Python中关于装饰器的问题请教,谢谢大家
class Deco:
def init(self,func):
self.func=func
print(“init__执行完毕。func=",self.func)
def call(self,*arg,**arg2):
print("开始执行__call。”)
self.func(‘abc’)
print(self,arg,arg2)
class MyCls():
@Deco
def myFunc(self):
print(‘this is my work arg is %s’%self)
mycls=MyCls() #语句 1
print(“mycls=MyCls()执行完毕”)
deco=Deco(mycls.myFunc) #语句 2
print(“deco=Deco(mycls.myFunc)执行完毕”)
deco(sendarg=‘abcdefg’) #语句 3
上面这段代码的输出如下,前面的序号是我另外加上的:
1. init__执行完毕。func=
2. mycls=MyCls()执行完毕
3. init__执行完毕。func= <main.Deco object at 0x0208A110>
4. deco=Deco(mycls.myFunc)执行完毕
5. 开始执行__call。
6. 开始执行__call。
7. this is my work arg is abc
8. <main.Deco object at 0x0208A110> (‘abc’,) {}
9. <main.Deco object at 0x0208A150> () {‘sendarg’: ‘abcdefg’}
对于上面的输出,我有以下问题:
1、为什么语句 1 会导致序号 1 的输出?
2、语句 2 是把类 Deco 实例化的操作,语句 3 产生了序号 3 的输出,为何实例化时只执行了类 Deco 的__init__函数而不执行__call__函数呢,难道不需要调用__call__来返回一个对象么?
3、语句 3 产生了序号 5 至序号 6 的 5 条输出内容,不明白为何是这样的输出顺序,恳请大家详细指点一下?
都是些小白问题,恳请大家不吝赐教,感谢!
Python中关于装饰器的问题请教,谢谢大家
1 所谓生成一个 MyCls 的实例,就是把该 class 的定义语句执行一遍啊
2 实例化的时候当然不执行__call__啊!这东西是“把 class 当作 function 调用”的时候才执行的
建议你不要把面向对象、装饰器、__class__三者混在一起学
装饰器是Python里一个挺酷的特性,本质上就是个返回函数的高阶函数。它的核心作用是在不修改原函数代码的情况下,给函数动态添加功能,比如日志、计时、权限检查这些。
给你看个最基础的例子就明白了:
def my_decorator(func):
def wrapper():
print("在原函数前干点啥")
func()
print("在原函数后干点啥")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
运行这个,你会先看到“在原函数前干点啥”,然后是“Hello!”,最后是“在原函数后干点啥”。那个@my_decorator其实就是say_hello = my_decorator(say_hello)的语法糖。
如果你想装饰带参数的函数,得这么写:
def decorator_with_args(func):
def wrapper(*args, **kwargs):
print(f"准备调用 {func.__name__}")
result = func(*args, **kwargs)
print(f"{func.__name__} 调用完了")
return result
return wrapper
用*args和**kwargs就能处理任意参数了。
还有个更实用的例子,比如给函数计时:
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 执行耗时: {end - start:.4f}秒")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
return "Done"
slow_function()
简单说,装饰器就是函数的功能扩展器。
装饰器是在导入模块时立即执行的,所以装饰函数中的代码在导入模块时会被执行,
但是装饰函数中如果有__init__或__call__模块,这些模块中的代码在导入时是不会被执行的。
我按照上面这个说法来理解对不对呢?
这些函数都是有特殊含义的,你要学习建议先用自己定义的函数。

