web-dev-qa-db-ja.com

Pythonで__setattr__を使用する理由

__setattr__のような単純な参照の代わりにx.a=1を使用する理由がわかりません。

私はこの例を理解しています:

class Rectangle:
    def __init__(self):
        self.width = 0
        self.height = 0


x=Rectangle()
x.width=20
x.__setattr__('height',30)
setattr(x,'width',99)

ただし、文字列(「高さ」)に応じてコードを使用する理由はわかりません。

__setattr__の利点は何ですか?

23
user278618

あなたはそれを自分とは呼びません。限目。名前が事前にわからないために文字列を使用する必要がある場合(very必要だと思われるすべてのケースの99%で悪い考えこれは、ほとんどの場合、dictまたはリストがより良い/より良い選択です)、組み込みのsetattr関数を使用します。

しかし、それはあなたのために呼び出されます-あなたが_a.x = ..._をするとき、それはa.__setattr__('x', ...)として行われます(これはおそらく単純化しすぎです)。そして、いくつかのオブジェクトはそれをオーバーロードして、いくつかのトリックを可能にします。不変性をエミュレートします。 「特別なメソッド」のドキュメントを参照してください。

31
user395760

__setattr__は、setattr組み込みメソッドによって呼び出されるクラスメソッドです。つまり、__setattr__が特定のクラスで定義されている場合。ほとんどの場合、独自のバージョンの__setattr__を宣言しないので、setattrメソッドの用途を尋ねていると思います。

名前を知っているだけでなく、設定したい属性の名前を持つ変数があるとします。

class A(object):
    def doSth(self, name, val):
        setattr(self, name, val)

self.name = valでは不可能

また、一般的な使用法はキーワード引数での使用です:

class A(object):
    def __init__(self, *args, **kwargs):
        for k,v in kwargs.items():
            setattr(self, k, v)
16
pajton

たとえば、__setattr__および__getattr__をオーバーライドして、メモリに保持されていない他のデータ構造へのオブジェクトのようなアクセスを提供するアプリケーションを想定できます。たとえば、foo.CustomerName = "John"CustomerNameが指すデータベース行のfoo列を更新して値"John"を含むオブジェクトを作成できます。つまり、foo.__setattr__は、属性名と値を使用して、ディスク上のデータベースを更新するコマンドを作成します。そんなことを書かなくてもいいのですが、可能でしょう。

7
Peter Milley

ご了承ください __xxx__は、クラスの演算子オーバーロードメソッドであるため、特別な状況でのみ使用し、例のような場合には使用しないでください。

例えば、 __setattr__はすべての属性割り当てをインターセプトし、値が属性に割り当てられたときにクラスの動作を変更するために使用できます。

2
joaquin

___setattr___の最初の使用は、クラス定義で上書きされます。

_class Foo ( object ) :

    def __init__ ( self ) :
        self.x = 'looser'

    def __setattr__ ( self, name, value ) :
        if name == 'x' :
            print( 'Hello, {} !'.format( value ) )
            self.x = value
_

問題、Foo()は無限のシーケンスを出力します:

_'Hello, looser !'
_

2つ目の使用法があります。その場合、親クラス(デフォルトではobject)からsetattrを呼び出して、無限再帰を回避できます。

_class Foo ( object ) :

    def __setattr__ ( self, name, value ) :
        self.bar( name, value )
        object.__setattr__( self, name, value )

    def bar ( self, name, value ) :
        print( 'Setting {} to {}.'.format( name, value ) )
_

したがって :

_f = Foo()

>> 'Hello, winner !'

f.x

>> 'winner'
_
1
Thrastylon

__setattr__はリフレクションに使用できます。実行時にオブジェクトRectangleのプロパティを作成できます。詳細は http://en.wikipedia.org/wiki/Reflection_%28computer_science%29 にあります。 =

class Rectangle:
    def __init__(self):
        #... code ...

x = Rectangle()
#x.__setattr__('newProperty',30)      Edited after comment
setattr(x, 'newProperty', 30)
print x.newProperty #>>> 30
1
aweis
class Name(object):
    pass

obj=Name()

#just i have created object two way 
#first

obj.a="first"
print obj.a

#answer= "first"
#second

obj.__setattr__('b','second')
print obj.a
#answer= "second"
0
user3657729