繁体   English   中英

python类装饰器内部方法

[英]python class decorator inside method

我尝试将装饰器模式用于类层次结构,因此我如下定义了类装饰器:

def delegate(cls, target='_base'):
    class Wrapper(object):
        def __init__(self, *args, **kwargs):
            self.wrapped = cls(*args, **kwargs)

        def __getattr__(self, name):
            if hasattr(self.wrapped, name):
                return getattr(self.wrapped, name)
            else:
                return getattr(self.wrapped.__dict__.get(target), name)

    return Wrapper

class A(object):
    def __init__(self):
      pass

    def foo(self):
      print('this is foo()')


@delegate
class B(object):
    def __init__(self):
        self._base = A()

    def bar(self):
        self.foo()  # self._base.foo() will work

def main():
    B().foo()  #1. works
    B().bar()  #2. attribute not found error

为什么在#1起作用时,对bar()中的self.foo()的调用没有抛出委托? 为了用没有硬性代码self._base.foo()的装饰器解决它,我是否必须为B中需要_base的每个方法编写方法装饰器? 我尝试减少样板代码。

def delegate(cls, target='_base'):
    class Wrapper(object):
        def __init__(self, *args, **kwargs):
            self.wrapped = cls(*args, **kwargs)

        def __getattr__(self, name):
            if hasattr(self.wrapped, name):
                return getattr(self.wrapped, name)
            else:
                return getattr(self.wrapped.__dict__.get(target), name)

    return Wrapper

class A(object):
    def __init__(self):
      pass

    def foo(self):
      print('this is foo()')


@delegate
class B(object):
    def __init__(self):
        self._base = A()

    def bar(self):
        self.foo()

    def thirdbar(self):
        self._base.foo()  # self._base.foo() will work

    def secondbar(self,x):
        x.foo()  # self._base.foo() will work

x=B()
x.foo()  #1. works
x.secondbar(x) #it is working
x.thirdbar()  #it is working
x.bar()   #still not working

之所以发生这种情况,是因为装饰器的行为(至少对我而言)有点违反直觉。

当您检查所有涉及的对象的类型时,将发生以下情况:

>>> type(b)
<class 'Wrapper'>

>>> type(b.wrapped)
<class 'B'>

>>> type(b.wrapped._base)
<class 'A'>

因为b 实际上Wrapper的实例,而不是 B ,所以当您调用b.foo() ,发生的是(psuedocode):

b.foo() --> Wrapper.__getattr__(foo) --> wrapped._base.foo

因此foo来自Wrapper对象的__getattr__而不是Bar对象的。

问题在于以这种方式定义bar

def bar(self):
    self.foo()

self不引用Wrapper对象的foo属性,而是Bar对象的foo属性,该属性不存在。

因此,当您调用b.bar() ,方法链为:

b.bar() --> Wrapper.__getattr__(bar) --> wrapped.bar() --> wrapped.foo()

您可以通过让Bar调用self._base.foo()来解决此问题。

    B().bar()  #2. attribute not found error

为什么? 实例化Wrapper该实例的wrapped

然后,您可以对'bar'进行点分查找。

'bar'将在包装好的B找到,因此这将返回一个绑定方法, self就是包装的B() ,而不是Wrapper()

def __getattr__(self, name):
    if hasattr(self.wrapped, name): 
        return getattr(self.wrapped, name) 

我不确定您要在这里完成什么。 似乎将子类化或直接将行为添加到类中可能比这样做更好。

据说调试代码的技巧必须是编写代码的两倍。 如果您太聪明了,那么就使您无法调试它。 我建议在这里做些不同的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM