接下来看字典解构的例子:
In[27]: d = {'a': 1, 'b': 2, 'c': 3} In[28]: fn(**d) 1 2 3 # **可以把字典解构成关键字参数参数解构发生在函数调用时。解构的时候,线性结构的解构是位置参数,字典解构是关键字参数。
传参的顺序:位置参数,线性结构解构;关键字参数,字典解构。尽量的少的同时使用两种解构,除非你真的知道在做什么。
In[29]: def fn(a, b, c, d): ...: print(a, b, c, d) ...: In[30]: fn(0, *[2], c=1, **{'d': 3}) 0 2 1 3 9. 参数槽(keyword-only参数)Python3中引入的。
def fn(a, b, c): print(a, b, c) fn(a=1, b=2, c=3)如果要强制传入的参数为关键字参数:
def fn(*, a, b, c): print(a, b, c) >>> fn(1, 2, 3) Traceback (most recent call last): File "<pyshell#17>", line 1, in <module> fn(1, 2, 3) TypeError: fn() takes 0 positional arguments but 3 were given >>> fn(a=1, b=2, c=3) 1 2 3 # *之后的参数,必须以关键字参数的形式传递,称之为参数槽。参数槽通常和默认参数搭配使用。
>>> def fn(a, b, *, x, y): print(a, b) print(x, y) >>> fn(1, 2, 3, 4) Traceback (most recent call last): File "<pyshell#23>", line 1, in <module> fn(1, 2, 3, 4) TypeError: fn() takes 2 positional arguments but 4 were given >>> fn(1, 2, x=3, y=4) 1 2 3 4 >>> fn(1, 2, **{'x': 3, 'y': 4}) 1 2 3 4 def fn(a, b, *): print(a, b) def fn(a, b, *): ... print(a, b) File "<stdin>", line 1 SyntaxError: named arguments must follow bare *几个例子:
def fn01(*, x=1, y=5): print(x) print(y) >>> fn01() 1 5 def fn02(x=1, *, y): print(x) print(y) >>> fn02(y=3) 1 3参数槽之坑:
*之后必须有参数
非命名参数有默认值时,命名参数可以没有默认值
默认参数应该在每段参数的最后
使用参数槽时,不能使用可变位置参数,可变关键之参数必须放在命名参数之后
三、高级用法1. 递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
def fact(n): if n==1: return 1 return n*fact(n-1)使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
2. 匿名函数 lambda
python 使用 lambda 来创建匿名函数。
lambda只是一个表达式,函数体比def简单很多。
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda函数拥有自己的名字空间,且不能访问自有参数列表之外或全局名字空间里的参数。
虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
fib = lambda n,x=0,y=1:x if not n else fib(n-1,y,x+y) print(fib(20))3. Python函数中的多态