<p>第一点:<code>@decorator</code>语法并不是什么神奇的东西,它只是语法上的糖分,所以</p>
<pre><code>@decorator
def func():
pass
</code></pre>
<p>实际上只是一个方便的快捷方式:</p>
<pre><code>def func():
pass
func = decorator(func)
</code></pre>
<p>第二点:<code>property</code>类型是<a href="https://docs.python.org/3/reference/datamodel.html#implementing-descriptors" rel="nofollow noreferrer">the ^{<cd3>} protocol</a>的一个通用实现(而且相当简单,这里同样不涉及魔法)。描述符仅在解析为类属性时才“起作用”,因此将属性设置为实例属性将不起作用,句点(查找它们将返回描述符对象本身,它不会调用描述符的<code>__get__</code>和<code>__set__</code>方法)。你知道吗</p>
<p>第三点:您的代码甚至没有将创建的属性设置为实例属性(无论如何都不会工作),它们只是在<code>_CreateAttributes</code>方法执行期间存在的普通<strong>本地<strong>名称。你知道吗</p>
<>这一切都不会解决你的问题——你必须为某人提供更多的上下文来发布解决方案,以解决具体的用例(基于这个C++父类实际上是如何实现的)等等,但是至少现在你知道为什么尝试失败了。你知道吗</p>
<p>编辑:</p>
<blockquote>
<p>I have a method inside the parent that allows me to know which are the properties. For the sake of the example let's suppose I have a method ListAttributes in the SomeOtherObj C++ class which returns a list of the attributes names (strings) dynamically created by the Parent class.</p>
</blockquote>
<p>如果是classmethod或staticmethod,则可以使用类装饰器来创建属性(或者,为了简化样板文件,可以使用自定义描述符):</p>
<pre><code>class Parent(object):
def __init__(self):
self._props = {"foo": 42, "bar": None}
@classmethod
def ListAttributes(cls):
return ["foo", "bar"]
def GetProperty(self, name):
return self._props[name]
def ModifyProperty(self, name, value):
self._props[name] = value
class Prop(object):
def __init__(self, name):
self.name = name
def __get__(self, instance, cls):
return instance.GetProperty(self.name)
def __set__(self, instance, value):
instance.ModifyProperty(self.name, value)
def setprops(cls):
parent = cls.__bases__[0]
for name in parent.ListAttributes():
setattr(cls, name, Prop(name))
return cls
@setprops
class Child(Parent):
pass
c = Child()
print("foo : {}".format(c.foo))
print("bar : {}".format(c.bar))
c.bar = "yay!"
print("bar: {}".format(c.bar))
</code></pre>
<p>如果<code>Parent.ListAttributes</code>是实例方法,那么仍然可以使用<code>__getattr__</code>和<code>__setattr__</code>特殊方法:</p>
<pre><code>class Parent2(object):
def __init__(self):
self._props = {"foo": 42, "bar": None}
def ListAttributes(self):
return ["foo", "bar"]
def GetProperty(self, name):
return self._props[name]
def ModifyProperty(self, name, value):
self._props[name] = value
class Child2(Parent2):
def __getattr__(self, name):
if name in self.ListAttributes():
return self.GetProperty(name)
raise AttributeError("object {} has no attribute {}".format(type(self), name))
def __setattr__(self, name, value):
if name in self.ListAttributes():
self.ModifyProperty(name, value)
super(Child2, self).__setattr__(name, value)
c = Child2()
print("foo : {}".format(c.foo))
print("bar : {}".format(c.bar))
c.bar = "yay!"
print("bar: {}".format(c.bar))
# check we didn't break the default __setattr__
c.baaz = "ok"
print("baaz: {}".format(c.baaz))
</code></pre>
<p>注意:<code>__getattr__</code>只有在其他所有查找都失败的情况下才作为最后手段被调用,所以它基本上是无害的,但是<code>__setattr__</code>是默认的属性设置器,所以您必须确保明智地使用它。你知道吗</p>