def func( ...... ): #默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。'''函数说明 #文档字符串,见下面说明,python有潜规则'''...... #进入函数提后,会有一个存储函数局部变量的新符号表#变量的查找首先会在这个局部符号表中查找,然后是外层局部符号表,#再是全局局部符号表,最后是内置名称符号表。有点类似Lua的环境表。return ...... #没有return值,就返回None
参数传递
def changeVal( arg ):#传入参数的过程:相当于生成一个新变量(指针),指向传入的变量指向的对象。#类比C++的指针传递,本质就是值传递,值就是对象的地址。arg = 2 #arg = &Number(2),改变的只是arg的指向。arg[0] = 1 #如果arg指向的对象可修改比如List,则通过arg可修改传入的对象#最终效果就是函数内部可修改传入的对象,但对象必须是可修改类型。return;num = 1 #void *num = &Number(1)lst = [1]changeVal(num) #void *arg = num,arg和num都指向Number(1)changeVal(lst) #void *arg = lst,arg和num都指向lst,通过arg修改了lst,num看起来也跟着改变。print(num) #输出:1
参数匹配
- key匹配
顺序匹配 ```python def fuckme(shit1, shit2):
python中,参数名字是实际意义的,准备的应该叫参数的key(关键字)。
关键字参数kwarg
key匹配:如传入的参数key为shit1,则值传入到第一个参数位置。
传入的参数如果有key,则后续都必须有key。
这种带key的参数,我们将关键字参数kwarg
位置参数
顺序匹配:默认匹配方式,没有key就按这种方式。
从shit1开始,从左往右依次填充,
注意一定是从shit1开始,也就是第一个参数开始。
pass
fuckme(1) #没有key,按顺序匹配 fuckme(shit1=1) #key为shit1,按key匹配 fuckme(shit3=1) #key为shit3,按key匹配,但没有找到,报错。 fuckme(shit1=1,2) #错误:后续都必须有key fuckme(1, shit1=1) #错误,shit1参数有多个值匹配。 fuckme(1, shit2=1) #正确
<a name="NBZyU"></a>## 默认参数规则和C++类似。```pythondef fuckme(shit1, shit2=2)#如果一个参数有默认值,则后续都必须有默认值#注意,一个函数的所有调用都共享一份默认值,见下面例子理解。pass;fuckme(1) #shit1=1,shit2=2fuckme(shit1=1) #shit1=1,shit2=2fuckme(1, 3) #shit1=1,shit2=3#shit2的[]将被所有函数调用共享def fuckme(shit1, shit2=[]):shit2.append(shit1)print(shit2)fuckme(1) #[1]fuckme(2) #[1, 2]fuckme(3) #[1, 2, 3]#如何不共享默认值?def fuckme(shit1, shit2=None):if shit2 is None:shit2 = [];shit2.append(shit1)
可变参数列表
*args
def fuckme(arg1..., *args, argn...):#args是一个列表/元组,存储的是位置参数,argn...可以没有,或者必须是kwarg关键字参数#*args相当于解包args,类似Lua的unpack一个table。for arg in var_list:passpassdef fuckme(*args):passfuckme( 10 )fuckme( 70, 60, 50 )
**kwargs
def fuckme(arg1..., **kwargs):#kwargs是一个dict字典,存储的是所有关键字参数,除了与已有形参匹配了的关键字参数。#可以和*args组合使用,*args必须在**kwargs的前面。for key in kwargs:print key, kwargs[key]################例子1def fuckme(shit1, shit2, **kwargs):print shit1, shit2print("-" * 10)for key in kwargs:print key, kwargs[key]fuckme(1, shit2=2,bitch=3,fuck=4);# 1, 2#-----------# bitch, 3# fuck, 4################例子2def fuckme(shit1, shit2, *args, **kwargs):print shit1, shit2print("-" * 10)for arg in args:print(arg)print("-" * 10)for key in kwargs:print key, kwargs[key]fuckme(1, 2, 3, 4, 5, 6, bitch=7, fucker=8)# 1, 2#-----------# 3, 4, 5, 6#-----------# bitch, 7# fucker, 8
解包参数列表:unpack
#unpack场景一:列表元组中的参数,转换成位置参数def unpack_arg(arg1, arg2, arg3):print(arg1, arg2, arg3)lst = [1, 2, 3]unpack_arg(*lst) #1, 2, 3#unpack场景二:字典中的参数,转换成关键字参数def unpack_arg(arg1, arg2, arg3):print(arg1, arg2, arg3)kwargs = { "arg3":3, "arg2":2, "arg1": 1}unpack_arg(**kwargs) #1, 2, 3
匿名函数(lambda)
lambda [arg1 [,arg2,.....argn]]:expression#expression必须是一个表达式,不是代码块。#且不能访问自有参数列表之外或全局命名空间里的参数。add = lambda arg1, arg2: arg1 + arg2add(1, 2)
文档字符串
def my_function():"""摘要描述 #摘要一般紧接在开头引号后面#摘要和详细描述之间最好空一行详细描述1... #详细描述最好有相同缩进详细描述2..."""passprint(my_function.__doc__)#Do nothing, but document it.## No, really, it doesn't do anything.
函数标注
def f(arg1: str, arg2: str = 'arg2') -> str:#冒号后面接一个表达式,表达式会被求值,值就是标注值。#尾置形式,表示返回值的类型。print("Annotations:", f.__annotations__) #字典,key为参数key,value为标注值print("Arguments:", ham, eggs)return ham + ' and ' + eggsf('arg1')#Annotations: {'arg1': <class 'str'>, 'return': <class 'str'>, 'arg2': <class 'str'>}#Arguments: arg1 arg2#'arg1 and arg2'
