python的def语句实际上是一个可执行的语句:当它运行的时候,它会创建一个新的函数对象并将其赋值给一个变量名。因为它是一个语句,一个def可以出现在任一语句可以出现的地方。
View Code
1 if test: 2 def func(): 3 pass 4 else: 5 def func(): 6 pass
python的return语句可以在函数主体中的任何地方出现。它表示函数调用的结束,并将结果返回至函数调用处。return语句是可选的,如果它没有出现,那么函数将会在控制流执行完函数主体时结束。一个没有返回值的函数自动返回了non对象。
命名空间,又称为作用域
内嵌的模块是全局作用域。每一个模块都是一个全局作用域
全局作用域的作用范围仅限于单个文件
每次对函数的调用都创建了一个新的本地作用域
赋值的变量名除非声明为全局变量或非本地变量,否则均为本地变量
所有其他的变量名都可以归纳为本地、全局或者内置的
变量名解析:LEGB原则
本地作用域
上层结构中的def或lambda的本地作用域(当函数中嵌套函数才需要考虑)
全局作用域
内置作用域
nonlocal,允许对嵌套的函数作用域中的名称赋值(本地作用域能对上层作用域的变量赋值)
函数参数匹配模型
位置:从左到右进行匹配
关键字参数:通过关键字进行匹配
默认参数:为没有传入值的参数定义参数值
可变参数:收集任意多基于位置或关键字的参数
可变参数解包:传递任意多的基于位置或关键字的参数
keyword-only参数:参数必须按照名称传递
在函数调用中,参数必须以此顺序出现:任何位置参数(value),后面跟着关键字参数(name=value)和*sequence组合,再然后是**dict
在函数头部,参数必须以此顺序出现:任何一般参数(name),默认参数(name=value),如果有的话,后面是*name(python3中*)的形式,后面紧跟着任何name或name=value keyword-only参数(python3中),后面跟着**name
*args收集不匹配的位置参数,将它放到一个元组中,并将这个元组赋值给变量args
**args只对关键字有效(name=value),将这些关键字参数传递给一个新的字典,能够使用键或迭代。
1 #!/usr/bin/env python3 2 3 def func(a, b, c): 4 print(a, b, c) 5 func(c=3, b=2, a=1) # 关键字参数 6 func(1, c=3, b=2) #关键字参数 7 8 def func1(a, b=2, c=3): 9 print(a, b, c) 10 11 func1(1) # 默认参数,如果不给b和c赋值,则会赋默认值。 12 func1(1, 4) # 如果传两个参数,则只有C获得默认值。 13 14 # 位置参数 15 def f(*args): 16 print(args) 17 ''' 18 当这个函数调用时,python将所有位置相关的参数收集到一个新的元组中,并 19 将这个元组赋值给args,因为它是一个元组对象,它能够通过索引或for循环 20 中进行步进。 21 ''' 22 f(1, 2) 23 24 # ××特性类似,但只能通过关键字传参。将这些关键字参数传递给一个新的字典。 25 # 之后可以通过键来访问字典。 26 def f1(**args): 27 print(args['a'], args['b']) 28 29 f1(a=1, b=2) 30 31 # 解包参数 32 def f2(a, b, c, d): 33 print(a, b, c, d) 34 # 我们能通过一个元组给一个函数传递四个参数(×语句),它会解包参数。 35 args = (1, 2, 3, 4) 36 f2(*args) 37 38 # 相似的,**会以键/值对的形式解包一个字典,使其成为关键字参数 39 40 args= {'a':1, 'b':2, 'c':3, 'd':4} 41 f2(**args) 42 43 # 另外,在调用函数的过程中,可以通过灵活的方式混合普通参数。 44 f2(*(1,2),**{'d':4, 'c':3}) 45 f2(1,*(2,),**{'d':4, 'c':3})
keywords-only:def f(a,*,c),*后面的参数只接收关键字参数,def f(a,*b,c),a可能按位置或名称接收参数,b接收任意额外的参数,c只能通过关键字接收参数
View Code
''' 带有默认值的keyworld-only参数都是可选的,但是,那些没有默认值的keyworld-only 参数真正变成了函数必须的keyworld-only参数 ''' def f3(a, *b, c, d='spam'): print(a, b, c, d) f3(1,2,3,4,c=5) # ---> 1 (2, 3, 4) 5 spam f3(1,2,3,d=4) # --> error
匿名函数lambda
一般形式:关键字Lambda后一个或多个参数,紧跟一个冒号,之后是一个表达式。
lambda是一个表达式,而不是一个语句
lambda的主体是一个单一的表达式,而不是一个代码块
map是lambda通常出现的地方之一
filter根据函数过滤一些元素,将函数运用到迭代器中的每个元素
reduce对每对元素都应用函数并运行到最后结果,它不是迭代器,返回的是单个结果
基于某一函数过滤一些元素:filter
对每对元素都应用函数并运行到最后结果:reduce
print (reduce((lambda x,y:x-y),[10,9,6])):每一步,reduce都传递了当前的差及下一个元素,传递给lambda。
由于函数名是一个函数对象的引用,我们可以把空上对象赋给其他的名称并且调用它
View Code
我们还可以通过dict(func)来查看函数的属性,也可以向函数添加新的属性
View Code
def echo(msg): print(msg) f = echo f('hello world!') # --->hello world
def echo(msg): print(msg) f = echo f('hello world!') # --->hello world echo.handles="button" echo.handles # ---> button