オブジェクトのタイプを決定しますか?

2010年02月09日に質問されました。  ·  閲覧回数 1.8M回  ·  ソース

Justin Ethier picture
2010年02月09日

変数がリスト、辞書、またはその他のものであるかどうかを判断する簡単な方法はありますか? どちらのタイプのオブジェクトも返されますが、違いがわかる必要があります。

回答

poke picture
2010年02月09日
2042

オブジェクトのタイプを識別するのに役立つ2つの組み込み関数があります。 オブジェクトの正確なタイプが必要な場合はtype() isinstance()使用でき、オブジェクトのタイプを何かとisinstance()使用できます。 通常、 isistance()は非常に堅牢であり、型の継承もサポートしているため、ほとんどの場合使用する必要があります。


オブジェクトの実際のタイプを取得するには、組み込みのtype()関数を使用します。 オブジェクトを唯一のパラメータとして渡すと、そのオブジェクトのタイプオブジェクトが返されます。

>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True

もちろん、これはカスタムタイプでも機能します。

>>> class Test1 (object):
        pass
>>> class Test2 (Test1):
        pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True

type()はオブジェクトの直接の型のみを返しますが、型の継承については教えてくれないことに注意してください。

>>> type(b) is Test1
False

これをカバーするには、 isinstance関数を使用する必要があります。 もちろん、これは組み込みタイプでも機能します。

>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True

isinstance()は、派生型も受け入れるため、通常、オブジェクトの型を確認するための推奨される方法です。 したがって、(何らかの理由で)実際に型オブジェクトが必要でない限り、 type()よりもisinstance()を使用することをお勧めします。

isinstance()の2番目のパラメーターもタイプのタプルを受け入れるため、一度に複数のタイプをチェックすることができます。 オブジェクトが次のいずれかのタイプの場合、 isinstanceはtrueを返します。

>>> isinstance([], (tuple, list, set))
True
brettkelly picture
2010年02月09日
175

type()を使用してそれを行うことができます:

>>> a = []
>>> type(a)
<type 'list'>
>>> f = ()
>>> type(f)
<type 'tuple'>
Seth Johnson picture
2010年02月09日
40

try ... exceptブロックを使用する方がPythonicである可能性があります。 そうすれば、リストのように鳴くクラスやdictのように鳴くクラスがある場合、そのタイプが実際に何であるかに関係なく、適切に動作します。

明確にするために、変数タイプ間の「違いを伝える」ための好ましい方法は、ダックタイピングと呼ばれるものを使用することです。変数が応答するメソッド(および戻り値の型)がサブルーチンが期待するものである限り、期待どおりに扱います。することが。 たとえば、ブラケット演算子をgetattrsetattrでオーバーロードするクラスがあるが、面白い内部スキームを使用している場合、それが辞書として動作するのが適切です。エミュレートしようとしています。

type(A) is type(B)チェックのもう1つの問題は、 ABサブクラスである場合、プログラムでfalseと評価されることです。 trueます。 オブジェクトがリストのサブクラスである場合、それはリストのように機能するはずです。他の回答に示されているようにタイプをチェックすると、これを防ぐことができます。 (ただし、 isinstanceは機能します)。

Lorenzo Persichetti picture
2013年06月27日
34

オブジェクトのインスタンスには、次のものもあります。

__class__

属性。 これはPython3.3コンソールから取得したサンプルです

>>> str = "str"
>>> str.__class__
<class 'str'>
>>> i = 2
>>> i.__class__
<class 'int'>
>>> class Test():
...     pass
...
>>> a = Test()
>>> a.__class__
<class '__main__.Test'>

python 3.xおよびNew-Styleクラス(オプションでPython 2.6から利用可能)では、クラスとタイプがマージされており、予期しない結果が生じる可能性があることに注意してください。 主にこの理由から、タイプ/クラスをテストする私のお気に入りの方法は、組み込み関数の

Aaron Hall picture
2017年03月15日
21

Pythonオブジェクトのタイプを判別する

typeオブジェクトのタイプを判別します

>>> obj = object()
>>> type(obj)
<class 'object'>

それは機能しますが、 __class__ような二重アンダースコア属性は避けてください-それらは意味的に公開されておらず、おそらくこの場合ではありませんが、組み込み関数は通常より良い動作をします。

>>> obj.__class__ # avoid this!
<class 'object'>

型チェック

変数がリスト、辞書、またはその他のものであるかどうかを判断する簡単な方法はありますか? どちらのタイプのオブジェクトも返されますが、違いがわかる必要があります。

それは別の質問です。タイプは使用しないでください。 isinstanceください。

def foo(obj):
    """given a string with items separated by spaces, 
    or a list or tuple, 
    do something sensible
    """
    if isinstance(obj, str):
        obj = str.split()
    return _foo_handles_only_lists_or_tuples(obj)

これは、ユーザーがstrサブクラス化することによって巧妙または賢明なことをしている可能性がある場合をカバーします-Liskov Substitutionの原則に従って、コードを壊すことなくサブクラスインスタンスを使用できるようにしたい-そしてisinstanceはこれをサポートしています。

抽象化を使用する

