第一个装饰器的代码:
registry = []
def register(func):
def __init__(self):
print("INIT!!!")
print('running register(%s)' % func)
registry.append(func)
return func
@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__方法却被执行了?
1
Kilerd 2017-08-21 22:17:58 +08:00 via iPhone
def a():
def b(): print("emmmmmmm") print("oh yep") a() 为什么 b 没有被执行? |
2
Trim21 2017-08-21 22:20:04 +08:00
楼主发下一个帖子前记得看看 markdown...看一眼预览再发帖...
|
3
saximi OP @Trim21 我是看过预览才发的,我用论坛用不太好,比如 name 前后各有两个下划线没有显示出来,因为着急问问题,想着这不影响整体阅读就没有去改了
|
4
saximi OP @Kilerd 不是很明白,您的例子中因为没有 b()这样的调用语句,自然 b 不会被执行。可我的例子中第一个装饰器是执行了 register(f1()),这时 register.__init__()应该被执行的吧?
|
5
saximi OP @Kilerd 感谢指点,我晕了,register 是函数不是类!顺便问个问题,所谓的函数装饰器,是说装饰器是一个函数,还是说被装饰的对象是函数呢?
|
6
enomine 2017-08-21 23:23:10 +08:00 1
函数装饰器 这只是个中文词汇,有歧义,所以不用太在意。
你只需要知道装饰器可以是一个类也可以是一个函数,被装饰的可以使一个类也可以是一个函数 这边有我总结的装饰器相关的两篇文章,希望可以帮到你。 http://45.32.54.6/2017/04/17/Decorators-for-Class http://45.32.54.6/2017/04/17/Decorators-for-Functions-and-Methods |
7
garfieldWu 2017-08-21 23:29:35 +08:00
http://coolshell.cn/articles/11265.html
check this out! |
8
lrxiao 2017-08-21 23:40:04 +08:00
decorator 只是个 AOP 的糖(
|
10
saximi OP @enomine 感谢指点,关于装饰器我另外还发了一个问题求指点,如果有空的话,能否看看我发的帖子,点拨我一下呢,谢谢了! https://www.v2ex.com/t/384418#reply2
|
11
saximi OP @garfieldWu 感谢!
|
13
lovestudykid 2017-08-22 07:30:39 +08:00
@enomine 谢谢你的总结,我看了一下,似乎有点问题。你的被装饰的类似乎没必要重载__new__方法吧,如果要的话,应该使用新式类 class A(object),否则__new__不会被调用。
|
14
enomine 2017-08-22 10:27:54 +08:00
@lovestudykid 首先,我的代码是 Python3 代码,不存在新式类和旧式类之分,不管怎么声明,都是新式类。其次,我重载__new__方法是来看调用顺序,没别的用处。
|
15
saximi OP |
16
saximi OP @enomine 关于您的类的装饰器这篇 http://45.32.54.6/2017/04/17/Decorators-for-Class/,
例子“ 1.3 装饰器带参数 2 ”,既然 A() = Decorator(1,2).__call__() ,那为何__call__方法不返回一个对象,而是返回方法 wrapper,这样等号两边的对象不会不匹配么? |
17
enomine 2017-08-28 19:56:31 +08:00
@saximi
统一回复,装饰器的目的是利用语法糖,以不改变原有函数的功能为原则,额外增加一些逻辑。 你的这两个问题,执行一下代码,你自己就会明白。建议你按照你自己的想法,修改我的代码,看出来的结果区别在哪里,这样就会明白为什么要那样写。 |