6

例えば:

>>> s = 'string'
>>> hasattr(s, 'join')
True
>>> 'join' in dir(s)
True

Python のドキュメントには、例外が発生するかどうかをhasattr呼び出して確認することが実装されていると書かれています。getattrただし、取得した値が破棄され、例外が発生する可能性があるため、これは大きなオーバーヘッドにつながります。

問題は、呼び出し'attribute' in dir(obj)が同じことを意味するかどうか、より高速か、安全か、または特定の場合に失敗する可能性があるかということです。

4

4 に答える 4

13

まったく同じではありません。およびが検出する属性を省略するdir()診断ツールです。getattr()hasattr()

dir()ドキュメントから:

デフォルトのメカニズムは、完全な情報ではなく最も関連性dir()の高い情報を生成しようとするため、オブジェクトの種類によって動作が異なります。

  • オブジェクトがモジュール オブジェクトの場合、リストにはモジュールの属性の名前が含まれます。
  • オブジェクトが型またはクラス オブジェクトの場合、リストにはその属性の名前と、そのベースの属性が再帰的に含まれます。
  • それ以外の場合、リストには、オブジェクトの属性の名前、そのクラスの属性の名前、およびそのクラスの基本クラスの属性の再帰的な名前が含まれます。

:は、主にインタラクティブ プロンプトでの使用を便利にするdir()ために提供されているため、厳密にまたは一貫して定義された名前のセットを提供しようとするよりも、興味深い名前のセットを提供しようとします。詳細な動作は、リリース間で変わる可能性があります。たとえば、引数がクラスの場合、属性は結果リストに含まれません。metaclass

鉱山を強調します。

これは、メタクラスが提供する属性hasattr()を見つけることを意味しますが、そうではなく、関数の定義はデバッグの利便性を提供するためのものであり、完全性を提供するためのものではないため、見つかったものは Python リリース間で異なる可能性があります。dir()

特定のメタクラス シナリオのデモ。hasattr()メタクラスで定義された属性が見つかります。

>>> class Meta(type):
...     foo = 'bar'
... 
>>> class Foo(metaclass=Meta):
...     pass
... 
>>> hasattr(Foo, 'foo')
True
>>> 'foo' in dir(Foo)
False

最後だが大事なことは:

オブジェクトに という名前のメソッドがある場合__dir__()、このメソッドが呼び出され、属性のリストを返す必要があります。

これは、メソッドが実装されている場合、「見つかった」属性がさらに大きく異なる可能性があることhasattr()を意味します。dir().__dir__()

に固執するだけhasattr()です。1 つには、属性のテストは 1 つ以上の辞書に対するメンバーシップ テストであるため安価であるため、より高速です。一方、すべてのディクショナリ キーを列挙し、それらをインスタンス、クラス、および基本クラス全体でマージすると、CPU コストがはるかに高くなります。

于 2013-07-18T12:37:44.670 に答える
4

hasattr は 100 倍以上高速です :)

In [137]: s ='string'

In [138]: %timeit hasattr(s, 'join')
10000000 loops, best of 3: 157 ns per loop

In [139]: %timeit 'join' in dir(s)
100000 loops, best of 3: 19.3 us per loop
于 2013-07-18T12:37:29.307 に答える
1

dir()、またはそのようなものは呼び出しませんgetattr()。それ自体を「説明」するクラスに依存します。

>>> class Foo(object):
...     def __dir__(self):
...         return ['apples', 'bananas', 'mangoes']
...     def __getattr__(self, attr):
...         return {'a': 1}[attr]
...     
>>> foo = Foo()
>>> hasattr(foo, 'a')
True
>>> hasattr(foo, 'apples')
False
>>> 'a' in dir(foo)
False
>>> 'apples' in dir(foo)
True

dir()ドキュメントを探す場合に のみ使用してください。

于 2013-07-18T12:37:48.653 に答える
0

hasattr() は基本的に

try:
    s.attribute
    return True
except AttributeError:
    return False

一方、「ディレクトリ内の属性」は次のようになります。

for attr in dir(s):
    if attribute == attr:
        return True
return False

したがって、 hasattr は少し高速になると予想されます。

とにかく、少し軌道から外れることが許されるなら、これをお勧めします。次のようなことをしたい場合:

if hasattr(s, 'attributeName'):
    s.attributeName()
else:
    do_stuff()

次に、次のようにすることをお勧めします。

try:
    s.attributeName()
except AttributeError:
    do_stuff()

なんで?

  1. 余分な try-except ブロック/ for ループのオーバーヘッドを回避するため。
  2. Python では、許可よりも許しを求める方が簡単です。
于 2013-07-18T12:46:03.733 に答える