【问题标题】:Way to encapsulate instance fields in Python在 Python 中封装实例字段的方法
【发布时间】:2011-07-16 20:54:02
【问题描述】:

这种@property decorator 的使用是否适合获得对实例字段的良好封装?我试图实现 Foobar 类的客户端不能以任何方式将任意值分配给 Foobar 实例的字段vel,事实上绕过了属性设置器方法中定义的分配规则。

谢谢。

class Foobar(object):
    def __init__(self):
        self._vel = 0

    @property
    def vel(self):
        return self._vel

    @vel.setter
    def vel(self, v):
        self._vel = v if v > 0 else 0

该字段似乎封装得很好。

>>> foobar = Foobar()
>>> foobar.vel
0
>>> foobar.vel = -1
>>> foobar.vel
0
>>> foobar.vel = 1
>>> foobar.vel
1

【问题讨论】:

  • 请注意,提高 ValueError 而不是静默限制值可能是更好的做法,这可能会造成混淆。如果检查离散值(例如枚举类型或字符串格式检查),我肯定会这样做;速度我不确定。

标签: python properties decorator encapsulation


【解决方案1】:

您无法阻止用户绕过 python 中的任何内容。总有办法修补/反映/检查属性;不支持对象沙盒。

在你的例子中:

>>> foobar._vel = -1

将完全绕过该属性并直接分配给真实属性。你根本无法阻止它。有一些方法可以让它变得更难,但是如果用户真的想要,可以分配,那有什么意义呢?

通常的方法似乎是依赖于您图书馆的用户是成年人并信任他们这一事实:

在文档中声明期望值的范围并要求用户遵循。如果他们不这样做,那是他们的错。

【讨论】:

  • 你严重误解了“我们都是成年人”的原则。这并不意味着“我们都很完美”。您无法阻止人们绕过您的 API 并分配给 foobar._vel,但在您的 public 方法 (foobar.vel) 上使用访问器来执行值检查是完全正常的。不要只在文档中提及事情并试图推卸责任,因为您的代码没有进行任何值检查。
  • @Glenn Maynard:我不知道你从哪里得到这样的印象,但似乎你正在反对大多数现有的 python 库——很难在属性中看到这种类型的值检查一个真正知名的python库中的级别。在一般情况下,这需要很长时间(属性中的赋值使用函数调用,并且比属性赋值慢几个数量级)才能获得收益。如果给出错误的值,代码无论如何都会失败,因此检查实际上没有那么有用
  • 人们似乎以“我们都是成年人”为借口。对值进行完整性检查是完全合理的,就像您无法构造日期(月 = 13)一样。您假设“代码将失败”以某种不错的、干净的方式,而在实践中它可能会在很久以后产生无效的结果或导致微妙的、难以追踪的错误。 (这不是关于优化的问题。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-12
  • 1970-01-01
  • 1970-01-01
  • 2013-06-23
  • 1970-01-01
  • 1970-01-01
  • 2013-02-12
相关资源
最近更新 更多