69829


Pythonでクラスの属性にfor文などで順番にアクセスすることはできるのでしょうか？


CC BY-SA 4.0
2020-08-24T12:21:25.390
69828
2020-08-24T16:25:46.420
19297
question
python python3
Pythonでクラスの属性に順番にアクセスする方法


ちょっと質問が漠然としていてどのようにfor文でアクセスしたいのは不明ですが、下記のようなコードを書いてみました。

まず属性の名前を取り出して、その後その名前でforを回して属性の値を取り出しています。

[code]

    class Hoge:
      def __init__(self):
        self.ii = "foo"
        self.jj = "bar"
    
    hoge = Hoge()
    hogeKeys = hoge.__dict__.keys()
    
    print(hogeKeys)
    
    for key in hogeKeys:
      print(getattr(hoge, key))
    
[/code]

実行結果:

[code]

    dict_keys(['ii', 'jj'])
    foo
    bar
    
[/code]

値を変更したいのであれば下記のような感じです

[code]

    class Hoge:
      def __init__(self):
        self.ii = "foo"
        self.jj = "bar"
    
    hoge = Hoge()
    hogeKeys = hoge.__dict__.keys()
    
    for key in hogeKeys:
      setattr(hoge, key, "set" + key)
    
    for key in hogeKeys:
      print(getattr(hoge, key))
    
[/code]

## 参考資料

  * [python - How to access object attribute given string corresponding to name of that attribute - Stack Overflow](https://stackoverflow.com/questions/2612610/how-to-access-object-attribute-given-string-corresponding-to-name-of-that-attrib)
  * [methods - How to get instance variables in Python? - Stack Overflow](https://stackoverflow.com/questions/109087/how-to-get-instance-variables-in-python)


CC BY-SA 4.0
2020-08-24T12:32:54.767
69829
2020-08-24T12:56:22.730
2020-08-24T12:56:22.730
9008
9008
69828
answer


少しづつ仕様(アクセス範囲とか?)の違う複数の手段があるようですね。  
__slots__のように明示的に作成していないと存在しないのもありますが。  
いずれもリストとか辞書が返されるので、それを基にアクセス出来るようです。

  * @shingo.nakanishiさん回答の__dict__
  * vars()
  * dir()
  * __slots__

この辺の記事を参考に。

* * *

[Python クラスのプロパティ情報取得](http://www.ajisaba.net/python/class_property.html)  
dict系

  * object.__dict__.items()  
全プロパティの名前と値を取得

  * object.__dict__.keys()  
全プロパティの名前だけ取得

  * object.__dict__.values()  
全プロパティの値だけ取得

実質は上記dictと同じ[vars([object])](https://docs.python.org/ja/3/library/functions.html#vars)

> モジュール、クラス、インスタンス、あるいはそれ以外の __dict__ 属性を持つオブジェクトの、 __dict__ 属性を返します。

vars()についてはこちらも。  
[Pythonで変数(インスタンス)の詳細を確認する](https://qiita.com/wakoit/items/659dd0fdbb16b214454f)

* * *

[List attributes of an object](https://stackoverflow.com/q/2675028/9014308)  
承認された回答は無いですが、上記の2つの情報を含めて多数の回答があって色々と情報があります。

ここで追加されるのは[dir([object])](https://docs.python.org/ja/3/library/functions.html#dir)と[__slots__](https://docs.python.org/ja/3/reference/datamodel.html#slots)ですね。

仕様のdir()説明の抜粋

> 引数がある場合、そのオブジェクトの有効な属性のリストを返そうと試みます。  
>  オブジェクトが __dir__() という名のメソッドを持つなら、そのメソッドが呼び出され、属性のリストを返さなければなりません。  
>  オブジェクトが __dir__() を提供していない場合、定義されていればオブジェクトの __dict__
> 属性から、そして型オブジェクトから、情報を収集しようと試みます。結果のリストは完全であるとは限らず、また、カスタムの __getattr__()
> を持つ場合、不正確になるかもしれません。  
>  **注釈** dir()
> は主に対話プロンプトでの使用に便利なように提供されているので、厳密性や一貫性を重視して定義された名前のセットというよりも、むしろ興味を引くような名前のセットを返そうとします。

仕様の__slots__説明の抜粋

> __slots__ を使うと、(プロパティのように) データメンバを明示的に宣言し、 (明示的に __slots__
> で宣言しているか親クラスに存在しているかでない限り) __dict__ や __weakref__ を作成しないようにできます。

__slots__に関してはこちらの記事が詳しそうです。  
[Usage of __slots__?](https://stackoverflow.com/q/472000/9014308)  
[__slots__を定義する場合の継承に関する注意点](https://qiita.com/fumitoh/items/60f181695844daf72450)

* * *

4者の関係については上記の[回答の1つ](https://stackoverflow.com/a/60299405/9014308)に記述があって、それが注意事項でしょうか。

>   * Using `__dict__` or `vars` **does not work** because it misses out
> `__slots__`.
>   * Using `__dict__` and `__slots__` **does not work** because it misses out
> `__slots__` from base classes.
>   * Using `dir` **does not work** because it includes class attributes, such
> as methods or properties, as well as the object attributes.
>   * Using `vars` is equivalent to using `__dict__`.
>


CC BY-SA 4.0
2020-08-24T16:25:46.420
69836
2020-08-24T16:25:46.420
26370
69828
answer