【问题标题】:Python: overloading the __getattr__ and properties, making __setattr__ work correctlyPython:重载 __getattr__ 和属性,使 __setattr__ 正常工作
【发布时间】:2012-09-19 06:46:03
【问题描述】:

考虑以下python代码:

class Foo(object):

    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return "value: {v}".format(v=self._value)

    @value.setter
    def value(self, value):
        self._value = value

class Bar(object):

    def __init__(self):
        self.foo = Foo('foo')

    def __getattr__(self, attr, *args, **kwargs):
        """
        Intercepts attribute calls, and if we don't have it, look at the
        webelement to see if it has the attribute.
        """

        # Check first to see if it looks like a method, if not then just return
        # the attribute the way it is.
        # Note: this has only been tested with variables, and methods.
        if not hasattr(getattr(self.foo, attr), '__call__'):
            return getattr(self.foo, attr)

        def callable(*args, **kwargs):
            '''
            Returns the method from the webelement module if found
            '''
            return getattr(self.foo, attr)(*args, **kwargs)
        return callable

>>> b = Bar()
>>> b.foo
<__main__.Foo object at 0x819410>
>>> b.foo.value
'value: foo'
>>> b.foo.value = '2'
>>> b.foo.value
'value: 2'
>>> b.value
'value: 2'
>>> b.value = '3'
>>> b.value
'3'

最后一部分,我希望它是 'value: 3' 而不是 '3' 因为现在我的属性 'value' 现在是一个属性。

有可能吗,如果是的话,我会怎么做。

【问题讨论】:

    标签: python properties


    【解决方案1】:

    您的__getattr__ 返回属性,而不是属性本身。当您访问 getattr(self.foo, attr) 时,它会执行与 self.foo.value 等效的操作并返回它,然后调用该属性。

    因此,您还需要实现__setattr__ 方法,以镜像__getattr__ 并将值设置传递给包含的foo 对象。

    在底层,Python 将属性实现为descriptors;他们的__get__() method 被较低级别的__getattribute__ method 调用,这导致他们返回他们的计算值。返回的绝不是属性对象本身。

    这是一个例子__setattr__

    def __setattr__(self, attr, value):
        if hasattr(self, 'foo') and hasattr(self.foo, attr):
            setattr(self.foo, attr, value)
            return
        super(Bar, self).__setattr__(attr, value)
    

    注意:因为您的__init__ 设置了self.foo,您需要测试您的班级是否存在foo (hasattr(self, 'foo')。您还需要调用原始__setattr__ 实现以确保@ 987654339@ 还在工作。

    【讨论】:

    • 那么我该如何实现这样的setattr。我试过但不知道如何正确地做到这一点。谢谢马丁!
    • @glouie:为您添加了一个示例__setattr__
    猜你喜欢
    • 2012-05-26
    • 2023-03-09
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    相关资源
    最近更新 更多