さらに良いことに、 collectionsまたはnumbersから特定の抽象基本クラスを探すことができます。

from collections import Iterable
from numbers import Number

def bar(obj):
    """does something sensible with an iterable of numbers, 
    or just one number
    """
    if isinstance(obj, Number): # make it a 1-tuple
        obj = (obj,)
    if not isinstance(obj, Iterable):
        raise TypeError('obj must be either a number or iterable of numbers')
    return _bar_sensible_with_iterable(obj)

または、明示的にタイプチェックしないでください

または、おそらく何よりも、ダックタイピングを使用し、コードを明示的に型チェックしないでください。 ダックタイピングは、より優雅で冗長性の少ないリスコフの置換をサポートします。

def baz(obj):
    """given an obj, a dict (or anything with an .items method) 
    do something sensible with each key-value pair
    """
    for key, value in obj.items():
        _baz_something_sensible(key, value)

結論

  • typeを使用して、実際にインスタンスのクラスを取得します。
  • isinstanceを使用して、実際のサブクラスまたは登録された抽象化を明示的にチェックします。
  • そして、それが理にかなっているところでは型チェックを避けてください。
deed02392 picture
2014年06月01日
13

type()またはisinstance()を使用できます。

>>> type([]) is list
True

同じ名前の現在のスコープに変数を割り当てることで、 listまたはその他のタイプを壊す可能性があることに注意してください。

>>> the_d = {}
>>> t = lambda x: "aight" if type(x) is dict else "NOPE"
>>> t(the_d) 'aight'
>>> dict = "dude."
>>> t(the_d) 'NOPE'

上記では、 dictが文字列に再割り当てされるため、次のテストが行​​われます。

type({}) is dict

...失敗します。

これを回避し、 type()より慎重に使用するには:

>>> import __builtin__
>>> the_d = {}
>>> type({}) is dict
True
>>> dict =""
>>> type({}) is dict
False
>>> type({}) is __builtin__.dict
True
Alan Franzoni picture
2016年06月17日
5

質問はかなり古いですが、私は自分で適切な方法を見つけているときにこれに遭遇しました、そして少なくともPython 2.x (Python 3ではチェックしませんでしたが、問題はクラシッククラスで発生する

ここで私はタイトルの質問に答えようとしています:どうすれば任意のオブジェクトのタイプを判別できますか? isinstanceを使用するかどうかに関する他の提案は、多くのコメントと回答で問題ありませんが、私はそれらの懸念に対処していません。

type()アプローチの主な問題は、古いスタイルのインスタンスでは正しく機能しないことです。

class One:
    pass

class Two:
    pass


o = One()
t = Two()

o_type = type(o)
t_type = type(t)

print "Are o and t instances of the same class?", o_type is t_type

このスニペットを実行すると、次のようになります。

Are o and t instances of the same class? True

これは、ほとんどの人が期待することではないと私は主張します。

__class__アプローチは最も正確に近いですが、1つの重要なケースでは機能しません。渡されたオブジェクトが古いスタイルのクラス(インスタンスではない!)である場合、それらのオブジェクトにはそのようなものがないためです。属性。

これは、一貫した方法でそのような正当な質問を満たすと私が考えることができる最小のコードスニペットです。

#!/usr/bin/env python
from types import ClassType
#we adopt the null object pattern in the (unlikely) case
#that __class__ is None for some strange reason
_NO_CLASS=object()
def get_object_type(obj):
    obj_type = getattr(obj, "__class__", _NO_CLASS)
    if obj_type is not _NO_CLASS:
        return obj_type
    # AFAIK the only situation where this happens is an old-style class
    obj_type = type(obj)
    if obj_type is not ClassType:
        raise ValueError("Could not determine object '{}' type.".format(obj_type))
    return obj_type
tnusraddinov picture
2017年11月14日
5

isinstanceの使用には注意してください

isinstance(True, bool)
True
>>> isinstance(True, int)
True

しかしタイプ

type(True) == bool
True
>>> type(True) == int
False
Dimitris Fasarakis Hilliard picture
2016年12月07日
3

前の回答とは別に、ダックタイピングを補完するいくつかの抽象基本クラス(ABC)を含むcollections.abcの存在に言及する価値があります。

たとえば、何かが次のようなリストであるかどうかを明示的にチェックする代わりに、

isinstance(my_obj, list)

持っているオブジェクトがアイテムの取得を許可しているかどうかだけを確認したい場合は、 collections.abc.Sequence使用できます。

from collections.abc import Sequence
isinstance(my_obj, Sequence) 

アイテムの取得、設定削除を可能にするオブジェクト(つまり、可変シーケンス)に厳密に関心がある場合は、 collections.abc.MutableSequenceます。

他の多くのABCがそこで定義されています。マップとして使用できるオブジェクトの場合はMappingIterableCallableなどです。 これらすべての完全なリストはcollections.abcドキュメントで確認できます

Jos&#233; Crespo Barrios picture
2019年06月17日
1

一般に、クラス名を持つオブジェクトから文字列を抽出できます。

str_class = object.__class__.__name__

比較のためにそれを使用して、

if str_class == 'dict':
    # blablabla..
elif str_class == 'customclass':
    # blebleble..