動的プロパティを持つクラスを作成しようとしています。2 つの読み取り専用プロパティを持つ次のクラスを考えてみましょう。
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 でプロパティがどのように使用されているかについては多くのことを見つけることができましたが、プロパティがどのように実装されているかについてはほとんど知りませんでした。「インスタンス プロパティ」が意味をなさない場合は、その理由を理解したいと思います。