我正在尝试编写一个具有动态属性的类。考虑以下具有两个只读属性的类:
class Monster(object):
def __init__(self,color,has_fur):
self._color = color
self._has_fur = has_fur
@property
def color(self): return self._color
@property
def has_fur(self): return self._has_fur
我想概括这一点,以便__init__
可以使用任意字典并从字典中的每个项目创建只读属性。我可以这样做:
class Monster2(object):
def __init__(self,traits):
self._traits = traits
for key,value in traits.iteritems():
setattr(self.__class__,key,property(lambda self,key=key: self._traits[key]))
但是,这有一个严重的缺点:每次创建 的新实例时Monster
,实际上都是在修改Monster
类。我没有为我的Monster
新实例创建属性,而是有效地将属性添加到. 要看到这个:Monster
>>> hasattr(Monster2,"height")
False
>>> hasattr(Monster2,"has_claws")
False
>>> blue_monster = Monster2({"height":4.3,"color":"blue"})
>>> hasattr(Monster2,"height")
True
>>> hasattr(Monster2,"has_claws")
False
>>> red_monster = Monster2({"color":"red","has_claws":True})
>>> hasattr(Monster2,"height")
True
>>> hasattr(Monster2,"has_claws")
True
这当然是有道理的,因为我明确地将属性添加为类属性setattr(self.__class__,key,property(lambda self,key=key: self._traits[key]))
。我在这里需要的是可以添加到实例中的属性。(即“实例属性”)。不幸的是,根据我阅读和尝试的所有内容,属性始终是类属性,而不是实例属性。例如,这不起作用:
class Monster3(object):
def __init__(self,traits):
self._traits = traits
for key,value in traits.iteritems():
self.__dict__[key] = property(lambda self,key=key: self._traits[key])
>>> green_monster = Monster3({"color":"green"})
>>> green_monster.color
<property object at 0x028FDAB0>
所以我的问题是:“实例属性”是否存在?如果不是,原因是什么?我已经能够找到很多关于如何在 Python 中使用属性的信息,但很少了解它们是如何实现的。如果“实例属性”没有意义,我想了解原因。