实践是检验真理的唯一标准:拷贝到pycharm一试便知。
.
一、__call__使用
1、callable(对象) 判断对象是否可调用:==> 调用 函数() 对象()
callable() 进入函数内部查看,本质是判断类是否拥有__call__方法。
2、实现类创建出来的实例对象可调用 def __call __(self, *args, **kwargs):
实例对象+() 会自动调用__call__方法
没用__call__
# 方法
def work():
pass
# 类
class TestClass:
pass
# callable(对象) 判断对象是否可调用:==> 调用 函数() 对象()
print('函数是可调用对象么?', callable(work))
print('类是可调用对象么?', callable(TestClass))
# 函数是可调用对象么? True
# 类是可调用对象么? True
# 创建实例对象
noCallObj = TestClass()
print('类创建的实例对象是可调用对象么?', callable(noCallObj))
# 类创建的实例对象是可调用对象么? False
# 类的实例对象加括号是调用,但调用会报错:
noCallObj()
# 报错 TypeError: 'TestClass' object is not callable
用了__call__
# 需求:实现类创建出来的实例对象可调用???
# 给类实现一个__call__方法
class Demo:
def __call__(self, *args, **kwargs):
print('Demo类__call__:实现对象可调用')
"""
:param args:
:param kwargs:
:return:
"""
print("----call---方法执行了")
# 需求:实现类创建出来的实例对象可调用???
obj = Demo()
print('添加了__call__方法的类,它的实例对象是可调用对象么?', callable(obj))
# 添加了__call__方法的类,它的实例对象是可调用对象么? True
# 类的实例对象加括号是调用,类添加了__call__方法,实例对象调用成功:
obj() # ===> obj.__call__
# Demo类__call__:实现对象可调用
# ----call---方法执行了
# 再掉一遍
obj()
# Demo类__call__:实现对象可调用
# ----call---方法执行了
.
二、通过__call__实现需求
通过__call__实现用类做装饰器
需求:通过类实现一个计时装饰器
1、装饰器不带参数 @CountTime
# -----------------1、装饰器不带参数 @CountTime-------------------------------
import time
# 1、装饰器不带参数 CountTime
class CountTime:
def __init__(self, func):
# func:是被装饰的函数,传入进来之后保存为func属性
self.func = func
def __call__(self, *args, **kwargs):
st = time.time()
# 调用原功能函数
res = self.func(*args, **kwargs)
et = time.time()
print("函数执行的耗时为:", et - st)
return res
@CountTime # ==> work = CountTime(work) # 实例化对象
def work(a, b):
print('这里是函数work')
time.sleep(2)
res_work = a + b
return res_work
work(1, 2)
# 这里是函数work
# 函数执行的耗时为: 2.0064079761505127
print('work(1, 2)执行结果:', work(1, 2))
# 这里是函数work
# 函数执行的耗时为: 2.000722646713257
# work(1, 2)执行结果: 3
2、装饰器带参数 @CountTime(666)
# -----------------2、装饰器带参数 @CountTime(666)-------------------------------
import time
class CountTime:
def __init__(self, n):
self.n = n
def __call__(self, func):
self.func = func
return self.run
def run(self, *args, **kwargs):
print("装饰器的功能代码:函数执行前内容")
st = time.time()
# 调用原功能函数
res = self.func(*args, **kwargs)
print("装饰器的功能代码:函数执行后内容")
et = time.time()
print("函数执行的耗时为:", et - st)
return res
@CountTime(666) # ==> work = CountTime(3)(work) # 实例化对象
def work():
time.sleep(2)
print('---work---')
return '这是函数work的返回值'
work()
# 装饰器的功能代码:函数执行前内容
# ---work---
# 装饰器的功能代码:函数执行后内容
# 函数执行的耗时为: 2.004631996154785
print(work())
# 装饰器的功能代码:函数执行前内容
# ---work---
# 装饰器的功能代码:函数执行后内容
# 函数执行的耗时为: 2.0007331371307373
# 这是函数work的返回值
3、装饰器带参数 @CountTime(888) 闭包函数实现
# -----------------3、装饰器带参数 @CountTime(888) 闭包函数实现-------------------------------
import time
class CountTime:
def __init__(self, n):
self.n = n
def __call__(self, func):
def wrapper(*args, **kwargs):
print("装饰器的功能代码:函数执行前内容")
st_time = time.time()
res = func(*args, **kwargs)
print("装饰器的功能代码:函数执行后内容")
ed_time = time.time()
print('函数执行耗时为:', ed_time - st_time)
print('装饰器传入的参数为:', self.n)
return res
return wrapper
@CountTime(888) # ==> work = CountTime(3)(work) # 实例化对象
def work():
time.sleep(2)
print('---work---')
work()
# 装饰器的功能代码:函数执行前内容
# ---work---
# 装饰器的功能代码:函数执行后内容
# 函数执行耗时为: 2.0053937435150146
# 装饰器传入的参数为: 888
print(work())
# 装饰器的功能代码:函数执行前内容
# ---work---
# 装饰器的功能代码:函数执行后内容
# 函数执行耗时为: 2.000443458557129
# 装饰器传入的参数为: 888
# None
欢迎来到testingpai.com!
注册 关于