Python-六、函数的应用

1、函数是什么

在Python中,函数不是数学函数那样看上去冰冷无聊的规则和公式,而是有实打实的、有自己作用的代码。

比如说当我们需要实现“打印”这个功能,会用到print();当我们需要实现“获取数据长度”这个功能,会用到len()。这些都是设定好了,可以直接拿过来就用的功能,这就叫做“组织好的代码”。

函数(Function)能实现的功能从简单到复杂,各式各样,但其本质是相通的:“喂”给函数一些数据,它就能内部消化,给你“吐”出你想要的东西。

这就像自动贩卖机,只不过贩卖机是喂点钱,吐出来一些吃的喝的用的东西;而Python函数则是喂各种各样的数据,吐出来各种各样的功能。

给函数输入数据,函数运算后输出结果

上图中函数后都带个小括号,小括号里用于放你输入的内容,这个内容就是“参数”,比如:

print('Hello World')

↑函数       ↑参数

函数的定义:函数是组织好的、可以重复使用的、用来实现单一功能的代码。

用贩卖机来打比方,贩卖机是设定好可以直接使用(组织好的),可以重复上架售卖不同的物品(重复使用),功能是卖东西(单一功能)。

而函数呢?以print()函数为例,它也是设定好可以直接使用(组织好的),不论你想打印什么参数都可以(重复使用),而print函数能实现的单一功能就是“打印”。

那么问题来了,贩卖机不一定有我们享要的东西,同理PYTHON自带的内置函数有限,那我们怎么通过编程,自定独一无二的函数呢?

2、定义和调用函数

2.1、定义函数

我们可以通过函数的语法来定义一个函数。

定义函数的语法

比如:

def greet(name):                  #def的意思是定义(define),greet是【函数名】,name是参数

    print(name+'早上好')        #函数(函数体)要实现的功能:打印出“name+早上好”这句话。

    return                               #函数内部一旦遇到return语句,就会停止执行并返回结果。

PS:没有return语句的函数,Python也会在末尾隐性地加上return None,即返回None值(return None可以简写为return)。所以我们经常可以省略这个return。

上面这段代码执行后,什么都没有,一片空白……那是因为我们只定义了函数,还没有调用它!

2.1、调用函数

函数咋调用?喊函数的名字就可以了!如下

def pika1():

    print('我最喜爱的神奇宝贝是皮卡丘')

#该函数没有参数,直接调用函数名。记得英文括号一定不能少

pika1()    #←←←←←这里就开始喊函数pika1的名字了

def pika2(name):

    print('我最喜爱的神奇宝贝是'+name)

#需要给参数name赋值,每次调用都可以给参数赋不同的值

pika2('皮卡丘')

pika2('喷火龙')

def pika3(name,person):

    print('我最喜爱的神奇宝贝是'+name)

    print('我最喜爱的驯兽师是'+person)

#需要给两个参数分别赋值,并用逗号隔开,否则会报错

pika3('卡比兽','小智')

函数的调用结果如下:

我最喜爱的神奇宝贝是皮卡丘

我最喜爱的神奇宝贝是皮卡丘

我最喜爱的神奇宝贝是喷火龙

我最喜爱的神奇宝贝是卡比兽

我最喜爱的驯兽师是小智

函数的调用关键是:弄清楚这个函数有多少个参数,如何给参数赋值,这个过程在函数里叫做参数的传递(pass)。

函数能将复杂的语句和功能统一封装进一个函数名里,调用者只需明白函数能实现什么,根据需要传递参数即可。

扩展,tree()函数打印圣诞树:

def tree(Height):

    print('Merry Christmas!')

    for i in range(Height):

        print((Height-i)*2*' '+'o'+ i*'~x~o')

        print(((Height-i)*2-1)*' '+(i*2+1)*'/'+'|'+(i*2+1)*'\\')

tree(6) #通过对tree函数输入height参数,即可生成圣诞树,我们以6层为例

输出结果:


6层圣诞树

3、函数重要概念

3.1、参数类型

主要的参数类型有:位置参数、默认参数、不定长参数。我们用一个案例把这些参数串起来。

假设有一家深夜食堂,顾客可以任意点菜。但因为人手不足,所以只能为每个人提供一份开胃菜和一份主食。如果写成函数的形式,这个函数就会有两个参数。

