<p><strong>免责声明</strong>:我不知道您为什么要这样做。如果要使用<code>setattr</code>动态创建属性,应该足够了:</p>
<pre><code>SC = SimpleClass()
setattr(SC, 'your_new_attribute_name', 'test')
</code></pre>
<p>总之,有一种简单的方法可以使用helper类获得所需的内容:</p>
<pre><code>In [1]: class SimpleClass:
...: def __getattr__(self, attr):
...: return AttributeSetter(self, attr)
...: class AttributeSetter:
...: def __init__(self, inst, attr):
...: self._inst = inst
...: self._attr = attr
...: def add(self, value):
...: setattr(self._inst, self._attr, value)
...:
In [2]: SC = SimpleClass()
In [3]: SC.new_attr.add('test')
In [4]: SC.new_attr
Out[4]: 'test'
</code></pre>
<hr/>
<p>关于你的评论。如果您询问是否可以这样写<code>SimpleClass</code>:</p>
<pre><code>SC.new_attr
</code></pre>
<p>返回<em>字符串</em><code>'test'</code><em>和</em>,<em>在</em>调用<code>Sc.new_attr.add('test')</code>调用之后:</p>
<pre><code>SC.new_attr.add('other')
</code></pre>
<p>是这样的:</p>
<pre><code>SC.new_attr
</code></pre>
<p>现在返回<em>字符串</em><code>'other'</code>,然后答案是:<strong>不,这是不可能的。你知道吗</p>
<p>不可能编写一个类,使得下面的<em>不会</em>产生一个<code>AttributeError</code>:</p>
<pre><code>In [2]: SC = SimpleClass()
In [3]: SC.new_attr.add('test')
In [4]: SC.new_attr #this returns a string, not a user-defined class
'test'
In [5]: SC.new_attr.add('new value')
-
AttributeError Traceback (most recent call last)
<ipython-input-5-f218074b7a68> in <module>()
> 1 SC.new_attr.add('new value')
AttributeError: 'str' object has no attribute 'add'
</code></pre>
<p>你为什么问?好吧,让我们看看解释器实际上做了什么:</p>
<pre><code>In [5]: import dis
...: dis.dis(lambda: SC.new_attr.add('some string'))
...:
2 0 LOAD_GLOBAL 0 (SC)
3 LOAD_ATTR 1 (new_attr)
6 LOAD_ATTR 2 (add)
9 LOAD_CONST 1 ('some string')
12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
15 RETURN_VALUE
</code></pre>
<p><code>dis</code>模块允许我们查看解释器正在执行的字节码。
注意有两个不同的字节码。
如您所见,解释器首先获取<code>new_attr</code>属性,然后<em>作为一个完全独立的操作,它检索<code>add</code>属性。你知道吗</p>
<p>现在,类<code>SC</code>只能修改第一个属性访问的行为(即对<code>new_attr</code>的访问)。它无法知道下一个字节码将访问<code>add</code>,因此唯一明智的做法是返回设置的字符串。你知道吗</p>
<p>以下属性访问<code>add</code>是对检索到的值执行的。这意味着解释器将查找字符串的<code>add</code>属性,该属性显然不存在。你知道吗</p>
<p>避免这种<code>AttributeError</code>的唯一方法是返回具有<code>add</code>方法的对象,但这意味着:</p>
<pre><code>In [6]: SC.new_attr
Out[6]: 'test'
</code></pre>
<p>将<em>失败</em>,因为不是返回字符串<code>"test"</code>,而是返回另一个对象。你知道吗</p>
<p>解决这个问题的方法是返回一个具有<code>add</code>方法和<code>value</code>属性的对象,这样我们可以得到如下结果:</p>
<pre><code>In [12]: SC.new_attr
Out[12]: <__main__.TheClass at 0x7fac44727a90>
In [13]: SC.new_attr.value
Out[13]: 'test'
In [14]: SC.new_attr.add('other')
In [15]: SC.new_attr.value
Out[15]: 'other'
</code></pre>
<p>另一种解决方案是编写此类,使其行为类似于字符串(我们甚至可以将<code>str</code>作为子类,但不要这样做!</strong>子类化内置的<em>从来都不是正确的做法,如果你在不知道确切后果的情况下这样做,你会遇到问题,很难发现和解决),但这意味着代码会变得更加复杂,必须实现<em>所有</em>字符串支持的操作(这意味着实现大约80-90-100个方法!)你知道吗</p>