python - 使用属性装饰器后,python 对象有两个非常相似的属性(foo.bar 和 foo._bar)。那样行吗?
问题描述
所以我正在重构我的代码,使其更加 Pythonic——特别是我了解到,使用显式 getter 和 setter 应该替换为 @property。我的情况是我有一个Example
具有初始化bar
属性的类(初始化帮助我知道用户设置了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 有两个属性:_bar
和bar
,都设置为'initializedValue'
. 此外,当我运行foo.bar = 'changedValue'
or时foo._bar = 'changedValue'
,它们都更改为'changedValue'
. 为什么有两个属性?这不是多余的吗?我想我明白为什么会有_bar
属性 - 我将它添加到 中@bar.setter
,但为什么会有bar
字符串属性?不应该bar
是一种导致的方法bar
@property
吗?
解决方案
没关系。请记住,这bar
不是实例属性,而是类属性。由于它具有 type property
,因此它实现了描述符协议,因此当从实例访问时它的行为是不同的。如果e
是 的实例Example
,e.bar
则不给您property
分配给的实例Example.bar
;它为您提供了结果Example.bar.__get__(e, Example)
(在这种情况下,恰好是Example.bar.fget(e)
,fget
由 装饰的原始函数在哪里@property
)。
简而言之,每个实例都有自己的_bar
属性,但对该属性的访问是由类属性介导的Example.bar
。
bar
如果您编写这个最小(并且足够,因为在这种情况下 getter 和 setter 都不需要def
语句)定义,则更容易看出这是一个类属性。
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)
推荐阅读
- javascript - JSON.parse - 意外的令牌',n
- asp.net - 在 asp.net 中连接到 oracle 时出现 ORA-12154
- python - 为什么我的正则表达式中的 $ 不匹配行尾
- php - 找到安装-PhpExtension 命令
- python - 将 ColumnTransformer 与已拟合的估计器一起使用
- java - 无法从 oracle 教程运行 Java EE 示例
- netcdf - 使用具有单个时间片的掩码来掩盖具有多个时间步长的另一个变量?
- rxjs - 如何缓冲 observable
何时计数或最大时间避免发出空数组? - swift - Swift:使用计算的结构属性实现 Comparable
- asp.net - 带有 VB 的 ASP.Net 似乎不起作用:如何使用 '@'