質問

いつ使用するかを理解しようとしています __getattr__ または __getattribute__. 。の ドキュメンテーション 言及 __getattribute__ 新しいスタイルのクラスに適用されます。新しいスタイルの授業とは何ですか?

役に立ちましたか?

解決

主な違いは、 __getattr__ そして __getattribute__ それは? __getattr__ 属性が通常の方法で見つからなかった場合にのみ呼び出されます。これは、欠落している属性のフォールバックを実装するのに適しており、おそらく必要な 2 つのうちの 1 つです。

__getattribute__ オブジェクトの実際の属性を確認する前に呼び出されるため、正しく実装するのが難しい場合があります。簡単に無限再帰に陥る可能性があります。

新しいスタイルのクラスの派生元 object, 、古いスタイルのクラスは、明示的な基本クラスを持たない Python 2.x のクラスです。しかし、古いスタイルのクラスと新しいスタイルのクラスの区別は、どちらかを選択するときに重要なものではありません。 __getattr__ そして __getattribute__.

ほぼ確実に欲しいです __getattr__.

他のヒント

両方の簡単な例をいくつか見てみましょう __getattr__ そして __getattribute__ 魔法の方法。

__getattr__

Python が呼び出します __getattr__ まだ定義されていない属性をリクエストするたびにメソッドを使用します。次の例では、私のクラスでは カウント ありません __getattr__ 方法。両方にアクセスしようとするとメインになります obj1.mymin そして obj1.mymax 属性はすべて正常に動作します。しかし、アクセスしようとすると obj1.mycurrent 属性 -- Python が与えてくれます AttributeError: 'Count' object has no attribute 'mycurrent'

class Count():
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent)  --> AttributeError: 'Count' object has no attribute 'mycurrent'

今私のクラス カウント もっている __getattr__ 方法。今アクセスしようとすると obj1.mycurrent 属性 -- Python は、私が実装したものをすべて返します。 __getattr__ 方法。この例では、存在しない属性を呼び出そうとすると、Python はその属性を作成し、整数値 0 に設定します。

class Count:
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax    

    def __getattr__(self, item):
        self.__dict__[item]=0
        return 0

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)

__getattribute__

では、見てみましょう __getattribute__ 方法。あなたが持っている場合 __getattribute__ クラス内のメソッドを使用すると、Python は属性が存在するかどうかに関係なく、すべての属性に対してこのメ​​ソッドを呼び出します。では、なぜ必要なのか __getattribute__ 方法?十分な理由の 1 つは、次の例に示すように、属性へのアクセスを防止して属性の安全性を高めることができるためです。

誰かが部分文字列で始まる私の属性にアクセスしようとするたびに 「カー」 Pythonはレイズします AttributeError 例外。それ以外の場合は、その属性を返します。

class Count:

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item) 
        # or you can use ---return super().__getattribute__(item)

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

重要:無限再帰を避けるために __getattribute__ メソッドの実装では、必要な属性にアクセスするために常に同じ名前の基本クラス メソッドを呼び出す必要があります。例えば: object.__getattribute__(self, name) または super().__getattribute__(item) そしてそうではありません self.__dict__[item]

重要

クラスに両方が含まれている場合 取得属性 そして 属性の取得 それから魔法の方法 __getattribute__ が最初に呼び出されます。しかし、もし __getattribute__ 上げるAttributeError 例外の場合、例外は無視され、 __getattr__ メソッドが呼び出されます。次の例を参照してください。

class Count(object):

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattr__(self, item):
            self.__dict__[item]=0
            return 0

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item)
        # or you can use ---return super().__getattribute__(item)
        # note this class subclass object

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

これは、に基づいた単なる例です ネッド・バチェルダー氏の説明.

__getattr__ 例:

class Foo(object):
    def __getattr__(self, attr):
        print "looking up", attr
        value = 42
        self.__dict__[attr] = value
        return value

f = Foo()
print f.x 
#output >>> looking up x 42

f.x = 3
print f.x 
#output >>> 3

print ('__getattr__ sets a default value if undefeined OR __getattr__ to define how to handle attributes that are not found')

同じ例を使用すると、 __getattribute__ >>> が得られます RuntimeError: maximum recursion depth exceeded while calling a Python object

