小白必看的Python函数讲解

定义函数
我们通过斐波那契数列来理解定义函数
>>>deffib(n):#将斐波那契数列打印到n ..."""将斐波那契数列打印到n""" ...a,b=0,1 ...whilea<n: ...print(a,end='') ...a,b=b,a+b ...print() ... >>>#调用上述定义的函数 ...fib(2000) 011235813213455891442333776109871597
关键字 def 介绍了函数定义 。后面必须跟随函数的名称和一系列用括号包裹的参数。构成函数体的句子从下一行开始,必须缩进。
函数体的第一句话可以是字符串常量,字符串常量是函数的文档字符串,也可以是 docstring ,有许多工具可用于在线或打印文档的自动生成,或允许用户在代码中互动浏览文档;在代码中写文档字符串是一个更好的实践,所以请养成写文档字符串的习惯。
函数的执行引入了一个新的符号表,用于存储函数的局部变量。更准确地说,函数中的所有变量赋值都将存储在本局部符号表中;因此,在查找变量引用时,首先查找局部符号表,然后查找封闭函数的局部符号表,然后查找全局符号表,最后查找内置名称表。因此,虽然函数中可能引用全局变量,但函数中不能直接赋予全局变量(除非使用) global 定义一个变量的句子)
当函数被调用时,函数参数被引入局部符号表;因此,参数是通过的 按值传递 传递的方式(此值表示一个对象 引用 ,而不是对象的值)。[1] 在一个函数中调用另一个函数时,将为此次调用创建新的局部符号表。
函数定义将在当前符号表中引入函数的名称。该函数名称对应值的类型将被解释器解释为用户定义的函数。该值可以赋予另一个名称,并可以作为函数使用。这是一种常用的重命名机制:
>>>fib <functionfibat10042ed> >>>f=fib >>>f(100) 01123581321345589
默认参数值
最常用的形式是为一个或多个参数指定默认值。这样,功能就可以少于其定义的参数。例如:
defask_ok(prompt,retries=4,reminder='Pleasetryagain!'):
whileTrue:
ok=input(prompt)
ifokin('y','ye','yes'):
returnTrue
ifokin('n','no','nop','nope'):
returnFalse
retries=retries-1
ifretries<0:
raiseValueError('invaliduserresponse')
print(reminder)该函数可以有几种不同的调用方法:
只指定强制参数
参数: ask_ok('Do you really want to quit?')
提供可选参数
参数: ask_ok('OK to overwrite the file?', 2)
或者给出所有参数
参数: ask_ok('OK to overwrite the file?', 2, 'Come on, onlyyes or no!')
顺便说一句,上面的例子也提到了 in 关键字。它用于测试一个特定值是否在一个序列中。
在定义函数时,默认值是 “在定义过程中” (defining )(如果函数参数的默认值是变量,则应根据函数定义前的变量值确定参数的默认值), 所以,
i=5 deff(arg=i): print(arg) i=6 f()
会打印5.
关键字参数
形如 kwarg=value 形式参数为 关键字参数。例如,以下函数:
defparrot(voltage,state='astiff',action='voom',type='NorwegianBlue'):
print("--Thisparrotwouldn't",action,end='')
print("ifyouput",voltage,"voltsthroughit.")
print("--Lovelyplumage,the",type)
print("--It's",state,"!")接收必选参数 (voltage) 以及三个可选参数(state,action, 和type)。以下方式调用此函数:
parrot(1000)#一个位置参数
parrot(voltage=1000)#关键字参数
parrot(voltage=1000000,action='VOOOOOM')#两个关键字参数
parrot(action='VOOOOOM',voltage=1000000)#两个关键字参数
parrot('amillion','bereftoflife','jump')#3个位置参数
parrot('athousand',state='pushingupthedaisies')#一个位置参数,一个关键字参数但以下调用方法均无效:
parrot()#缺少必选参数 parrot(voltage=5.0,'dead')#关键字参数背后的非关键字参数 parrot(110,voltage=220#同一参数重复赋值 parrot(actor='JohnCleese')#未知关键字参数
在函数调用中,关键字参数必须遵循参数位置。传输的所有关键字参数必须与函数接受的参数之一匹配。(例如,actor不是函数parot中的有效参数),它们的顺序并不重要。这也包括那些不必要的参数 (比如parot(voltage=1000)同样有效)。如果没有参数,可以多次获得一个值。下一个例子是失败的:
>>>deffunction(a): ...pass ... >>>function(0,a=0) Traceback(mostrecentcalllast): File"<stdin>",line1,in<module> TypeError:function()gotmultiplevaluesforkeywordargument'a'
当最终有**name形式的参数时,它最终会收到一个字典(见Mapping) Types --- dict) 包括所有与形式参数相对应的关键字参数。这可以与* 结合name形式的形式参数(下一节描述),接收包含正式参数列表以外的位置参数的元组。 (*name必须出现在**name之前。) 例如,如果我们定义以下函数:
defcheeseshop(kind,*arguments,**keywords):
print("--Doyouhaveany",kind,"?")
print("--I'msorry,we'realloutof",kind)
forarginarguments:
print(arg)
print("-"*40)
forkwinkeywords:
print(kw,":",keywords[kw])它可以这样调用:
cheeseshop("Limburger","It'sveryrunny,sir.",
"It'sreallyvery,VERYrunny,sir.",
shopkeeper="MichaelPalin",
client="JohnCleese",
sketch="CheeseShopSketch")可变参数
最后,指定参数最不常用的选项是可变参数。这些参数将组装成一个元组 (参见 元组和序列) 。零或多个正常参数可能出现在可变参数之前。
defwrite_multiple_items(file,separator,*args): file.write(separator.join(args))
分离参数列表
当输入参数以列表或元组的形式调用单独的位置参数时,就会出现与上述相反的情况。例如,内置函数 range() 需要独立 start 和 stop 参数。如果输入不是独立的参数,则需要使用 * 操作符从列表或元组中提取参数:
>>>list(range(3)6)#正常使用参数调用函数 [3,4,5] >>>args=[3,6] >>>list(range(*args))#从列表中提取参数并调用函数 [3,4,5]
Lambda 表达式
我们能用 lambda关键字创建小型匿名函数。该函数将返回其两个参数的和:lambda a,b:a + b。可用于任何需要函数对象的场合 Lambda 函数。它们仅限于语法上的单一表达式。从语义上讲,它们只是定义普通函数的语法糖。类似于嵌套函数的定义,lambda 函数可以从包含它的上下文中引用变量:
>>>defmake_incrementor(n): ...returnlambdax:x+n ... >>>f=make_incrementor(42) >>>f(0) 42 >>>f(1) 4
