python—装饰器
一、装饰器的定义
装饰他人的器具,在不修改被装饰对象的源代码,不修改被修饰对象的调用方式,为被装饰对象添加上新功能。
利用装饰器(decorator),可在不侵入内部实现,甚至在不之情的情况下,插入扩展逻辑。
利用装饰器功能,我们可以编写各种辅助开发工具,完成诸如调用跟踪、性能测试、内存检测等任务。当然,更多的时候用于模式设计,改善代码结构
二、装饰器的实现
1、不带参数装饰器
def login(func):
def inner():
your_name = input("name:")
your_password = input("password:")
if your_name == "ways" and your_password == "123":
func()
# return func() 如果被装饰的函数有返回值,则需要返回
else:
print("warning.....")
return inner
def home():
print("i am home")
def bbs():
print("i am bbs")
# 1.执行login函数,并将 @login 下面的 函数 作为login函数的参数,即:@w1 等价于 login(chat)
# 所以,内部就会去执行:
# def inner:
# #验证
# return chat() # func是参数,此时 func 等于 f1
# return inner # 返回的 inner,inner代表的是函数,非执行函数
# 其实就是将原来的 f1 函数塞进另外一个函数中
# 2.将执行完的 loign 函数返回值赋值给@login下面的函数的函数名chat
@login
def chat():
print("i am chat")
chat = login(chat)
chat()
2、装饰的的函数有参数
def login(func):
def inner(*arg,**kwargs):
your_name = input("name:")
your_password = input("password:")
if your_name == "ways" and your_password == "123":
func(*arg,**kwargs)
# return func(*arg,**kwargs) 如果被装饰的函数有返回值,则需要返回
else:
print("warning.....")
return inner
def home():
print("i am home")
def bbs():
print("i am bbs")
@login
def chat(style):
print("i am chat",style)
chat("我是聊天室")
3、装饰器带参数
def login(type):
def outter(func):
def inner(*arg,**kwargs):
if type == "wx":
print("我是bbs")
else:
print("我是chat")
your_name = input("name:")
your_password = input("password:")
if your_name == "ways" and your_password == "123":
func(*arg,**kwargs)
# return func(*arg,**kwargs) 如果被装饰的函数有返回值,则需要返回
else:
print("warning.....")
return inner
return outter
def home():
print("i am home")
@login("wx")
def bbs():
print("i am bbs")
@login("qq") #等价于 1,xx = login("qq") 其实就是outter 2,xx(chat)赋值给chat
def chat(style):
print("i am chat",style)
chat("我是聊天室")
bbs()
4、基于类的装饰器
在利用类定义装饰器时,我们用到了两个魔法方法。
__init__():初始化方法,设置实例的相关属性,用于初始化一个实例对象,它接收一个函数作为参数,也就是被装饰的函数。
__call()__:让一个实例对象可调用,就像函数调用一样,在调用被装饰函数时被调用,当一个类实现__call__方法时,这个类的实例就会变成可调用对象,让对象可以像函数那样调用。
# Author:ways
class Person:
"""
不带参数的类装饰器
"""
def __init__(self, fn): # 形参fn 用来接收函数名:hh
self.fn = fn
print(self.fn)
def __call__(self, *args, **kwargs):
print(*args, **kwargs)
print("函数执行前,我执行了")
return self.fn(*args, **kwargs)
print("函数执行后,我执行了")
@Person
def hh(x, y):
print(x+y)
hh(1, 2)
class Logging:
"""
带参数的类装饰器
"""
def __init__(self, level="INFO"): # 形参level,用来接收带参数装饰器的参数
self.level = level
def __call__(self, func):
def wrapper(*args, **kwargs):
if self.level == "INFO":
print("写正常日志")
elif self.level == "DEBUG":
print("写错误日志")
return func(*args, **kwargs)
return wrapper
@Logging("DEBUG")
def my_sum(x, y):
print(x+y)
@Logging()
def my_subtraction(x,y):
print(x-y)
my_sum(1, 2)
my_subtraction(1,2)
三、装饰器的小例子
1、装饰器装饰类中的方法
def my_warpper(func):
def wrapper(self,*args, **kwargs): # 传入self, 可以调用类中的方法和属性
print(self.name)
func(self,*args,**kwargs)
return wrapper
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@my_warpper
def print_info(self):
print("%s:%s" % (self.name, self.age))
p = Person("ways",13)
p.print_info()
浙公网安备 33010602011771号