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++类似。
```python
def fuckme(shit1, shit2=2)
#如果一个参数有默认值,则后续都必须有默认值
#注意,一个函数的所有调用都共享一份默认值,见下面例子理解。
pass;
fuckme(1) #shit1=1,shit2=2
fuckme(shit1=1) #shit1=1,shit2=2
fuckme(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:
pass
pass
def fuckme(*args):
pass
fuckme( 10 )
fuckme( 70, 60, 50 )
**kwargs
def fuckme(arg1..., **kwargs):
#kwargs是一个dict字典,存储的是所有关键字参数,除了与已有形参匹配了的关键字参数。
#可以和*args组合使用,*args必须在**kwargs的前面。
for key in kwargs:
print key, kwargs[key]
################例子1
def fuckme(shit1, shit2, **kwargs):
print shit1, shit2
print("-" * 10)
for key in kwargs:
print key, kwargs[key]
fuckme(1, shit2=2,bitch=3,fuck=4);
# 1, 2
#-----------
# bitch, 3
# fuck, 4
################例子2
def fuckme(shit1, shit2, *args, **kwargs):
print shit1, shit2
print("-" * 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 + arg2
add(1, 2)
文档字符串
def my_function():
"""摘要描述 #摘要一般紧接在开头引号后面
#摘要和详细描述之间最好空一行
详细描述1... #详细描述最好有相同缩进
详细描述2...
"""
pass
print(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 ' + eggs
f('arg1')
#Annotations: {'arg1': <class 'str'>, 'return': <class 'str'>, 'arg2': <class 'str'>}
#Arguments: arg1 arg2
#'arg1 and arg2'