14

私は苦労してい__getattr__ます。複雑な再帰コードベースがあり、例外を伝播させることが重要です。

class A(object):
    @property
    def a(self):
        raise AttributeError('lala')

    def __getattr__(self, name):     
        print('attr: ', name)
        return 1      

print(A().a)

結果:

('attr: ', 'a')
1

なぜこの振る舞いをするのですか?例外がスローされないのはなぜですか? この動作は文書化されていません ( __getattr__documentation )。getattr()ちょうど使用できますA.__dict__。何かご意見は?

4

6 に答える 6

9

コードを次のように変更しただけです

class A(object):
    @property
    def a(self):
        print "trying property..."
        raise AttributeError('lala')
    def __getattr__(self, name):     
        print('attr: ', name)
        return 1      

print(A().a)

そして、ご覧のとおり、実際にプロパティが最初に試されます。AttributeErrorしかし、( を上げることによって)存在しないと主張するので__getattr__()、「最後の手段」と呼ばれます。

明確に文書化されていませんが、「属性ルックアップで通常の場所に属性が見つからなかったときに呼び出される」の下にカウントされる可能性があります。

于 2012-06-20T10:08:21.960 に答える
6

__getattribute__ドキュメンテーションは言う:

クラスが も定義している場合__getattr__()、後者は、__getattribute__()明示的に呼び出すか、AttributeError.

私はこれを(inclusio unius est exclusio alterius によって)、属性アクセス、 (「属性アクセスを実装するために無条件に呼び出される」)発生した__getattr__場合に呼び出すと言っていると読んでいます-直接または記述子(プロパティfgetなど)内で発生します。「 (計算された)属性値を返すか、例外を発生させる」必要があることに注意してください。object.__getattribute__AttributeError__get____get__AttributeError

類推として、オペレーターの特別なメソッドがNotImplementedError呼び出されると、他のオペレーター メソッド (たとえば__radd__for __add__) が試行されます。

于 2012-06-20T10:46:11.267 に答える
4

__getattr__属性アクセスが AttributeError で失敗したときに呼び出されます。おそらくこれが、エラーを「キャッチ」すると思う理由です。ただし、そうではありません。それらをキャッチしてから呼び出すのは、Python の属性アクセス機能です__getattr__

しかし、__getattr__それ自体はエラーをキャッチしません。AttributeError を発生させると、__getattr__無限再帰が発生します。

于 2012-06-20T10:11:49.543 に答える
0

@propertyと組み合わせると、とにかく運命づけられます__getattr__

class Paradise:
    pass

class Earth:
    @property
    def life(self):
        print('Checking for paradise (just for fun)')
        return Paradise.breasts
    def __getattr__(self, item):
        print("sorry! {} does not exist in Earth".format(item))

earth = Earth()
try:
    print('Life in earth: ' + str(earth.life))
except AttributeError as e:
    print('Exception found!: ' + str(e))

次の出力が得られます。

Checking for paradise (just for fun)
sorry! life does not exist in Earth
Life in earth: None

あなたの本当の問題が呼び出しにあったときParadise.breasts

__getattr__AtributeErroranが立ち上がったときに常に呼び出されます。例外の内容は無視されます。

悲しいことに、与えられたこの問題に対する解決策はありません( が定義されているという理由だけで)hasattr(earth, 'life')が返されますが、実際の根本的な問題は にあるのに対し、属性 'life' は存在しなかったため到達されます。True__getattr__Paradise.breasts

@property私の部分的な解決策は、例外にヒットすることが知られているブロックでtry-except を使用することAttributeErrorです。

于 2016-10-07T15:36:00.503 に答える