Python の各種オブジェクトが持っている属性(メンバー)の一覧を取得する方法です。
属性といえば attribute。
変数名からドット .
でアクセスできるメンバー変数やメンバー関数(メソッド)のことです。
それらの一覧を取得する方法です。
使用できる属性を探すときは、『組み込み関数の dir()
〔ディーアイアール、ダー〕』と『 inspect
モジュールの inspect.getmembers()
〔ゲットメンバース〕』が便利でした。
inspect.getmembers()
は、import inspect
を実行すると使用できます。
2つの使い分けです。
自分は、dir()
で見つからなければ inspect.getmembers()
を使う、という感じで使用しています。
ほかにも、自作クラスの設定確認をしたい時などには、組み込み関数の vars()
〔バース〕 が便利でした。dir()
関数と同じ手軽さで使用することができて、『属性の名前』と『属性の値』を辞書として確認することができました。
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 マニュアルの場所です。
ディーアイアール関数(ダー関数)
(Python) dir([object])
インスペクト ゲットメンバース メソッド
(Python) inspect.getmembers(object[, predicate])
特殊属性の説明など
(Python) inspect 型とメンバー
コーラブル関数(呼び出し可能オブジェクトの判定)
(Python) callable(object)
属性(Attribute)の説明。
method の説明。
(Python) 関数を定義する(Python チュートリアル)
(Python) メソッドとは何ですか?(Python よくある質問 ⇒ プログラミング FAQ)
使い分け
自分は、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'>
vars() で __dict__ 属性を確認
ほかにも、コード例は省略しますが、組み込み関数の vars()
がとても便利でした。使い方は、vars(変数名)
と書くだけでした。
(Python) vars([object])
バース関数
変数に入れたオブジェクトが __dict__
属性を持つ場合に限られましたが、変数名からドット .
でアクセスできる『属性名』と『属性の値』が、『辞書 <class 'dict'>
』や『辞書のように参照できる型 <class 'mappingproxy'>
』として取得できました。
例えば、『自作クラス』に対して vars()
が使用できました。『属性名と値の一覧』が辞書として確認できて、便利でした。
そのほか、『logging
モジュールで取得したロガーの設定』を確認するときにも、vars()
関数が便利でした。『ロガーの名前、ロギングレベルの設定、propagate
属性の設定、ロガーに設定したハンドラのリスト』などの状況が、簡単に確認できました。
以上です。
⇒ 【Python】ロガーでロギングするコード例【logging】