93
if hasattr(obj, 'attribute'):
    # do somthing

try:
    # access obj.attribute
except AttributeError, e:
    # deal with AttributeError

どちらを優先する必要がありますか?その理由は?

4

12 に答える 12

93

パフォーマンスの違いを示すベンチはありますか?

それはあなたの友達です

$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'hasattr(c, "nonexistent")'
1000000 loops, best of 3: 1.87 usec per loop
$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'hasattr(c, "a")'
1000000 loops, best of 3: 0.446 usec per loop
$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'try:
 c.a
except:
 pass'
1000000 loops, best of 3: 0.247 usec per loop
$ python -mtimeit -s 'class C(object): a = 4
c = C()' 'try:
 c.nonexistent
except:
 pass'
100000 loops, best of 3: 3.13 usec per loop
$

       |positive|negative
hasattr|  0.446 |  1.87 
try    |  0.247 |  3.13
于 2009-05-24T06:41:27.237 に答える
88

hasattrブロックと同じタスクを内部的かつ迅速に実行しtry/exceptます。これは非常に具体的で最適化された 1 つのタスクのツールであるため、該当する場合は、非常に汎用的な代替手段よりも優先されます。

于 2009-05-24T05:17:15.250 に答える
30

3 番目の、多くの場合はより優れた代替手段があります。

attr = getattr(obj, 'attribute', None)
if attr is not None:
     print attr

利点:

  1. getattrには、Martin Geiser によって指摘された悪い例外hasattr飲み込み動作はありません。古い Python では、 KeyboardInterrupt.

  2. オブジェクトに属性があるかどうかを確認する通常の理由は、その属性を使用できるようにするためであり、これは当然のことです。

  3. 属性はアトミックに読み取られ、オブジェクトを変更する他のスレッドから安全です。(ただし、これが大きな懸念事項である場合は、オブジェクトにアクセスする前にオブジェクトをロックすることを検討してください。)

  4. よりもtry/finally短く、多くの場合よりも短いですhasattr

  5. 広いブロックは、予期しているもの以外except AttributeErrorをキャッチする可能性があり、混乱を招く動作につながる可能性があります。AttributeErrors

  6. 属性へのアクセスは、ローカル変数へのアクセスよりも遅くなります (特にプレーンなインスタンス属性でない場合)。(ただし、正直に言うと、Python でのマイクロ最適化はしばしばばかげたことです。)

注意すべきことの 1 つは、 が None に設定されているケースを気にする場合はobj.attribute、別のセンチネル値を使用する必要があるということです。

于 2013-05-24T03:18:35.717 に答える
13

関数が属性のないオブジェクトを受け入れるかどうかによって異なりますたとえば、関数の呼び出し元が 2 つあり、1 つは属性を持つオブジェクトを提供し、もう 1 つは属性を持たないオブジェクトを提供します。

属性のないオブジェクトを取得する唯一のケースが何らかのエラーによるものである場合は、例外メカニズムを使用することをお勧めします。例外メカニズムの方が遅くなる可能性がありますが、これはよりクリーンな設計であると考えているためです。

結論: 効率の問題ではなく、デザインと読みやすさの問題だと思います。

于 2009-05-24T05:37:42.993 に答える
5

属性を持たないことがエラー条件でない場合例外処理バリアントには問題があります。obj.attributeにアクセスするときに内部的に発生する可能性のあるAttributeErrorsもキャッチします(たとえば、属性はプロパティであるため、アクセスするとコードが呼び出されます)。

于 2009-06-30T10:52:28.280 に答える
4

テストしている属性が 1 つだけの場合は、 use と言うでしょうhasattr。ただし、存在するかどうかに関係なく属性に複数のアクセスを行う場合は、tryブロックを使用すると入力を節約できます。

于 2009-05-24T05:32:01.377 に答える
3

オプション 2 をお勧めします。他のスレッドが属性を追加または削除している場合、オプション 1 には競合状態があります。

また、Python にはイディオムがあり、EAFP (「許可よりも許しを求める方が簡単」) は LBYL (「ジャンプする前に見てください」) よりも優れています。

于 2009-05-24T08:00:38.027 に答える
2

実用的な観点からは、ほとんどの言語では、条件を使用する方が例外を処理するよりも常にかなり高速です。

現在の関数の外のどこかに存在しない属性のケースを処理したい場合は、例外を使用することをお勧めします。条件の代わりに例外を使用したいという指標は、条件が単にフラグを設定して現在の操作を中止し、他の何かがこのフラグをチェックし、それに基づいてアクションを実行することです。

とはいえ、Rax Olgud が指摘するように、他者とのコミュニケーションはコードの重要な属性の 1 つであり、「これは私が予想することです」よりも「これは例外的な状況です」と言いたいことの方が重要かもしれません。 .

于 2009-05-24T05:44:44.980 に答える
0

少なくとも、プログラムで何が起こっているか、読みやすさなどの人間の部分を除外する場合 (実際にはほとんどの場合、パフォーマンスよりも重要です (少なくともこの場合、そのパフォーマンススパンで))、 Roee Adler などが指摘したように)。

それでもその観点から見ると、どちらかを選択する問題になります

try: getattr(obj, attr)
except: ...

try: obj.attr
except: ...

hasattr最初のケースを使用して結果を決定するだけだからです。思考の糧 ;-)

于 2012-10-12T08:29:57.803 に答える
0

最初。

短い方が良いです。例外は例外的であるべきです。

于 2009-05-24T05:14:59.073 に答える