<p>我觉得你有点误解了属性的工作原理。没有“默认设置程序”。它在设置<code>badprop</code>时抛出一个<code>AttributeError</code>,这并不是因为它还不知道{<cd2>}是一个属性而不是一个普通属性(如果是这样的话,它只会毫无错误地设置属性,因为这现在是正常的属性行为),而是因为您没有为<code>badprop</code>提供setter,而只是一个getter。在</p>
<p>看看这个:</p>
<pre><code>>>> class Foo(object):
@property
def foo(self):
return self._foo
def __init__(self):
self._foo = 1
>>> f = Foo()
>>> f.foo = 2
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
f.foo = 2
AttributeError: can't set attribute
</code></pre>
<p>即使在构造实例之后,<code>__init__</code>之外也不能设置这样的属性。如果您只使用<code>@property</code>,那么您拥有的是一个只读属性(实际上是一个类似于属性read的方法调用)。在</p>
<p>如果您在getter和setter中所做的只是将读/写访问重定向到一个名称相同但带有下划线的属性,那么到<strong>far</strong>最简单的事情就是完全去掉这些属性,只使用普通属性。Python不是Java(即使在Java中,我也不相信私有字段具有明显的公共getter/setter的优点)。外部世界可以直接访问的属性是“公共”接口中非常合理的一部分。如果您后来发现在读/写属性时需要运行一些代码,那么您可以在不更改接口的情况下使其成为属性<strong>然后</strong>(这实际上是描述符最初的用途,<em>而不是</em>,这样我们就可以开始为每个属性编写Java风格的getter/setter)。在</p>
<p>如果您实际上在属性中做一些事情而不是更改属性的名称,并且您希望您的属性是只读的,那么您最好的选择可能是将<code>__init__</code>中的初始化视为直接设置带有下划线的底层数据属性。然后,您的类可以直接初始化而不需要<code>AttributeErrors</code>,然后属性将在读取属性时完成它们的工作。在</p>
<p>如果您实际上在属性中做了一些事情,而不是更改属性的名称,并且希望您的属性是可读写的,那么您需要实际指定当您获取/设置它们时会发生什么。如果每个属性都有独立的自定义行为,那么没有比为每个属性显式提供getter和setter更有效的方法了。在</p>
<p>如果您在每个getter/setter中运行完全相同(或非常相似)的代码(这不仅仅是在真正的属性名中添加下划线),这就是为什么您反对将它们都写出来(这是正确的!),那么通过实现<code>__getattr__</code>、<code>__getattribute__</code>、和{<cd11>}的一些功能,可能会更好地为您服务。这允许您每次将属性读/写重定向到相同的<em>代码(以属性名称作为参数),而不是每个属性的两个函数(获取/设置)。在</p>