Pythonでオブジェクトに属性があるかどうかを知る方法


1635

Pythonでオブジェクトに属性があるかどうかを判断する方法はありますか?例えば:

>>> a = SomeClass()
>>> a.someProperty = value
>>> a.property
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: SomeClass instance has no attribute 'property'

それを使用する前にa、属性があるかどうかをどのように確認できますpropertyか?

回答:


2343

試してくださいhasattr()

if hasattr(a, 'property'):
    a.property

編集:許しを求めることについての良いアドバイスを提供する以下のzweiterlindeの答えを見てください!非常にpythonicなアプローチ!

Pythonでの一般的な方法は、ほとんどの場合、プロパティが存在する可能性が高い場合は、それを呼び出して例外を伝播させるか、try / exceptブロックでトラップすることです。これはおそらくよりも速くなりhasattrます。ほとんどの場合、プロパティが存在しない可能性がある場合、または確信がない場合はhasattr、例外ブロックに繰り返し陥るよりも使用する方が速いでしょう。


19
名前空間の関数をチェックするためにも機能しているようです。例: import string hasattr(string, "lower")
riviera

15
hasattrtry/ を使用するのとまったく同じexcept AttributeErrorです。hasattrのdocstring(Python 2.7の場合)は、getattrハンドキャッチ例外を使用すると言っています
Jeff Tratner、2012

8
@JeffTratner:hasattr残念ながらできません正確に同じtry: ... except AttributeError:以来のPython 2.xでhasattrますすべての例外をキャッチ。例と簡単な回避策については、私の回答を参照しください。
マーティンガイスラー

632

以下のようジャレットハーディは答えた、hasattrトリックを行います。ただし、Pythonコミュニティの多くの人が、「飛躍する前に見る」(LBYL)ではなく、「許可よりも許しを求める方が簡単」(EAFP)の戦略を推奨していることを付け加えておきます。次の参考文献をご覧ください。

EAFP vs LBYL(Re:これまでのところ少しがっかりした)
EAFP vs. LBYL @Pythonのような@コード:慣用的なPython

つまり:

try:
    doStuff(a.property)
except AttributeError:
    otherStuff()

...の方が望ましい:

if hasattr(a, 'property'):
    doStuff(a.property)
else:
    otherStuff()

258
しかし、どのようにしてそれがAttributeErrorを引き起こしたのがa.propertyであり、doStuff()の何かではなかったことを確認しますか?あなたはそうではないようです。許しを求める方が本当に簡単だと思いますが、多くの場合、それも正しくありません。
jpalecek 2009

285
EAFPは……正気ではないようです。HasAttrは、特定の属性をチェックしていることを将来のメンテナンスプログラマに通知します。例外が発生しても、将来のプログラマーには何も通知されず、誰かをうさぎの穴に追い込む可能性があります。
Ethan Heilman、

74
@ e5:この場合は公平な点がありますが、多くの場合、EAFPが唯一の正しいオプションです。たとえば、ファイルの存在を確認してから開いた場合、そのファイルが確実に存在すると想定して、コードが間違っています。チェックと使用の間にファイルが削除または名前変更される可能性があります。これはTOCTOUエラー(Time-Of-Check-To-Time-Of-Use)と呼ばれ、クラッシュを引き起こすだけでなく、セキュリティの脆弱性の原因にもなります。
マックス

15
@EthanHeilman例外の原因に曖昧さが存在する場合にのみ異常であり、ほとんどの場合、適切な設計で回避できます。try / except /内のロジックの適切に階層化された構造は、最終的に一般に、消費する各コードのプリエンプティブifチェックでコードを散らかすよりも、より堅牢な(プログラマエラーが発生しやすい)ロジックになります。エラーも非常に明確にし、プログラマーがエラーを直接処理するオプションを許可します。
Peter M. Elias

64
ここでの曖昧な不満のほとんどは、サンプルコードの構造が不十分なためです。内部の唯一のものtry:は、試みられた属性アクセスです。doStuff同様に実行をラップする理由はありません。ただし、あいまいさが生じる可能性はまだあります。propertyプレーンな属性ではなく計算されたプロパティの場合、その実装はAttributeError内部で発生する可能性があります。これが、このようなほとんどすべての実際の状況でgetattrhasattrやのいずれかよりも好ましい理由AttributeErrorです。
カールマイヤー

