使用属性decorator后,python对象有两个非常相似的属性(foo.bar和foo_bar).可以吗



所以我正在重构我的代码,使其更加Python化——特别是我已经学会了使用显式getter和setter应该用@property代替。我的情况是,我有一个具有初始化bar属性的Example类(初始化帮助我知道用户设置了bar(:

class Example:
def __init__(self):
self.bar = 'initializedValue'
@property
def bar(self):
return self._bar
@bar.setter
def bar(self, b):
self._bar = b
def doIfBarWasSet():
if self.bar != 'initializedValue':
pass
else:
pass

在运行foo = Example()之后,我的调试器显示foo有两个属性:_barbar,都设置为'initializedValue'。此外,当我运行foo.bar = 'changedValue'foo._bar = 'changedValue'时,它们都会更改为'changedValue'。为什么有两个属性?这不是多余的吗?我想我理解为什么会有_bar属性——我在@bar.setter中添加了它,但为什么会有作为字符串属性的barbar不应该是一种导致bar@property的方法吗?

很好。请记住,bar不是实例属性,而是的属性。由于它的类型为property,因此它实现描述符协议,以便从实例访问时其行为不同。如果eExample的实例,则e.bar不会为您提供分配给Example.barproperty的实例;它给出了Example.bar.__get__(e, Example)的结果(在本例中,它恰好是Example.bar.fget(e),其中fget是由@property修饰的原始函数(。

简而言之,每个实例都有自己的_bar属性,但对该属性的访问是由类属性Example.bar介导的。


如果您编写这个最小(并且足够,因为在这种情况下getter和setter都不需要def语句(定义,则更容易看出bar是一个类属性。

class Example:
def __init__(self):
self.bar = "initalizedValue"
bar = property(lambda self: self._bar, lambda self, b: setattr(self, '_bar', b))

或者更一般地

def bar_getter(self):
return self._bar

def bar_setter(self, b):
self._bar = b

class Example:
def __init__(self):
self.bar = "initalizedValue"
bar = property(bar_getter, bar_setter)

最新更新