オブジェクトがNamed tupleのインスタンスであるかどうかを確認するにはどうすればよいですか?
7 に答える
関数 を呼び出すと、項目がすべて文字列であるタプルであるという名前のメンバーを持つ (他のクラスではない) のcollections.namedtuple
サブクラスである新しい型が得られます。したがって、次のことをすべて確認できます。tuple
_fields
def isnamedtupleinstance(x):
t = type(x)
b = t.__bases__
if len(b) != 1 or b[0] != tuple: return False
f = getattr(t, '_fields', None)
if not isinstance(f, tuple): return False
return all(type(n)==str for n in f)
これにより誤検知が発生する可能性がありますが、名前付きタプルによく似ているが名前付きタプルではない型を誰かが作成しようとしている場合に限られます;-)。
オブジェクトが特定の名前付きタプルのインスタンスであるかどうかを判断したい場合は、次のようにすることができます。
from collections import namedtuple
SomeThing = namedtuple('SomeThing', 'prop another_prop')
SomeOtherThing = namedtuple('SomeOtherThing', 'prop still_another_prop')
a = SomeThing(1, 2)
isinstance(a, SomeThing) # True
isinstance(a, SomeOtherThing) # False
3.7+
def isinstance_namedtuple(obj) -> bool:
return (
isinstance(obj, tuple) and
hasattr(obj, '_asdict') and
hasattr(obj, '_fields')
)
Improving on what Lutz posted:
def isinstance_namedtuple(x):
return (isinstance(x, tuple) and
isinstance(getattr(x, '__dict__', None), collections.Mapping) and
getattr(x, '_fields', None) is not None)
その上でnamedtuple固有の関数を呼び出す前にチェックする必要がある場合は、代わりにそれらを呼び出して例外をキャッチしてください。これは、Python でそれを行うための推奨される方法です。
私が使う
isinstance(x, tuple) and isinstance(x.__dict__, collections.abc.Mapping)
これは、名前付きタプルの性質の辞書的側面を最もよく反映しているように思えます。考えられる将来の変更に対しても堅牢に見えます。また、そのようなものが存在する場合、多くのサードパーティの名前付きタプル風のクラスでも動作する可能性があります。
IMO これは、 Python 3.6以降に最適なソリューションである可能性があります。
__module__
名前付きタプルをインスタンス化するときにカスタムを設定し、後で確認できます
from collections import namedtuple
# module parameter added in python 3.6
namespace = namedtuple("namespace", "foo bar", module=__name__ + ".namespace")
次に確認します__module__
if getattr(x, "__module__", None) == "xxxx.namespace":