485

を使用しhasattr()たりキャッチしたりできAttributeErrorますが、属性の値がなく、デフォルトがない場合は、次のように使用することをお勧めしますgetattr()

getattr(a, 'property', 'default value')

14
これにより、前述の両方の問題が解決されます。a)考えられるAttributeErrorのソースのあいまいさ、b)EAFPアプローチを維持します。
Peter M. Elias

6
また、コード行の25%です。確かにこれが最善の解決策でなければなりません。
fatuhoku 2013

16
これは、「デフォルトで属性の値が本当に必要な場合」に最適なソリューションです。多くの人が属性が存在するかどうかを検出したいと言ったときにこれが実際に必要なことだと思いますが、OPは実際に後者を要求したので、その質問(hasattr、AttributeError)への直接の回答が上位にリストされているのは妥当です。
Carl Meyer

41

あなたが探しているのはhasattrだと思います。ただし、Pythonのプロパティを検出する場合は、このようなものをお勧めします -

try:
    getattr(someObject, 'someProperty')         
except AttributeError:
    print "Doesn't exist"
else
    print "Exists"

ここでの欠点は、プロパティ__get__コードの属性エラーもキャッチされることです。

それ以外の場合は、

if hasattr(someObject, 'someProp'):
    #Access someProp/ set someProp
    pass

ドキュメント:http
:
//docs.python.org/library/functions.html 警告:私が推奨する理由は、hasattrがプロパティを検出しないためです。
リンク:http : //mail.python.org/pipermail/python-dev/2005-December/058498.html


3
hasattr一般的にプロパティを正常に検出します。これは、property-wrapped関数での例外の発生を、そのような属性が存在しないことを意味するものとして扱うだけです。リンクされたPythonメーリングリストの投稿は、アクセスしようとすると例外が発生するプロパティに関するものです。実際には、値を生成することはないため、この属性は存在しません。また、hasattr一般にPy 3.1以前の例外のみを抑制します。3.2以降では、(Falsereturnで置換)を抑制するだけAttributeErrorです。
ShadowRanger

32

pydocによると、hasattr(obj、prop)は単にgetattr(obj、prop)を呼び出して例外をキャッチします。そのため、事前にhasattr()を使用するのと同じように、tryステートメントで属性アクセスをラップしてAttributeErrorをキャッチすることも同様に有効です。

a = SomeClass()
try:
    return a.fake_prop
except AttributeError:
    return default_value

2
まあhasattrは実際最適化されるかもしれません。たとえば、pypyを使用します。
odinho-ベルモント11年

6
+1。これはさえある、より安全な使用に比べhasattrたときにSomeClass上書き__getattr__するのでhasattrキャッチします全てだけでなく、Pythonの2.xでの例外をAttributeError、あなたが期待するように。これはPython 3.2で修正されました— 簡単な回避策については、他の回答を参照しください。
マーティンガイスラー、2013

24

これを避けることをお勧めします:

try:
    doStuff(a.property)
except AttributeError:
    otherStuff()

ユーザー@jpalecekはそれを述べました: AttributeError内部doStuff()で発生した、あなたは失われます。

多分このアプローチの方が良いでしょう:

try:
    val = a.property
except AttributeError:
    otherStuff()
else:
    doStuff(val)

13

状況に応じて、isinstance所有しているオブジェクトの種類を確認し、対応する属性を使用できます。抽象基本クラスの導入によりPython 2.6 / 3.0がこのアプローチもさらに強力になりました(基本的にABCは、ダックタイピングのより洗練された方法を可能にします)。

これが役立つ状況の1つは、2つの異なるオブジェクトに同じ名前の属性があり、意味が異なる場合です。のみを使用hasattrすると、奇妙なエラーが発生する可能性があります。

良い例の1つは、イテレータとイテラブルの違いです(この質問を参照)。__iter__イテレータとイテラブルのメソッドは同じ名前ですが、意味的にはまったく異なります!それhasattrは役に立たないですがisinstance、ABCと一緒にすっきりとしたソリューションを提供します。

ただし、ほとんどの場合、hasattrアプローチ(他の回答で説明)が最も適切なソリューションであることに同意します。


13

hasattr()を期待していますが、hasattr()を避け、getattr()を優先してください。getattr()はhasattr()より高速です

hasattr()の使用:

 if hasattr(a, 'property'):
     print a.property

