我正在尝试编写一个具有动态属性的类.考虑以下具有两个只读属性的类:
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
Run Code Online (Sandbox Code Playgroud)
我想概括这一点,以便__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]))
Run Code Online (Sandbox Code Playgroud)
但是,这有一个严重的缺点:每次我创建一个新实例时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
Run Code Online (Sandbox Code Playgroud)
这当然是有道理的,因为我明确地将属性添加为类属性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>
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:"实例属性"存在吗?如果没有,原因是什么?我已经能够找到很多关于如何在Python中使用属性的内容,但关于如何实现它们却很少见.如果"实例属性"没有意义,我想了解原因.
不,没有每个实例属性这样的东西; 像所有描述符一样,属性总是在类上查找.请参阅描述符HOWTO以确切了解其工作原理.
您可以使用__getattr__钩子来实现动态属性,它可以动态检查实例属性:
class Monster(object):
def __init__(self, traits):
self._traits = traits
def __getattr__(self, name):
if name in self._traits:
return self._traits[name]
raise AttributeError(name)
Run Code Online (Sandbox Code Playgroud)
但这些属性并不是真正的动态; 你可以直接在实例上设置这些:
class Monster(object):
def __init__(self, traits):
self.__dict__.update(traits)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
394 次 |
| 最近记录: |