或阿呆のブログ

Pythonを好んで使っているプログラマです。Ruby,Perl,PowerShell,VBAなどでもたまに書いています。おバカなことが大好きです。

インスタンス生成後に属性を参照/設定/削除する

静的型付け言語では見慣れない仕組みだったのでご紹介。

クラスAサンプルコード

>>> class A():pass
>>> a = A()
>>> dir(a)
['__doc__', '__module__']
>>> a.attr1='spam'
>>> a.attr2='ham'
>>> dir(a)
['__doc__', '__module__', 'attr1', 'attr2']
  1. クラスAを定義
  2. クラスAのインスタンスaを生成
  3. インスタンスaの属性を表示→属性は無し
  4. インスタンスaに属性attr1,attr2を追加
  5. インスタンスaの属性を表示→attr1,attr2が表示される

ついでなんで、属性の削除もやってみる。

>>> del a.attr2
>>> dir(a)
['__doc__', '__module__', 'attr1']
  1. インスタンスaから属性attr2を削除
  2. インスタンスaの属性を表示→attr1が表示される

コメント

最初は違和感があったのだけれど、Pythonの言語仕様として

  • 変数の使用時にメモリが確保される
  • クラスは、名前空間に過ぎない

という点を考慮すると、別におかしくないなと思った。

クラスBサンプルコード

>>> del B
>>> class B():
...     attr1='spam'
...     def __init__(self):
...         self.attr2='ham'
...         
>>> b = B()
>>> dir(b)
['__doc__', '__init__', '__module__', 'attr1', 'attr2']
>>> del b.attr2
>>> dir(b)
['__doc__', '__init__', '__module__', 'attr1']
>>> del b.attr1
Traceback (most recent call last):
  File "<ipython-input-17-d354cf43134f>", line 1, in <module>
    del b.attr1
AttributeError: B instance has no attribute 'attr1'
  1. クラスBを定義
  2. クラスBのインスタンスbを生成
  3. インスタンスbの属性を表示→attr1,attr2が表示される
  4. インスタンスbの属性attr2を削除
  5. インスタンスbの属性を表示→attr1が表示される
  6. インスタンスbの属性attr1を削除しようとするが、、、→attr1はクラスBの属性なので削除出来ない。

コメント

クラスAの例を理解出来ていれば、こちらも理解出来る。注意としては、クラス属性と、インスタンス属性の違いを把握しておくことかな。

クラスAの例でも記載したが、

  • 変数の使用時にメモリが確保される
  • クラスは、名前空間に過ぎない

という点は同じ。

インスタンスb生成時に、__init__関数が呼ばれ、そのタイミングでインスタンス属性attr2が生成される。クラス属性attr1は、インスタンスb生成前に既に静的に存在して、インスタンスb生成時に紐付けされるといった感じ。

attr1には、クラス名からでもアクセス出来る。

>>> B.attr1
'spam'

インスタンスのスコープよりも、クラスのスコープのほうが広いということ。

コメント

Pythonのクラス、インスタンスの概念や実装は、さっぱりしていていい感じの印象。動的型付けって便利だと思う。静的型付け言語でオブジェクト指向で実装すると、どうしてもクラスが肥大化する。Pythonのクラスシステムだと、クラス自体はコンパクトにしつつ、作りこめるんではないかと。

但し、クラスの振る舞いをインスタンスが変えてしまうことを頻繁にやると、クラスってなんなの?!ってなっちゃうので要注意。

クラスなんて名前空間に過ぎないと割り切るのも有りだと思うけど。