(开胃菜和主食的英文分别是appetizer和course)

def menu(appetizer,course):

    print('一份开胃菜:'+appetizer)

    print('一份主食:'+course+'\n')

#还记得转义字符\n吧,表示换行

menu('牛肉拉面','话梅花生')

menu('话梅花生','牛肉拉面')

#如果采用下面这种形式传递,就不需要理会参数位置。

menu(course='牛肉拉面',appetizer='话梅花生')

运行结果:

第三个因为用的=赋值,所以按照函数的默认位置做输出

回到这个食堂的故事。经营了一阵子之后,为了吸引更多的人流,你决定给每个顾客免费送上一份甜品绿豆沙,这时候你就可以用到【默认参数】,注意:默认参数必须放在位置参数之后。

def menu(appetizer,course,dessert): #在函数里增加一个甜品就好啦

后来呢,盛夏来袭,你觉得卖烧烤是个不错的主意。但问题是每个人点的烤串数量都不同,你也不能限定死数量,这时候【不定长参数】就能派上用场,即不确定传递参数的数量。他的格式是一个星号*加上参数名。

def menu(*barbeque):

    print(barbeque)

menu('烤鸡翅','烤茄子','烤玉米')

#这几个值都会传递给参数barbeque


运行结果出来啦

看,输出结果是('烤鸡翅', '烤茄子', '烤玉米'),这种数据类型就跟元组(tuple)一样哦。

看,虽然我们只定义了一个参数,但是可以随便往参数里加东西哦!

现在,让我们开始点餐吧,用for循环向不定长参数里输入值(烧烤),并把前菜、主菜、甜点一起拼凑为一张菜单吧:

def menu(appetizer,course,*barbeque,dessert='熔岩巧克力'):

    print('开胃菜 '+appetizer)

    print('主菜 '+course)

    print('甜品 '+dessert)

    for i in barbeque:  #注意FOR循环与不定长参数

        print('烧烤 '+i)  #的用法,i就是这个不定长参数哦

menu('小红莓','生烤牛肉','熔岩巧克力++','烤鸡翅','烤猪劲肉','烤玉米')

输出结果

3.2、return的作用

return是返回值,当你输入参数给函数,函数就会返回一个值给你。

而print()函数本身比较特殊,它在屏幕上显示完相关的文本内容就没了,并不会返回一个值给我们。所以,它返回的是空值(None)。

在自定义函数的时候,我们就可以用return语句规定该函数要返回什么值给我们。带return语句的函数是这样的:

def niduoda(age):

    if age < 12:

        return '哈,是祖国的花朵啊'

    elif age < 25:

        return '哇,是小鲜肉呢'

    else:

        return '嗯,人生才刚刚开始'

print(niduoda(30))

在上例中,函数是互相嵌套的,niduoda()函数就被嵌套在print()函数里。那为什么在这个例子中,不直接用print,为啥还要用return呢?

因为我们在上面的立体中,要求把函数功能执行后,第一时间把参数打印出来。而在很多时候,当多个函数之间相互配合时,我们并不需要第一时间就将结果打印出来,而是需要将某个返回值先放着,等到需要的时候再做进一步的处理。

return语句-总结1:如果不是立即要对函数返回值做操作,那么可以使用return语句保留返回值。

来,让我们做个案例试试看。

在我们关于爱情的天真幻想中,我希望我的梦中情人拥有XXX的脸蛋和XXX的身材。

这个需求,需要我们做两点:一、分别定义两个函数,参数为人名,能够返回字符串'XXX的脸蛋'和'XXX的身材';二、将上述两个函数的返回值拼接在一起之后,再打印出来。请你先思考一下,再点击回车。

def face(name):

    return name + '的脸蛋'

def body(name):

    return name + '的身材'

print('我的梦中情人:'+face('李若彤') +' + ' + body('林志玲'))

