标签:toc 直接 进入 中国 __call 打印 obj 函数 个数
1. 先定义一个装饰器
2. 再定义你的业务函数或者类
3. 最后把装饰器扣在这个函数头上
# 定义装饰器
def decorator(func):
def wrapper(*args, **kw):
return func()
return wrapper
# 定义业务函数并进行装饰
@decorator
def function():
print("hello, decorator")
def logger(func):
def wrapper(*args, **kw):
print(‘我准备开始执行了:{} 函数了:‘.format(func.__name__))
# 真正执行的是这行。
func(*args, **kw)
print(‘我执行完啦。‘)
return wrapper
# 业务函数,计算两个数之和
@logger
def add(x, y):
print(‘{} + {} = {}‘.format(x, y, x+y))
add(200, 50)
# 执行结果
我准备开始执行了: add 函数了:
200 + 50 = 250
我执行完啦
def say_hello(country):
def wrapper(func):
def deco(*args, **kwargs):
if country == "china":
print("你好!")
elif country == "america"
print("hello.")
else:
return
# 真正执行函数的地方
func(*args, **kwargs)
return deco
return wrapper
# 小明,中国人
@say_hello("china")
def xiaoming()
pass
# jack,美国人
@say_hello("america")
def jack()
pass
xiaoming()
print("------------")
jack()
# 执行结果
你好!
------------
hello.
基于类装饰器的实现,必须实现__call__
和__init__
两个内置函数
__init__
:接收被装饰函数
__call__
:实现装饰逻辑
class logger(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("[INFO]:the function {func}() is running...".format(func=self.func__name__))
return self.func(*args, **kwargs)
@logger
def say(something):
print("say {}!".format(something))
say("hello")
# 执行结果
[INFO]:the function say() is running...
say hello!
不带参数的,只能打印INFO级别的日志,正常情况下,我们还需要打印DEBUG WARNING等级别的日志
__init__
:不再接收被装饰函数,而是接收传入参数
__call__
:接收被装饰函数,实现装饰逻辑
class logger(object):
def __init__(self, level=‘INFO‘):
self.level = level
def __call__(self, func): # 接受函数
def wrapper(*args, **kwargs):
print("[{level}]:the function {func}() is running...".format(level=self.level, func=func.__name__))
func(*args, **kwargs)
return wrapper # 返回函数
@logger(level=‘WARNING‘)
def say(something):
print("say {}!".format(something))
say("hello")
# 执行结果
[WARNING]: the function say() is running...
say hello
绝大多数装饰器都是基于函数和闭包实现de,但这并非制造装饰器的唯一方式.
Python对某个对象是否能通过装饰器(@decorator)形式使用只有一个要求:decorator必须是一个"可被调用(callable)的对象".
对于callable对象,最熟悉的就是函数.除函数外,类也可以是callable对象,只要实现了__call__
函数。
还有偏函数也是callable对象
DelayFunc是一个实现了__call__
的类,delay返回一个偏函数,在这里delay就可以做为一个装饰器.
import time
import functools
class DelayFunc:
def __init__(self, duration, func):
self.duration = duration
self.func = func
def __call__(self, *args, **kwargs):
print(f‘Wait for {self.duration} seconds...‘)
time.sleep(self.duration)
return self.func(*args, **kwargs)
def eager_call(self, *args, **kwargs):
print(‘Call without delay‘)
return self.func(*args, **kwargs)
def delay(duration):
"""
装饰器:推迟某个执行函数的执行.
同时提供 .eager_call 方法立即执行
"""
# 为了避免定义额外函数,
# 直接使用 functools.partial 帮助构造DelayFunc 实例
return functools.partial(DelayFunc, duration)
@delay(duration=2)
def add(a, b):
return a + b
print(add)
print(add(2, 4))
print(add.func)
# 执行结果
# add变成了Delay的实例
# <__main__.DelayFunc object at 0x7f744fd58470>
# 直接调用实例,进入__call__
# Wait for 2 seconds...
# 6
# 实现实例方法
# <function add at 0x7f744fd42d08>
标签:toc 直接 进入 中国 __call 打印 obj 函数 个数
原文地址:https://www.cnblogs.com/failan/p/14164534.html