为什么在python中使用__setattr__?

时间:2011-04-22 11:37:50

标签: python setter

我不知道为什么使用__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)

但不明白为什么使用代码取决于字符串('height')。

你能解释一下__setattr__的优点吗?

7 个答案:

答案 0 :(得分:28)

你不要自己打电话。期。如果你需要使用一个字符串,因为你事先不知道这个名字(非常坏主意,99%的人认为他们需要这个,所以几乎总是一个字典或列表更好/ saner choice),您使用内置的setattr函数。

然而,它是为您而设的 - 当您执行a.x = ...时,它已完成a.__setattr__('x', ...)(这可能过于简单化了)。并且一些对象超载它以允许一些欺骗,例如,模仿不变性。 See the documentation of "special methods".

答案 1 :(得分:15)

__setattr__是一个由setattr内置方法调用的类方法。也就是说,如果在给定的类中定义了__setattr__。大多数情况下,您不会声明自己的__setattr__版本,因此我假设您在询问setattr方法的用途。

假设您有一个var,其中包含您要设置的属性的名称,而不仅仅是知道名称:

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

无法使用self.name = val

此外,常见的用法是使用关键字args:

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

答案 2 :(得分:7)

我可以设想一个应用程序,例如,您覆盖__setattr____getattr__,以提供对未保存在内存中的其他数据结构的类似对象的访问。例如,您可以创建一个对象,其中foo.CustomerName = "John"更新了CustomerName指向的数据库行中的foo列,以包含值"John"。即,foo.__setattr__将使用属性名称和值来构造更新磁盘上数据库的命令。我不想写这样的东西,但这是可能的。

答案 3 :(得分:2)

请注意__xxx__是类的运算符重载方法,因此只应在特殊情况下使用,而不是在示例中使用。

例如,__setattr__拦截所有属性分配,并且可以在将值分配给属性时用于更改类的行为。

答案 4 :(得分:1)

__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

答案 5 :(得分:1)

__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 !'

第二种用法是,当您执行此操作时,您可以从父类(默认为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'

答案 6 :(得分:0)

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"