python相关(装饰器)

*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 产生同样的效果,但是在打日志的基础上,还会多发送一封邮件给管理员。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值