*args和**kwargs用法
*的作用
拆开数列’list’的数值作为位置参数,并把这些位置参数传给函数’fun’来调用。
def fun(a,b,c):
print(a,b,c)
fun(1,2,3)
#输出 1 2 3
list=[1,2,3]
fun(*list)
#输出 1 2 3
*args的作用
它接收元组作为位置参数,而非是常见的参数列表。在这里,”args”是个元组。
def fun(*args):
print args
fun(13)
#输出(13,)
fun(11,93,43)
#输出(11,93,43)
**的作用
它unpack字典,并将字典中的数据项作为键值参数传给函数
def fun(a,b,c):
print(a,b,c)
fun(1,5,7)
#输出1 5 7
fun(a=1,b=5,c=7)
#输出1 5 7
d={'b':5,'c':7}
fun(1,**d)
#输出1 5 7
d={'c':3}
fun(1,4,**d)
#输出1 4 3
**kwargs的作用
用”**kwargs”定义函数,kwargs接收除常规参数列表职位的键值参数字典
def fun(a,**kwargs):
print(a,kwargs)
fun(1,b=4,c=5)
#输出1 {'c':5,'b':4}
fun(45,b=6,c=7,d=8)
#输出45 {'c':7,'b':6,'d':8}
def fun(a,**kwargs):
print("a is ",a)
print("b is ",kwargs['b'])
print("c is ",kwargs['c'])
fun(1,b=3,c=5)
#输出a is 1
b is 3
c is 5
fun(1,**{'b':2,'c':34})
#输出a is 1
b is 2
c is 34
装饰器用法
函数作变量
def hi(name="yasoob"):
return "hi"+name
print(hi())
#输出:'hi yasoob'
greet=hi
print(greet())
#输出:'hi yasoob'
函数做参数
def hi():
return "hi yasoob~"
def dosthbeforehi(func):
print("do sth before func")
print(func())
dosthbeforehi(hi)
#输出do sth before func
hi yasoob~
从函数中返回函数
def hi(name="yasoob"):
def greet():
return "now you are in the greet() function"
def welcome():
return "now you are in the welcome() function"
if name=="yasoob":
return greet
else:
return welcome
a=hi()
print(a)
#输出:<function greet at 0x7f2143c01500>
print(a())
#输出:now you are in the greet() function
在 if/else 语句中我们返回 greet 和 welcome,而不是 greet() 和 welcome()。为什么那样?这是因为当你把一对小括号放在后面,这个函数就会执行;然而如果你不放括号在它后面,那它可以被到处传递,并且可以赋值给别的变量而不去执行它。
装饰器详解
def decorator(func):
def wrap():
print("do sth before executing func()")
func()
print("do sth after executing func()")
return wrap
def function_requiring_decoration():
print("function which needs decoration")
function_requiring_decoration()
#输出:"function which needs decoration"
function_requiring_decoration=decorator(function_requiring_decoration)
function_requiring_decoration()
#输出:do sth before executing func()
function which needs decoration
do sth after executing func()
@decorator
def function_requiring_decoration():
print("function which needs decoration")
function_requiring_decoration()
#输出:do sth before executing func()
function which needs decoration
do sth after executing func()
print(function_requiring_decoration.__name__)
#输出:wrap
这并不是我们想要的!输出应该是"function_requiring_decoration"。这里的函数被wrap替代了。它重写了我们函数的名字和注释文档。幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上一个例子来使用functools.wraps:
from functoos import wraps
def decorator(func):
@wraps(func)
def wrap():
print("do sth before executing func()")
func()
print("do sth after executing func()")
return wrap
@decorator
def function_requiring_decoration():
print("function which needs decoration")
print(function_requiring_decoration.__name__)
#输出:function_requiring_decoration
使用场景
插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。
授权
from functools import wraps
def requires_auth(f):
@wraps(f)
def decorated(*args,**kwargs):
auth=request.authorization
if not auth or not check_auth(auth.username,auth.password):
authenticate()
return f(*args,**kwargs)
return decorated
日志
from functoos import wraps
def logit(func):
@wraps(func)
def with_logging(*args,**kwargs):
print(func.__name__+" was called ")
return func(*args,**kwargs)
return with_logging
@logit
def addition_func(x):
"""do some math."""
return x+x
result=addition_func(4)
#输出:addition_func was called
带参数的装饰器
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func);
@wraps(func)
def wrapped_function(*args,**kwargs):
log_string=func.__name__+" was called"
print(log_string)
#打开logfile,并写入内容
with open(logfile,'a')as opened_file:
#将日志打到指定的logfile
opened_file.write(log_string+'\n')
return func(*args,**kwargs)
return wrapped_function
return logging_decorator
@logit()
def myfunc1():
pass
myfunc1()
#输出:myfunc1 was called
现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串
@logit(logfile='func2.log')
def myfunc2():
pass
myfunc2()
#输出my func2 was called
现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串
装饰器类
from functools import wraps
class logit(object):
def __init__(self,logfile='out.log'):
self.logfile=logfile
def __call__(self,func):
@wraps(func)
def wrapped_function(*args,**kwargs):
log_string=func.__name__+" was called"
print(log_string)
#打开logfile,并写入内容
with open(logfile,'a')as opened_file:
#将日志打到指定的logfile
opened_file.write(log_string+'\n')
self.notify()
return func(*args,**kwargs)
return wrapped_function
def notify(self):
#logit只打日志,不做别的
pass
@logit()
def myfunc1():
pass
现在,我们给 logit 创建子类,来添加 email 的功能。
class email_logit(logit):
'''
一个logit的实现版本,可以在函数调用时发送email给管理员
'''
def __init__(self,email='admin@myproject.com',*args,**kwargs):
self.email=email
super(email_logit,self).__init__(*args,**kwargs)
def notify(self):
# 发送一封email到self.email
# 这里就不做实现了
pass
从现在起,@email_logit 将会和 @logit 产生同样的效果,但是在打日志的基础上,还会多发送一封邮件给管理员。