类中的Python装饰器

2024-06-16 11:54:16 发布

您现在位置:Python中文网/ 问答频道 /正文

一个人能写出这样的东西吗:

class Test(object):
    def _decorator(self, foo):
        foo()

    @self._decorator
    def bar(self):
        pass

失败:self中的self未知

我也试过:

@Test._decorator(self)

也失败了:测试未知

我想临时更改一些实例变量 在decorator中,然后运行decorated方法 把它们换回来。


Tags: 实例方法testselfobjectfoodefbar
3条回答

这样的东西能满足你的需要吗?

class Test(object):
    def _decorator(foo):
        def magic( self ) :
            print "start magic"
            foo( self )
            print "end magic"
        return magic

    @_decorator
    def bar( self ) :
        print "normal call"

test = Test()

test.bar()

这避免了调用self来访问decorator,并将其作为常规方法隐藏在类命名空间中。

>>> import stackoverflow
>>> test = stackoverflow.Test()
>>> test.bar()
start magic
normal call
end magic
>>> 

编辑以回答评论中的问题:

如何在另一个类中使用隐藏的decorator

class Test(object):
    def _decorator(foo):
        def magic( self ) :
            print "start magic"
            foo( self )
            print "end magic"
        return magic

    @_decorator
    def bar( self ) :
        print "normal call"

    _decorator = staticmethod( _decorator )

class TestB( Test ):
    @Test._decorator
    def bar( self ):
        print "override bar in"
        super( TestB, self ).bar()
        print "override bar out"

print "Normal:"
test = Test()
test.bar()
print

print "Inherited:"
b = TestB()
b.bar()
print

输出:

Normal:
start magic
normal call
end magic

Inherited:
start magic
override bar in
start magic
normal call
end magic
override bar out
end magic

你想做什么是不可能的。以下面的代码是否有效为例:

class Test(object):

    def _decorator(self, foo):
        foo()

    def bar(self):
        pass
    bar = self._decorator(bar)

当然,它是无效的,因为self在那一点上没有定义。对于Test也是如此,因为只有在定义了类本身(它正在定义)之后才会定义它。我向您显示此代码片段是因为这是您的装饰程序片段转换成的内容。

因此,正如您所看到的,像这样访问decorator中的实例实际上是不可能的,因为decorators是在定义它们附加到的函数/方法时应用的,而不是在实例化期间应用的。

如果您需要类级别访问,请尝试以下操作:

class Test(object):

    @classmethod
    def _decorator(cls, foo):
        foo()

    def bar(self):
        pass
Test.bar = Test._decorator(Test.bar)
import functools


class Example:

    def wrapper(func):
        @functools.wraps(func)
        def wrap(self, *args, **kwargs):
            print("inside wrap")
            return func(self, *args, **kwargs)
        return wrap

    @wrapper
    def method(self):
        print("METHOD")

    wrapper = staticmethod(wrapper)


e = Example()
e.method()

相关问题 更多 >