同じここで私はgetattrを使用してプロパティを取得しています

   property = getattr(a,"property",None)
    if property:
        print property

11

編集:このアプローチには重大な制限があります。オブジェクトが反復可能なオブジェクトであれば機能するはずです。以下のコメントを確認してください。

私のようにPython 3.6以降を使用している場合は、オブジェクトに特定の属性があるかどうかを確認する便利な方法があります。

if 'attr1' in obj1:
    print("attr1 = {}".format(obj1["attr1"]))

ただし、どちらが現時点で最善のアプローチかはわかりません。using hasattr()、using getattr()またはusingを使用しinます。コメントは大歓迎です。


6
inキーワードは反復可能な型をチェックするために機能します。たとえば'foo' in None、エラーをスローしますTypeError: argument of type 'NoneType' is not iterable。修正は、を使用する前に型が反復可能かどうかを確認することinです。反復不可能なタイプのようなエッジケースを修正した後hasattr()は、エッジケースを処理するように設計されているため、おそらく使用した方がよいでしょう。
Seth Difley、2017年

3
これは属性アクセスとは何の関係もありません。それがどうして賛成されたかはわかりません。属性アクセスに必要な唯一の類似点はdict、JavaScriptオブジェクトの設計と同様に「軽量オブジェクト」として使用している場合ですが、ほとんどの通常のクラスはこれを一般的にサポートしていません(@SethDifleyによって言及されたエラーのバリアントを取得します)。 。
ShadowRanger


1

これは非常にシンプルで、dir(オブジェクトを使用するだけ)
です。これにより、オブジェクトの使用可能なすべての関数と属性のリストが返されます。


1

別の可能なオプションですが、それはあなたが以前に何を意味しているのかによって異なります:

undefined = object()

class Widget:

    def __init__(self):
        self.bar = 1

    def zoom(self):
        print("zoom!")

a = Widget()

bar = getattr(a, "bar", undefined)
if bar is not undefined:
    print("bar:%s" % (bar))

foo = getattr(a, "foo", undefined)
if foo is not undefined:
    print("foo:%s" % (foo))

zoom = getattr(a, "zoom", undefined)
if zoom is not undefined:
    zoom()

出力:

bar:1
zoom!

これにより、値のない属性をチェックすることもできます。

だが!誤ってインスタンス化してundefined複数の場所を比較しないように注意してくださいis

更新:

上記の段落で警告していたこと、一致しない複数の未定義があるため、最近このパターンを少し変更しました:

undefined = NotImplemented

NotImplementedは、と混同しないでください。NotImplementedError組み込みundefinedです。JSの意図とほぼ一致し、その定義をどこでも再利用でき、常に一致します。欠点は、ブール値では「真実」であり、ログやスタックトレースで奇妙に見える可能性があることです(ただし、このコンテキストでのみ表示されることがわかっているとすぐに乗り越えられます)。


0

組み込みメソッドobjectを使用して、属性が含まれているかどうかを確認できますhasattr

インスタンスがオブジェクトでaあり、属性を確認したい場合stuff

>>> class a:
...     stuff = "something"
... 
>>> hasattr(a,'stuff')
True
>>> hasattr(a,'other_stuff')
False

メソッドシグネチャ自体は、ブール値を与えるか、オブジェクト内の属性の存在に従って、2番目の引数に渡される属性を持っているhasattr(object, name) -> boolかどうかを意味します。objecthasattrTrueFalsename


0

hasattr()正解です。追加したいのは、asserthasattr()と組み合わせて使用することもできます(不要なステートメントを回避し、コードを読みやすくするため)。if

assert hasattr(a, 'property'), 'object lacks property' 

SOの別の回答で述べたように、アサートは、発生してはならない条件をテストするために使用する必要があります。目的は、プログラムの状態が破損した場合に早期にクラッシュすることです。


これは役に立ちますが、常にそうであるとは限りません。おそらく、オブジェクトにプロパティがあるかどうかをテストし、それを初めて追加したか、そのプロパティを持つオブジェクトに対して別のコードを実行する必要があるかもしれません。コードが続行できない場合は、アサートで問題ない可能性があります。しかし、繰り返しますが、常にそうであるとは限りません。重要なことはhasattr、周囲のコードを使用しないことです。
ルーカスガブリエルサンチェス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.