5


2

hasattr()でアクセスしようとしたときに評価されないような属性を遅延させるデコレータを作ることは可能ですか? 私はそれを怠惰にする方法を考え出しました、しかし、 `hasattr()`はそれを時期尚早に評価させます。 例えば。、

class lazyattribute:#マジック。

クラスA:@ lazyattribute def bar(self):print( "Computing")return 5

>>> a = A()>>> print(a.bar) 'コンピューティング' 5 >>> print(a.bar)5 >>> b = A()>>> hasattr(b、 'bar') 'コンピューティング' 5#希望する出力:5

5 Answer


4


難しいかもしれません。 hasattrのドキュメントから:

hasattr(オブジェクト、名前)

引数はオブジェクトと文字列です。 文字列がオブジェクトのいずれかの属性の名前である場合、結果はTrueになり、そうでない場合はFalseになります。 (これは、getattr(object、name)を呼び出して、例外が発生するかどうかを確認することによって実装されています。

属性は `getattr`メソッドによって動的に生成されるかもしれないので、それらの存在を確実にチェックする他の方法はありません。 あなたの特別な状況では、辞書を明示的にテストすれば十分でしょう。

any(dの 'bar'からdの(b .__ dict__、b .__ class __.__ dict__))


2


これまで誰も対処していないと思われるのは、おそらくするべき最善策は `hasattr()`を使用しないことです。 代わりに、EAFP(許可よりも許しを依頼する方が簡単)に行きます。

試してみてください。AttributeError以外のx = foo.bar:#else-blockで何が起こったか... else:#if hasattr(foo、 "bar")ブロックに入ってきたこと

これは明らかにドロップイン置換ではありません、そしてあなたは少し周りにものを動かさなければならないかもしれません、しかしおそらくそれは(もちろん主観的に)「最も良い」解決策です。


0


問題は、 hasattr`が getattr`を使っているので、 hasattr`を使った時にはあなたの属性が常に評価されることです。 あなたの `lazyattribute`マジックのコードを投稿するならば、誰かが hasattr`や `getattr`を必要としない属性の存在をテストする別の方法を提案できることを願っています。 `hasattr`のヘルプを見てください。

>>> help(hasattr)モジュール__builtin__の組み込み関数hasattrに関するヘルプ:

hasattr(...)hasattr(object、name) - >ブール

オブジェクトが指定された名前の属性を持っているかどうかを返します。 (これはgetattr(object、name)を呼び出して例外をキャッチすることによって行われます。)


0


私はあなたがこのようなものが必要な理由に興味があります。 もし `hasattr`があなたの" compute function "を呼んでしまうのであれば、それもそうです。 とにかくあなたの財産はどのくらい怠惰である必要がありますか?

それでも、呼び出し側の関数の名前を調べることによってこれを行うには、やや不適切な方法があります。 おそらくもう少し良くコーディングすることもできますが、真剣に使われるべきではないと思います。

輸入検査

クラスlazyattribute(object):def __init __(self、func):self.func = func

def __get __(self、obj、kls = None):objがNoneまたはinspect.stack()の場合[1] [4] [0] .startswith( 'hasattr'):戻り値なしvalue = self.func(obj)setattr (obj、self.func .__ name__、value)の戻り値

クラスFoo(オブジェクト):@lazyattribute def bar(self):return 42


-2


この修正は少し厄介ですが、次のものから構成されます

  1. hasattrの名前を変更(_hasattrと言う)

  2. 次のようにhasattrを再バインドします。

def hasattr(obj、name):試してください:obj._hasattr(name)または_hasattr(obj、name)を返してください。
  1. いくつかのデータ構造をチェックすることによってクラスメソッド_hasattrを実装します(すなわち。 これにはすべてのlazy属性* names が入ります(配列の場合は lazyAttrArrayにname *が入ります)。

  2. 最後に、@lazyattributeデコレータに何らかの方法で項目を追加させ(上記の配列のように)、その後_hasattrを呼び出すと、その構造が表示されます。

    • _これは、私が自分でデコレータを作成することに取り組んでいないために、どのようにあなたが実装するのかよくわからないというステップです。