Python装饰器:如何在子类中使用父类装饰器

Gen*_*cos 7 python decorator

注意:

在另一个问题上接受的答案显示了如何使用父装饰器.

此问题上接受的答案显示将装饰器移动到模块范围.


编辑:使用前面的例子是一个坏主意.希望这更清楚:

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).有什么指针吗?

Eth*_*man 6

问题是继承适用于例如属性查找,而不适用于类定义.所以当你尝试用B中的A.deco装饰时,它找不到它.解决方案是deco移出模块范围,因为名称没有任何魔力self,你可以继续使用它.您还需要明确地传递selffunc了,你不会需要将它传递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)