506

__getattr__いつ使用するか、またはを理解しようとしています__getattribute__。記載されているドキュメント__getattribute__、新しいスタイルのクラスに適用されます。新しいスタイルのクラスとは何ですか?

4

8 に答える 8

591

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

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

新しいスタイルのクラスは から派生しobject、古いスタイルのクラスは明示的な基底クラスを持たない Python 2.x のクラスです。しかし、古いスタイルのクラスと新しいスタイルのクラスの違いは、 と のどちらかを選択する際には重要ではありませ__getattr____getattribute__

あなたはほぼ確実__getattr__に .

于 2010-07-19T02:22:00.353 に答える
198

__getattr____getattribute__魔法のメソッドの簡単な例をいくつか見てみましょう。

__getattr__

Python は __getattr__、まだ定義されていない属性を要求するたびにメソッドを呼び出します。次の例では、クラスCountにメソッドがありません__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'

今、私のクラスCountには__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 つは、次の例に示すように、属性へのアクセスを防止し、より安全にすることができることです。

誰かが部分文字列'cur'で始まる属性にアクセスしようとすると、 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)or super().__getattribute__(item)and notself.__dict__[item]

重要

クラスに getattr と getattribute の両方のマジック メソッドが含まれている場合、最初呼び出さ __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)
于 2016-08-05T11:37:09.870 に答える
18

これは、 Ned Batchelder の説明に基づいた単なる例です。

__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

于 2013-09-16T06:11:50.943 に答える
15

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

class SomeObject(object):
    pass

class SubObject(SomeObject):
    pass

古いスタイルのクラスはしません:

class SomeObject:
    pass

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

9.クラス(Pythonチュートリアル)、NewClassVsClassicClass、およびPythonの古いスタイルクラスと新しいスタイルクラスの違いは何ですか?を参照してください。詳細については。

于 2010-07-19T02:18:53.823 に答える
6

新しいスタイルのクラスは、「オブジェクト」を(直接的または間接的に)サブクラス化するクラスです。それらには、__new__クラスメソッドに加えて__init__、やや合理的な低レベルの動作があります。

通常、オーバーライドする必要があります__getattr__(どちらかをオーバーライドする場合)。そうしないと、メソッド内で「self.foo」構文をサポートするのに苦労します。

追加情報:http ://www.devx.com/opensource/Article/31482/0/page/4

于 2010-07-19T02:18:09.487 に答える