Python中关于装饰器中__init__方法的问题

第一个装饰器的代码:

registry = []

def register(func):

    def __init__(self): 
    print("INIT!!!") 

print('running register(%s)' % func)   

registry.append(func)   

return func   

[@register](/user/register)

def f1():

    print('running f1()') 

def main():

    print('registry ->', registry) 
f1()  

if name =='main':

    main()             

上面代码的输出如下,可见装饰器的__init__方法并没有执行:

running register()

registry -> []

running f1()

第二个装饰器的代码:

class tracer(object):

    def __init__(self, func):   
        print("tracer: init")  

        self.func = func 

def __call__(self, *args, **kwargs):    

        return self.func(*args, **kwargs) 

class C:

    def __init__(self): 
        pass 

@tracer 

def f(self):  

        print("run f!") 

print("--------------")

输出如下:

tracer: init


我的问题是,这两个装饰器为何第一个装饰器的__init__方法没有执行,而第二个装饰器的__init__方法却被执行了?


Python中关于装饰器中__init__方法的问题

18 回复

def a():
def b():
print(“emmmmmmm”)
print(“oh yep”)

a()

为什么 b 没有被执行?


我无法理解你的问题

楼主发下一个帖子前记得看看 markdown…看一眼预览再发帖…

我是看过预览才发的,我用论坛用不太好,比如 name 前后各有两个下划线没有显示出来,因为着急问问题,想着这不影响整体阅读就没有去改了

不是很明白,您的例子中因为没有 b()这样的调用语句,自然 b 不会被执行。可我的例子中第一个装饰器是执行了 register(f1()),这时 register.init()应该被执行的吧?

感谢指点,我晕了,register 是函数不是类!顺便问个问题,所谓的函数装饰器,是说装饰器是一个函数,还是说被装饰的对象是函数呢?

函数装饰器 这只是个中文词汇,有歧义,所以不用太在意。
你只需要知道装饰器可以是一个类也可以是一个函数,被装饰的可以使一个类也可以是一个函数
这边有我总结的装饰器相关的两篇文章,希望可以帮到你。
http://45.32.54.6/2017/04/17/Decorators-for-Class
http://45.32.54.6/2017/04/17/Decorators-for-Functions-and-Methods

decorator 只是个 AOP 的糖(

AOP 是什么的缩写呢?语法?

感谢指点,关于装饰器我另外还发了一个问题求指点,如果有空的话,能否看看我发的帖子,点拨我一下呢,谢谢了! https://www.v2ex.com/t/384418#reply2

感谢!

#9 面向切面编程

谢谢你的总结,我看了一下,似乎有点问题。你的被装饰的类似乎没必要重载__new__方法吧,如果要的话,应该使用新式类 class A(object),否则__new__不会被调用。

首先,我的代码是 Python3 代码,不存在新式类和旧式类之分,不管怎么声明,都是新式类。其次,我重载__new__方法是来看调用顺序,没别的用处。

关于您写的这篇文章 http://45.32.54.6/2017/04/17/Decorators-for-Functions-and-Methods/。
我看“ 2.1 函数不带参数”小节中,装饰器的效果等同于 echo()=Decorator.call() ,所以等号的右边,即 Decorator.call()运行后应该要返回一个函数才对吧?
但是为何__call__方法直接就执行 self.fun(),而不是 return self.fun 呢?

关于您的类的装饰器这篇 http://45.32.54.6/2017/04/17/Decorators-for-Class/,
例子“ 1.3 装饰器带参数 2 ”,既然 A() = Decorator(1,2).call() ,那为何__call__方法不返回一个对象,而是返回方法 wrapper,这样等号两边的对象不会不匹配么?


统一回复,装饰器的目的是利用语法糖,以不改变原有函数的功能为原则,额外增加一些逻辑。
你的这两个问题,执行一下代码,你自己就会明白。建议你按照你自己的想法,修改我的代码,看出来的结果区别在哪里,这样就会明白为什么要那样写。

回到顶部