【Python】属性の一覧を取得する方法(2種類)

Python の各種オブジェクトが持っている属性(メンバー)の一覧を取得する方法です。

属性ぞくせいといえば attributeアトリビュート

変数名からドット . でアクセスできるメンバー変数やメンバー関数のことです。

それらの一覧を取得する方法です。

使用できる属性を探すときは、『組み込み関数の dir() 〔ディーアイアール、ダー〕』と『 inspectインスペクト モジュールの inspect.getmembers() 〔ゲットメンバース〕』が便利でした。

inspect.getmembers() は、import inspect を実行すると使用できます。

2つの使い分けです。

自分は、dir() で見つからなければ inspect.getmembers() を使う、という感じで使用しています。

dir() で属性を確認

属性名ぞくせいめい』の一覧を見るときは、Visual Studio Code のウォッチ式(ウォッチウィンドウ)に、dir(変数名) と書きます。

これで見ることができました。

デバッグモードで一時停止してから dir(変数名) を入力しました。

inspect.getmembers() で属性を確認

dir(変数名) の代わりに inspect.getmembers(変数名) を使用したら、『属性名』と『現在の値』の一覧が見れました。

さらに、属性の中から関数的かんすうてきなものを探すときは

[x for x in inspect.getmembers(変数名) if callable(x[1])]

で確認できました。callableコーラブル() は Python の組み込み関数です。

逆に、属性の中からあたいのようなものを探すときは

[x for x in inspect.getmembers(変数名) if not callable(x[1])]

で確認できました。

x[1] には『現在の属性の値(オブジェクト)』が入っていました。

それを、callable() に渡して判定しています。

Python マニュアル

Python マニュアルの場所です。

ディーアイアール関数(ダー関数)
dir([object])

インスペクト ゲットメンバース メソッド
inspect.getmembers(object[, predicate])

特殊属性の説明など
inspect 型とメンバー

コーラブル関数(呼び出し可能オブジェクトの判定)
callable(object)

使い分け

自分は、dir() で見つからなければ inspect.getmembers() を使う、という感じで使用しています。

たいていのケースでは dir() で十分でした。

ですが、一部表示されない属性もありましたので、その時は inspect.getmembers() を使用しています。

inspect.getmembers() は、『属性の種類』を選んで取得できるところが便利でした。

『属性名』と『現在の値(オブジェクト)』のタプルが取得できたので、自在に分けて表示することができました。

属性の中から、関数だけを取得したり、メソッドだけを取得したり、値だけを取得したり、といったことができました。

inspect.getmembers() が列挙した属性の数は、dir() と同じか、それよりも多かったです。

__class____name__ などの特殊属性とくしゅぞくせいも、すべてチェックすることができました。

モジュールをインポート import inspect しておく必要がありましたが、dir() で見つからなかったときは、inspect.getmembers() が便利でした。

dir() の使用例

BeautifulSoup に dir() を使用したコード例です。

"""attribute_dir.py"""
from bs4 import BeautifulSoup

# HTML ソースを決める
source = """<!DOCTYPE html><html lang="ja">
<head><meta charset="UTF-8"><title>タイトル</title></head>
<body><h1>見出し</h1><p>本文。</p></body>
</html>"""

# BeautifulSoup のオブジェクトを取得
soup = BeautifulSoup(source, features="html.parser")

# 属性 (attribute、メンバー) を取得
attributes = dir(soup)

# 属性を表示
n_max = len(attributes)
for (n, attribute) in enumerate(attributes, start=1):
    print(f'{n}/{n_max} {attribute}')

    # (表示例)
    # 1/180 ASCII_SPACES
    # 2/180 DEFAULT_BUILDER_FEATURES   
    # 3/180 NO_PARSER_SPECIFIED_WARNING
    # 4/180 ROOT_TAG_NAME
    # 5/180 __bool__
    # 6/180 __call__
    # 7/180 __class__
    # 8/180 __contains__
    # ...
    # 179/180 unwrap
    # 180/180 wrap

inspect.getmembers() の使用例

BeautifulSoup に inspect.getmembers() を使用したコードです。

『すべての属性を取得する場合』と『属性の種類を指定して取得する場合』のコード例を書きました。

すべての属性を取得

inspect.getmembers() に、調べたいオブジェクトを渡しています。

"""attribute_getmembers_all.py"""
import inspect
from bs4 import BeautifulSoup

# HTML ソースを決める
source = """<!DOCTYPE html><html lang="ja">
<head><meta charset="UTF-8"><title>タイトル</title></head>
<body><h1>見出し</h1><p>本文。</p></body>
</html>"""

# BeautifulSoup のオブジェクトを取得
soup = BeautifulSoup(source, features="html.parser")

# すべての属性 (attribute、メンバー) を取得
attributes = inspect.getmembers(soup)

# 属性を表示
n_max = len(attributes)
for (n, (attribute, value)) in enumerate(attributes, start=1):
    print(f'{n}/{n_max} {attribute} {type(value)}')

    # (表示例)
    # 1/180 ASCII_SPACES <class 'str'>
    # 2/180 DEFAULT_BUILDER_FEATURES <class 'list'>  
    # 3/180 NO_PARSER_SPECIFIED_WARNING <class 'str'>
    # 4/180 ROOT_TAG_NAME <class 'str'>
    # 5/180 __bool__ <class 'method'>
    # 6/180 __call__ <class 'method'>
    # 7/180 __class__ <class 'type'>
    # 8/180 __contains__ <class 'method'>
    # ...
    # 179/180 unwrap <class 'method'>
    # 180/180 wrap <class 'method'>