print('我的梦中情人:'+face('新垣结衣) +' + ' + body(''长泽雅美))   #如要再打印,得再输入调用

所以更常见的做法是:再定义一个主函数main(),参数调用前两个函数的返回值。老师先给出代码,你可以琢磨一下,主要思考第5行和第6行代码。

def face(name):

    return name + '的脸蛋'

def body(name):

    return name + '的身材'

def main(dream_face,dream_body):

    return '我的梦中情人:' + face(dream_face) + ' + ' + body(dream_body)

#使用main函数以后,就只调用一次了~

print(main('李若彤','林志玲'))

print(main('新垣结衣','长泽雅美'))

这个代码有点绕,让我们做个图解:


函数与main函数

return语句-总结2:需要多次调用函数时,可以再定义一个主函数main(),调用非主函数的返回值。

现在,我们尝试用另外的方法来一次性返回这两个值:

def lover(name1,name2):

    face = name1 + '的脸蛋'

    body = name2 + '的身材'

    return face,body

a=lover('李若彤','林志玲')

print('我的梦中情人:'+a[0]+' + '+a[1])

一次性返回的两个值,是('李若彤的脸蛋', '林志玲的身材')这样一个元组。

Python语言中的函数返回值可以是多个,而其他语言都不行,这是Python相比其他语言的简便和灵活之处。一次接受多个返回值的数据类型就是元组。

return语句-总结3:python的函数返回值可以是多个,多个返回值的数据类型是元组(tuple)。

return语句-总结4:没有return语句的函数会默认返回None值。

示例:

def fun():

    a ='I am coding'

print(fun())

运行结果:None

return语句-总结5:一旦函数内部遇到return语句,就会停止执行并返回结果。

示例:

def fun():

  return 'I am coding.'

  return 'I am not coding.'

print(fun())

运行结果:I am coding.

3.3 巩固练习

习题:

一、定义一个带有两个参数的函数,函数的功能是返回两个参数中较大的那个值;二、调用函数,将99的平方和8888赋值给参数,并将较大值打印出来。

思路:

1、定义存储两个参数的函数,函数将比较这两个参数;

2、返回较大的值。

代码:

def bigdata(num1,num2):

    if num1 > num2:

        return num1

    else:

        return num2

print(bigdata(99**2,8888))

3.4、变量作用域

当我们定义一个函数的时候,很重要的事情就是理解函数中变量的作用域。

第一点:在一个函数内定义的变量仅能在函数内部使用(局部作用域),它们被称作【局部变量】。

第二点:在所有函数之外赋值的变量,可以在程序的任何位置使用(全局作用域),它们叫【全局变量】。

例:

x=99 #全局变量x

def num():

    x=88 #局部变量x

    print(x)

num()

#打印局部变量x

print(x)

#打印全局变量x

因为x=99是在函数外赋值的,所以第一个变量x是全局变量;x=88是在函数内赋值的,所以第二个变量x是局部变量。

局部和全局变量

我们可以将定义的函数想象成一个私人房间,所以里面存数据的容器(变量)是私有的,只能在个人的房间里使用;而在函数外存数据的变量是公用的,没有使用限制。

局部作用域和全局作用域

我们来看看容易新手容易踩的坑:

def egg(): 

    quantity = 108

egg()

print(quantity) 

运行结果:NameError: name 'quantity' is not defined,这句话翻译成中文就是:变量quantity并没有被定义。其实,我们定义了,只不过是在函数egg() 内定义的,所以这是个局部变量。但问题是我们不能在定义的函数egg() 外面,也就是不能在全局作用域中使用这个局部变量。

怎么办呢?其实也很简单,就像私人房间里的人可以使自由使用公共区域的物品,在函数内部的局部作用域,是可以访问全局变量的。

quantity = 108     #定义变量quantity,这不是在我们定义的函数内的,所以是全局变量。

def egg():

  print(quantity)    #函数内的功能是打印变量quantity

egg()                   #调用这个函数

记住一句话,当变量处于被定义的函数内时,就是局部变量,只能在这个函数内被访问;当变量处于被定义的函数外时,就是全局变量,可以在程序中的任何位置被访问。

如果你非要将局部变量变成全局变量,就像把私人房间的东西挪到公共区域,可不可以呢?Python也是能够满足你的,只不过要用到一种新的语句global语句,就像这样子:

def egg():

    global quantity      #global语句将变量quantity声明为全局变量

    quantity = 108

egg()

print(quantity)

3.5、练习 1-Hello Kitty抽奖

练习目标:

我们会通过今天的项目练习,学习函数的封装和调用。 

练习要求:

我们已经有一个hellokitty抽奖器,现在,请你把这个程序封装成一个新的函数。

运行抽奖器的代码:

# 查看注释,运行代码。

import random

import time

# 用random函数在列表中随机抽奖,列表中只有3位候选者。

luckylist = ['海绵宝宝','派大星','章鱼哥']

# random模块中有个随机选取一个元素的方法:random.choice()。

a = random.choice(luckylist)  # 从3个人中随机选取1个人。

print('开奖倒计时',3)

time.sleep(1)  # 调用time模块,控制打印内容出现的时间

print('开奖倒计时',2)

time.sleep(1)

print('开奖倒计时',1)

time.sleep(1)

# 使用三引号打印hellokitty的头像

image = '''

/\_)o<

|      \\

| O . O|

\_____/

'''

print(image)  # ……

print('恭喜'+a+'中奖!')  # 使用print函数打印幸运者名单

#我了个去,这排版变这样子,HelloKitty都扭曲了,太难看了,要在程序里跑才能正常。

思路:

这段代码中,时间调用模块是可以用通过for循环调用函数实现的,来试试看吧。

# 查看注释,运行代码。

import random

import time

# 用random函数在列表中随机抽奖,列表中只有3位候选者。

def main(a,b,c):

    luckylist = [a,b,c]

    a = random.choice(luckylist) # 从3个人中随机选取1个人。

# random模块中有个随机选取一个元素的方法:random.choice()。

    x = 4

    for i in range(1,x):

        y = x - i

        print('开奖倒计时',y)

        time.sleep(1) # 调用time模块,控制打印内容出现的时间

# 使用三引号打印hellokitty的头像

    image = '''

    /\_)o<

    |      \\

    | O . O|

    \_____/

    '''

    print(image)

    print('恭喜'+a+'中奖!')  # 使用print函数打印幸运者名单

main('张三','李四','王五')

抽奖函数封装练习

3.6、练习2-打印52张扑克牌

练习目标

通过这个练习,你可以通过Python优雅地生成一副扑克牌。 

练习要求

我们将通过这个练习,简单地复习一下return的用法。另外,这个练习也要求你能够快速地学习新知识并将其运用出来。新知识有3个:一种新的列表生成方式、extend 的新用法和列表生成式。

# 知识1:一种新的列表生成方式

num1 = [1,2,3,4,5]  # 想一想,如果用这个方法生成一个1-100的列表……

num2 = list(range(1,6))

print(num1)

print(num2)

# 知识2:extend 的新用法

num2.extend(['ABCDE'])

num2.extend('ABCDE')  # extend后面是列表的话会将其合并,后面是字符串的话会将每个字符当成一个列表中的元素。

print(num2)

# 知识点3:列表生成式

list1 = [i for i in range(3)]  # 规定列表中元素的范围

print(list1)

list2 = [m+n for m in ['天字', '地字'] for n in '一二']  # 列表元素可以是组合,分别规定范围。

print(list2)

list3 = [n*n for n in range(1,11) if n % 3 == 0]  # 元素既可规定范围,也可附加条件。

print(list3)

通过新知识点,补全函数cards()。

#每张扑克牌的展现形式是一个元组:(花色,大小)

# 函数会返回一个扑克牌列表,里面有52个元组(将花色和数字分开),对应52张牌。(代码量5行左右)

思路:

1、扑克牌有52张,10以上是JOKA,就是每组13张。则需要预置元组1存储花色:黑红梅方;通过数字取值范围+预置分别定义并组合为元组2存储牌的大小:2<10<JQKA。

2、循环遍历元组1与元组2,将数据返还给调用者,调用者将返还的数据打印出来。

def cards():

    # 在下方补充4行代码(左右),让函数下方的打印函数打印出52张扑克牌。每张扑克牌的展现形式是元组(花色,大小)。

    cards_suit =['黑桃','红桃','梅花','方块']        #存储好花色

    cards_range = list(range(2,11))                 #存储好2~10的牌号

    cards_range.extend('JQKA')                     #把JQKA加入牌号里

    return [m+n for m in cards_suit for n in list(map(str,cards_range))]    

    #把牌号组合好返还,但cards_range中有一部分是数字,所以组合前要转为str

print(cards())  # 将函数的返回值打印出来

打印52张扑克牌
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容