2016-07-31 1 views
0

は、Python 2.7.12のドキュメントによると:__setattr__()はインスタンス属性に割り当てたい場合はなぜ新しいスタイルクラスでのみオブジェクト.__ setattr __(self、name、value)が優先されますか?

、それは単に self.name = valueを実行してはならない - これは、自分自身への再帰呼び出し を引き起こします。代わりに、インスタンス属性の辞書 に値を挿入する必要があります(例:self.__dict__[name] = value)。 新しいスタイルのクラスではではなく、インスタンス辞書にアクセスして、それが は object.__setattr__(self, name, value)、例えば、同じ名前の基底クラスのメソッドを呼び出す必要があります。

ただし、次のコードは1つが期待通りに動作します

class Class(object): 
    def __setattr__(self, name, val): 
     self.__dict__[name] = val; 

c = Class() 
c.val = 42 
print c.val 

私はsuper(Class, obj).__setattr__(name, value)が呼び出されるすべての基底クラスの__setattr__メソッドを確保することができます知っているが、古典的なクラスも拠点クラスから継承することができます。だから、なぜそれは新しいスタイルのクラスにのみ推奨されますか?

一方、クラシッククラスでは推奨されないのはなぜですか?

+1

*新しいスタイルクラスにのみ推奨されるのはなぜですか?*インスタンス辞書で操作する代わりに '__setattr__'を呼び出すと、スーパークラスは何が起こっているのかを監督することができます。このアプローチを新しいスタイルクラスの利点と考えてください。*継承しない古いスタイルのクラスは*呼び出し可能な '__setattr__'メソッドを持つスーパークラスを持っていません。 – jedwards

+1

@jedwards昔のクラスでは 'classobj .__ setattr__'がないので、新しいスタイルクラスでは' object .__ setattr__'だけです。 –

+0

あなたはまさに正しいです。私の主張は、あなたが大胆に書いた文章を、インスタンスディクテーションを直接使用することからの落胆ではなく、見たことです(あなたが示したように、多くの場合完璧にうまくいきます.Martijnが示したように、 )、しかし、 "__setattr__"を使うことはもっと奨励*されます。これは、スーパークラスのいくつかの監視とディスクリプタなどの新しい機能の使用を可能にします。もし私が不明だったら申し訳ありません:) – jedwards

答えて

3

新しいスタイルのクラスは、スロットを使用しています。この時点では、割り当て先は__dict__ではありません。新しいスタイルのクラスでは、他のデータ記述子もサポートされています。オブジェクトは、特定の名前の属性設定や削除を処理するクラスで定義されています。 documentation on slotsから

:デフォルトでは

、新旧両方のスタイルクラスのインスタンスは、属性記憶のための辞書を持っています。これは、インスタンス変数が非常に少ないオブジェクトのためのスペースを無駄にします。空間消費は、多数のインスタンスを作成するときに鋭敏になります。

デフォルトは、新しいスタイルのクラス定義で__slots__を定義することでオーバーライドできます。 __slots__宣言は一連のインスタンス変数を取り、各インスタンスには各変数の値を保持するのに十分なスペースを確保します。 __dict__がインスタンスごとに作成されないため、領域が節約されます。

スロットにアクセスする代わりに、クラスにdata descriptorsを追加して実装します。そのような属性ごとに__set__および/または__del__メソッドを持つオブジェクト。

データディスクリプタのもう1つの例は、セッターまたはデリター機能が付加されたproperty() objectsです。 __dict__の記述子オブジェクトと同じ名前のキーを設定すると、データ記述子によって属性検索が__dict__を迂回するため、無視されます。

object.__setattr__()は、データディスクリプタの処理方法を知っています。そのため、データディスクリプタを呼び出す必要があります。

+0

"__dict__の中のそのようなオブジェクトのキーを設定することは無視されます"は "__dict__のデータ記述子を使用するクラスのクラスのキーを設定することは無視されます"それをもっと明確にする? –

+0

@sunqingyao:問題の「オブジェクト」は、クラスのデータ記述子です。 –

関連する問題