我不知道为什么使用__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__
的优点吗?
答案 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"