注意:
在另一个问题上接受的答案显示了如何使用父装饰器.
此问题上接受的答案显示将装饰器移动到模块范围.
编辑:使用前面的例子是一个坏主意.希望这更清楚:
class A:
def deco( func ):
print repr(func)
def wrapper( self, *args ):
val = func( *args )
self.do_something()
return val
return wrapper
def do_something( self ):
# Do something
print 'A: Doing something generic for decoration'
@deco
def do_some_A_thing ( self ):
# Do something
print 'A: Doing something generic'
class B ( A ):
@deco
def do_some_B_thing( self ):
# Do something
print "B: Doing something specific"
a = A()
b = B()
a.do_some_A_thing()
b.do_some_B_thing()
#Expected Output:
#A: Doing something generic
#A: Doing something generic for decoration
#B: Doing something specific
#A: Doing something generic for decoration
Run Code Online (Sandbox Code Playgroud)
此代码生成NameError:名称'deco'未在B中定义.装饰器需要在类范围内,因为我需要访问存储状态.
第三编辑:关于斯文的建议,我试过这个:
class A:
def deco( func ):
def wrapper( self, *args ):
val = func( *args )
self.do_something(*args)
return val
return wrapper
def do_something( self ):
# Do something
print 'A: Doing something generic for decoration'
@deco
def do_some_A_thing ( self ):
# Do something
print 'A: Doing something generic'
deco = staticmethod(deco)
class B ( A ):
@A.deco
def do_some_B_thing( self ):
# Do something
print "B: Doing something specific"
a = A()
b = B()
a.do_some_A_thing()
b.do_some_B_thing()
#Expected Output:
#A: Doing something generic
#A: Doing something generic for decoration
#B: Doing something specific
#A: Doing something generic for decoration
Run Code Online (Sandbox Code Playgroud)
我现在有TypeError:do_some_A_thing()只取1个参数(给定0).有什么指针吗?
问题是继承适用于例如属性查找,而不适用于类定义.所以当你尝试用B中的A.deco装饰时,它找不到它.解决方案是deco移出模块范围,因为名称没有任何魔力self,你可以继续使用它.您还需要明确地传递self到func了,你不会需要将它传递self.do_something().这是更新的代码:
def deco( func ):
print repr( func )
def wrapper( self, *args ):
val = func( self, *args )
self.do_something()
return val
return wrapper
class A:
def do_something( self ):
# Do something
print 'A: Doing something generic for decoration'
@deco
def do_some_A_thing ( self ):
# Do something
print 'A: Doing something generic'
class B ( A ):
@deco
def do_some_B_thing( self ):
# Do something
print "B: Doing something specific"
a = A()
b = B()
a.do_some_A_thing()
b.do_some_B_thing()
Run Code Online (Sandbox Code Playgroud)