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中关于装饰器的问题请教,谢谢大家


4 回复

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__模块,这些模块中的代码在导入时是不会被执行的。

我按照上面这个说法来理解对不对呢?

这些函数都是有特殊含义的,你要学习建议先用自己定义的函数。

回到顶部