属性の種類を指定して取得

inspect.getmembers() で、調べたいオブジェクトに加えて、取得する『オブジェクトの種類』を渡しています。

また、組み込み関数の callable() を使用して、『関数的なもの』と『値のようなもの』をそれぞれ分けて取得しています。

これで、属性がたくさんあったケースでも、だいぶ探しやすくなりました。

"""attribute_getmembers_type.py"""
import inspect
from bs4 import BeautifulSoup

# HTML ソースを決める
source = """<!DOCTYPE html><html lang="ja">
<head><meta charset="UTF-8"><title>タイトル</title></head>
<body><h1>見出し</h1><p>本文。</p></body>
</html>"""

# BeautifulSoup のオブジェクトを取得
soup = BeautifulSoup(source, features="html.parser")


print('(1/5) 属性から『メソッド (method)』を取得 & 表示')
attributes = inspect.getmembers(soup, inspect.ismethod)
n_max = len(attributes)
for (n, (attribute, value)) in enumerate(attributes, start=1):
    print(f'{n}/{n_max} {attribute} {type(value)}')

    # (メソッドの表示例)
    # 1/106 __bool__ <class 'method'>
    # 2/106 __call__ <class 'method'>
    # 3/106 __contains__ <class 'method'>
    # 4/106 __copy__ <class 'method'>
    # 5/106 __delitem__ <class 'method'>
    # 6/106 __eq__ <class 'method'>
    # 7/106 __getattr__ <class 'method'>
    # ...
    # 105/106 unwrap <class 'method'>
    # 106/106 wrap <class 'method'>


print('\n(2/5) 属性から『関数 (function)』を取得 & 表示')
attributes = inspect.getmembers(soup, inspect.isfunction)
n_max = len(attributes)
for (n, (attribute, value)) in enumerate(attributes, start=1):
    print(f'{n}/{n_max} {attribute} {type(value)}')

    # (関数の表示例)
    # 1/1 _check_markup_is_url <class 'function'>


print('\n(3/5) 属性から『ジェネレーター (generator)』を取得 & 表示')
attributes = inspect.getmembers(soup, inspect.isgenerator)
n_max = len(attributes)
for (n, (attribute, value)) in enumerate(attributes, start=1):
    print(f'{n}/{n_max} {attribute} {type(value)}')

    # (ジェネレーターの表示例)
    # 1/8 descendants <class 'generator'>
    # 2/8 next_elements <class 'generator'>
    # 3/8 next_siblings <class 'generator'>
    # 4/8 parents <class 'generator'>
    # 5/8 previous_elements <class 'generator'>
    # 6/8 previous_siblings <class 'generator'>
    # 7/8 strings <class 'generator'>
    # 8/8 stripped_strings <class 'generator'>


print('\n(4/5) 属性を取得 &『カッコ()を付けて呼び出せるもの』を表示')
attributes = inspect.getmembers(soup)
attributes = [x for x in attributes if callable(x[1])]
n_max = len(attributes)
for (n, (attribute, value)) in enumerate(attributes, start=1):
    print(f'{n}/{n_max} {attribute} {type(value)}')

    # (callable な属性の表示例)
    # 1/126 __bool__ <class 'method'>
    # 2/126 __call__ <class 'method'>
    # 3/126 __class__ <class 'type'>
    # 4/126 __contains__ <class 'method'>
    # 5/126 __copy__ <class 'method'>
    # 6/126 __delattr__ <class 'method-wrapper'>
    # ...
    # 24/126 __ne__ <class 'method'>
    # 25/126 __new__ <class 'builtin_function_or_method'>
    # 26/126 __reduce__ <class 'builtin_function_or_method'>
    # ...
    # 48/126 currentTag <class 'bs4.BeautifulSoup'>
    # 49/126 decode <class 'method'>
    # ...
    # 125/126 unwrap <class 'method'>
    # 126/126 wrap <class 'method'>


print('\n(5/5) 属性を取得 &『カッコ()を付けて呼び出せないもの』を表示')
attributes = inspect.getmembers(soup)
attributes = [x for x in attributes if not callable(x[1])]
n_max = len(attributes)
for (n, (attribute, value)) in enumerate(attributes, start=1):
    print(f'{n}/{n_max} {attribute} {type(value)}')

    # (not callable な属性の表示例)
    # 1/54 ASCII_SPACES <class 'str'>
    # 2/54 DEFAULT_BUILDER_FEATURES <class 'list'>
    # 3/54 NO_PARSER_SPECIFIED_WARNING <class 'str'>
    # 4/54 ROOT_TAG_NAME <class 'str'>
    # 5/54 __dict__ <class 'dict'>
    # 6/54 __doc__ <class 'str'>
    # 7/54 __module__ <class 'str'>
    # 8/54 __weakref__ <class 'NoneType'>
    # 9/54 _is_xml <class 'bool'>
    # ...
    # 50/54 string <class 'NoneType'>
    # 51/54 strings <class 'generator'>
    # 52/54 stripped_strings <class 'generator'>
    # 53/54 tagStack <class 'list'>
    # 54/54 text <class 'str'>
タイトルとURLをコピーしました