返回属性对象的类属性

时间:2017-09-16 16:52:28

标签: python python-3.x properties metaprogramming

在此之前被标记为重复之前,我之前知道这个question has been answered,但那里提供的解决方案似乎并不适用于我的案例。我试图以编程方式设置类属性。我知道我可以使用property,所以我想这样做:

class Foo:
    def __init__(self, x):
        self._x = x
        def getx(): return self._x
        def setx(y): self._x = y
        self.x = property(fget=getx, fset=setx)

然而,当我以交互方式运行时,我得到:

>>> f = Foo(42)
>>> f.x
<property object at 0x0000000>
>>> f._x
42
>>> f.x = 1
>>> f.x
1

有什么方法可以解决这个问题吗?

编辑:

我觉得我可能遗漏了太多,所以这就是我实际想要达到的目标。我有一个类,其变量名为config,其中包含要设置为属性的配置值。该类应该被子类化以实现config变量:

class _Base:
    config = ()

    def __init__(self, obj, **kwargs):
        self._obj = obj()
        for kwarg in kwargs:
            # Whatever magic happens here to make these properties

# Sample implementation
class Bar(_Base):
     config = (
         "x",
         "y"
     )

     def __init__(self, obj, x, y):
         super().__init__(obj, x=x, y=y)

现在允许操作:

>>> b = Bar(x=3, y=4)
>>> b.x
3
>>> # Etc.

我试图尽可能保持DRY,因为我必须经常继承_Base

1 个答案:

答案 0 :(得分:3)

property个对象是descriptors,只有在类或元类上定义时才会调用描述符。你不能直接把它们放在一个实例上;类的__getattribute__实现只是不调用所需的绑定行为。

您需要将属性放在类上,而不是放在每个实例上:

class Foo:
    def __init__(self, x):
        self._x = x

    @property
    def x(self): return self._x

    @x.setter
    def x(self, y): self._x = y

如果必须拥有仅适用于某些实例的属性,则必须更改getter和setter方法以改变行为(例如,当实例的状态为时,引发AttributeError这样该属性应该不存在&#39;)。

class Bar:
    def __init__(self, has_x_attribute=False):
        self._has_x_attribute = has_x_attribute
        self._x = None

    @property
    def x(self):
        if not self._has_x_attribute:
            raise AttributeError('x')
        return self._x

    @x.setter
    def x(self, y):
        if not self._has_x_attribute:
            raise AttributeError('x')
        self._x = y

property对象仍然存在且已绑定,但当标志设置为false时,其行为就像该属性不存在一样。