2017-10-03 6 views
4

Pythonでは、先に定義したクラスCに属性を追加できます。しかし、私はlistに属性を追加することはできません - 結果のエラーメッセージがlistがビルトインされているため、タイプであると説明していますPythonのどのオブジェクトに属性を動的に追加できますか?

同様
>>> class C: pass 
... 
>>> C.foo = 1 
>>> C.foo 
1 

>>> list.foo = 1 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can't set attributes of built-in/extension type 'list' 

Cのインスタンスに属性を追加することは可能であるが、 listのインスタンスではありません。しかし、この場合には、エラーメッセージがはるかにあいまいです:

>>> o = C() 
>>> o.bar = 2 
>>> o.bar 
2 

>>> o = [] 
>>> o.bar = 2 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'list' object has no attribute 'bar' 

なぜlistのインスタンスにメンバーを追加することはできませんか? listはビルトインタイプなので、もう一度ですか?

Pythonでオブジェクトをより一般的に

は、動的に追加された属性を持つことができますか?

+0

組み込み型でないものがあります。 –

+0

強く関連しています。https://stackoverflow.com/questions/6738987/extension-method-for-python-built-in-types –

答えて

1

オブジェクト上の任意のプロパティを設定し、これを効果的にオブジェクトの__dict__変異します。 __dict__は、オブジェクトのすべてのメンバーを格納する辞書です。オブジェクトにメンバーを追加するには、次の2つの条件があります。

  1. オブジェクトには__dict__が必要です。
  2. オブジェクトの__dict__は変更可能である必要があります。

これらの条件のいずれかに該当することがないかもしれないいくつかの理由があります。タイプの次のカテゴリは通常は、オブジェクトの変更を許可しないだろう。

  • が内蔵ネイティブタイプは、ネイティブコードで実装され、メンバーの固定セットを持って、彼らのネイティブオブジェクト定義に焼いています。例としては、intstrlistbytes、...おそらく最も(すべてではない)例numpyのもののための外部ライブラリからbuilt-in types
  • ネイティブ種類が含まれます。
  • __slots__を使用している任意のPythonクラス。 Slotsは、__dict__を有効にして固定されたメンバーセットで置き換える明示的な方法です。明らかに、これは後でオブジェクトへの追加を防ぐ(設計ごとに)。

あなたがオブジェクトを変更できるかどうかを検出するための良い方法は何ですか?さて、上から条件をチェックしてください。オブジェクトが__dict__を持っているかどうか:

>>> class Example: 
     pass 
>>> class SlotsExample: 
     __slots__ = ['x'] 

>>> hasattr(Example(), '__dict__') 
True 
>>> hasattr(SlotsExample(), '__dict__') 
False 
>>> hasattr(list, '__dict__') 
True 
>>> hasattr([], '__dict__') 
False 

そして__dict__が本当の辞書であるかどうか:要するに

>>> isinstance(Example().__dict__, dict) 
True 
>>> isinstance(list.__dict__, dict) 
False 
0

、それは__setattr__マジックメソッドに依存します。

Pythonの属性は__getattr____setattr__を介して検索されています。それがないクラスがある場合、デフォルトが適用されます。 (スロットは少し異なります。)

組み込み/拡張タイプ(CPythonではHEAPTYPE)の場合、デフォルトで他の属性を追加することはできませんが、別の機能を提供することでオーバーライドできます。 (純粋なPythonでは使えません)

関連する問題