New-Styleクラスは、object、または別の新しいスタイルクラスから継承します。

class SomeObject(object):
    pass

class SubObject(SomeObject):
    pass
.

オールドスタイルのクラスはありません:

class SomeObject:
    pass
.

Python 2にのみ適用されます.Python 3では、上記のすべてが新しいスタイルのクラスを作成します。

9を参照してください.//"nofollownoreferrer"> 9。クラス (Pythonチュートリアル)、 NewClassvsClassicClass href="https://stackoverflowflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-pthon">古いスタイルの違いは何ですかそしてPythonの新しいスタイルクラス? 詳細は

New-Styleクラスは、 "オブジェクト"(直接または間接的に)サブクラス化されているものです。__new__に加えて、一般的な低レベルの行動を持つことに加えて__init__クラス法があります。

通常、__getattr__を上書きしたいと思うでしょう(どちらも上書きしている場合)、それ以外の場合は、メソッド内の "self.foo"構文をサポートするのに苦労しています。

追加情報: http://www.devx.com/opensource/論文/ 31482/0 / PAGE / 4

Bezley&Jones PCBを読んで、私は__getattr__の明示的で実用的なユースケースにつまず、OPの質問の一部に答えるのに役立ちます。本から:

"__getattr__()メソッドは属性検索用のキャッチアリのようなものです。コードが存在しない属性にアクセスしようとすると呼び出されるメソッドです。」私たちは上記の答えからこれを知っていますが、PCBレシピ8.15では、この機能は代表団デザインパターンを実装するために使用されます。オブジェクトAがオブジェクトBのすべてのオブジェクトBのメソッドをすべて再定義するのではなく、オブジェクトAのすべてのメソッドを再定義するのではなく、Object Aのすべてのメソッドを再定義するのではなく、次のように__getattr__()メソッドを定義します。

def __getattr__(self, name):
    return getattr(self._b, name)
.

ここで、_bはオブジェクトBであるオブジェクトAの属性の名前です。オブジェクトB上で定義されたメソッドがオブジェクトAで呼び出されると、参照チェーンの最後に__getattr__メソッドが呼び出されます。別のオブジェクトに委任するためだけに定義されたメソッドのリストがないので、これはコードクリーナーを作るでしょう。

  • getAttribute :インスタンスから属性を取得するために使用されます。 DOT表記またはgetAttr()組み込み関数を使用してインスタンス属性にアクセスするたびに、インスタンス属性にアクセスするたびにキャプチャします。
  • getAttr :オブジェクトに属性が見つからない場合は、最後のリソースとして実行されます。デフォルト値を返すか、AttributionErrorを起動することを選択できます。

__ getAttribute __ 関数に戻る。デフォルトの実装がオーバーライドされていない場合。メソッドの実行時に次のチェックが行われます。

  • MROチェーン内の任意のクラスで定義された同じ名前(属性名)の記述子があるかどうか(メソッドオブジェクト解決)
  • はインスタンスの名前空間
  • を調べます
  • その後クラス名前空間
  • に調べます。
  • それから各ベースの名前空間などに。
  • 最後に、見つからない場合、デフォルトの実装はインスタンスのフォールバック getattr ()メソッドを呼び出し、デフォルトの実装としてattributeError例外を発生させます。

これは、オブジェクトの実際の実装です.__ getAttribute__メソッド:

".. c:function :: pyObject * pyObject_genericGetAttr(PyObject * O、PyObject * name) タイプに入れることを意味する一般的な属性getter関数 オブジェクトのTP_GETATTROスロット。辞書内の記述子を探します オブジェクトのMROのクラスとオブジェクトの属性 :attr:〜オブジェクト。 dict (存在する場合)。概要:REF:記述子、 データ記述子はインスタンス属性よりも優先されますが、データは非データ ディスクリプタはしません。それ以外の場合は、:EXC:AttributionErrorが発生します。 "

私は誰もこの違いを言及していないことがわかります:

__getattribute__にはデフォルトの実装がありますが、__getattr__はそうではありません。

class A:
    pass
a = A()
a.__getattr__ # error
a.__getattribute__ # return a method-wrapper
.

これは明確な意味を持ちます.__getattribute__はデフォルトの実装をしているため、__getattr__は、はっきりとPythonがユーザーに__getattr__を実装することを奨励します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top