python传参和装饰器
2019-05-17 本文已影响0人
何赛艾慕
一. 位置参数与关键字参数
def say_hi(name,who):
print("{} say hi to {}".format(name,who))
say_hi("jose","bill") #正确
say_hi(who="bill","jose") #错误
say_hi(name="jose","bill") #错误
say_hi('bill',name="jose") #正确
结论很简单,有位置参数时,位置参数必须在关键字参数的前面,并且关键字参数之间不存在先后顺序。
二. *args和**kwarg
可变位置参数和可变关键字参数是不确定要向函数传参与否或者传几个参数时使用的:
def func(*args):
...
# func()
# func(a)
# func(a, b, c)
按照传参顺序生成元组,就像把几个位置参数打成包裹。
def func(**kwargs):
...
# func(a = 1)
# func(a = 1, b = 2)
按照传参顺序生成一个字典。也就是把可变关键字参数打成包裹。
def foo(x,*args,a=4,**kwargs): #使用默认参数时,注意默认参数的位置要在args之后kwargs之前
print(x)
print(a)
print(args)
print(kwargs)
foo(1,5,6,7,8,y=2,z=3) #调用函数,不修改默认参数
1 #x的值
4 #a的值
(5, 6, 7, 8) #*args的值
{'y': 2, 'z': 3} ##kwargs的值
三. 装饰器
听说装饰器必问?毕竟是在python中应用特别广泛的代表,今天好好研究一下。
首先要明确的是,装饰器本质上也是一个python函数,可以让其他函数在不需要做任何代码变动的前提下增加额外功能。一个简单的例子就是为函数增加他的名字。
def fun1(para):
print('abc')
print(fun1.__name__)
如果不仅仅有fun1,还有fun2,fun3我们统称fun,我们为每个函数都增加一个显示名字的方法,你肯定知道一个个加是不现实的,而且也很麻烦。可能你想到了创建一个新函数。
def log(fun):
print(fun.__name__)
fun()
但是这样的话其实也不可避免的改动了函数声明,比如原来使用fun1(para)就能完成的任务,现在要使用log(fun1(para))。
那么如果你有很多别的语言的学习经验,可能已经注意到了一点不同,那就是python的函数也可以当作普通的对象传递给另一个函数,有了这一点前提,装饰器就有了一席之地。
def log(func):
def real():
print("%s is running" % func.__name__)
return func()
return real
@log
def abc():
print('abc')
#abc = log(abc)
abc()
可以看到,装饰器与bar = log(bar)的作用实际上是一样的。
除了函数装饰器之外还有类装饰器,原理是一样的,只不过类装饰器中需要有一个“call”方法:
class log(object):
def __init__(self, func):
self._func = func
def __call__(self):
print ('abc')
self._func()
# @Foo
def abc():
print ('abc')
abc = log(abc)
abc()