ユーニックス総合研究所

  • home
  • archives
  • python-zokusei-ichiran

Pythonで属性の一覧の取得と属性のフィルタリング。他、関連技術

  • 作成日: 2023-06-26
  • 更新日: 2023-12-24
  • カテゴリ: Python

Pythonで属性の一覧の取得

Pythonでオブジェクトなどの属性の一覧を取得するにはdir()関数を使います。
dir()の第1引数にオブジェクトを指定するとリストで属性の文字列が返ってきます。

class Animal:  
    def __init__(self):  
        self.age = 20  
        self.name = 'Tama'  

    def walk(self):  
        print('walking...')  


print(dir(Animal))  
# ['__class__', '__delattr__', '__dict__', '__dir__',   
#  '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',   
#  '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__',   
#  '__lt__', '__module__', '__ne__', '__new__', '__reduce__',   
#  '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',   
#  '__subclasshook__', '__weakref__', 'walk']  

animal = Animal()  
print(dir(animal))  
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',   
#  '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',   
#  '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__',   
#  '__module__', '__ne__', '__new__', '__reduce__',   
#  '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',   
#  '__subclasshook__', '__weakref__', 'age', 'name', 'walk']  

上記は独自クラスのAnimaldir()で見た場合です。
dir(Animal)でクラスの属性を取得しています。このときself.ageself.nameはありません。
これはこれらの属性が__init__()で代入されるからです。

animal = Animal()Animalをオブジェクトにしてdir(animal)で属性の一覧を取得しています。
こちらにはagenameがあります。これはオブジェクト化のさいに__init__()が呼ばれてself.ageself.nameが代入されたからです。

属性の有無の判定

dir()が返すのは文字列のリストなのでin演算子を使えば特定の属性の有無は判定できます。

class Animal:  
    def __init__(self):  
        self.age = 20  
        self.name = 'Tama'  

    def walk(self):  
        print('walking...')  


print('age' in dir(Animal))  
# False  

animal = Animal()  
print('age' in dir(animal))  
# True  

しかしPythonにはhasattr()関数があり、これを使えばもっと簡単に属性の有無を判定できます。

class Animal:  
    def __init__(self):  
        self.age = 20  
        self.name = 'Tama'  

    def walk(self):  
        print('walking...')  


print(hasattr(Animal, 'age'))  
# False  

animal = Animal()  
print(hasattr(animal, 'age'))  
# True  

属性のフィルタリング

__」で始まる属性を除外するフィルタリングは以下のように行います。

class Animal:  
    def __init__(self):  
        self.age = 20  
        self.name = 'Tama'  

    def walk(self):  
        print('walking...')  


animal = Animal()  
attrs = [attr for attr in dir(animal) if not attr.startswith('__')]         
print(attrs)  
# ['age', 'name', 'walk']  

リスト内包表記でdir(animal)の結果を回しています。
リスト内包表記は

リスト = [格納したい要素 for 要素 in リストなど]  

という感じの表記です。
これはfor文を簡略化した表記になっています。
上記の場合はリストなどから要素が1つずつ回り、それを格納したい要素に書くことで新しいリストに要素が格納されます。

この格納したい要素に条件を加えたい場合は

リスト = [格納したい要素 for 要素 in リストなど if 条件式]  

という感じでお尻にifを加えます。

🦝 < すげー表記方法だ

🦝 < 溜息が出るな

この条件にif not attr.startswith('__')と書いています。
startswith()は文字列のメソッドで、これは文字列の先頭が引数と同じかどうか判定します。
つまり文字列の先頭が__だったらTrueを返します。これをnotで反転していますので、このif文の条件は「文字列の先頭が__じゃなかったらTrue」という条件になります。
Trueの場合は「格納したい要素」が新しいリストに格納されるので、これによって__がついている属性は除外されます。

複数のメソッドをまとめて呼び出し

クラスにメソッドが複数定義されていて、それを一括で呼び出したい場合などは属性の一覧を使った方法が使えます。

class Animal:  
    def walk(self):  
        print('walking...')  

    def run(self):  
        print('running...')  

    def dance(self):  
        print('dancing...')  


animal = Animal()  

# __が付いている属性を除外  
attrs = [attr for attr in dir(animal) if not attr.startswith('__')]         

# メソッドの属性をfor文ですべて呼び出し  
for attr in attrs:  
    method = getattr(animal, attr)  # 属性の実体を取得  
    method()  

# dancing...  
# running...  
# walking...  

まず__が付いている属性をdir()とリスト内包表記で除外します。
こうするとメソッドを抽出できます。もっともインスタンス変数も取得できますのでこの辺はまた別で除外する必要があります。

あとはこの除外した結果のattrsfor文で回してgetattr()関数でanimalから属性の実体を取り出します。
getattr()関数は第1引数のオブジェクトから第2引数の属性の実体を取り出す関数です。
これで取り出したmethodを実行すればwalk(), run(), dance()のメソッドを一括で呼び出せます。

🦝 < トリッキーですね

🦝 < せやな

おわりに

今回はPythonの属性の一覧の取得と関連技術を解説しました。
なにか参考になれば幸いです。

🦝 < 属性をまとめてゲット!

🦝 < フィルタリングしてシュート!