__setattr__
实现中访问对象的属性 - 我无法弄清楚如何。这是我到目前为止所尝试的:
class Test1(object):
def __init__(self):
self.blub = 'hi1'
def __setattr__(self, name, value):
print self.blub
class Test2(object):
def __init__(self):
self.blub = 'hi2'
def __setattr__(self, name, value):
print object.__getattr__(self, 'blub')
class Test3(object):
def __init__(self):
self.blub = 'hi3'
def __setattr__(self, name, value):
print object.__getattribute__(self, 'blub')
class Test4(object):
def __init__(self):
self.blub = 'hi4'
def __setattr__(self, name, value):
print self.__getattr__('blub')
class Test5(object):
def __init__(self):
self.blub = 'hi5'
def __setattr__(self, name, value):
print self.__getattribute__('blub')
class Test6(object):
def __init__(self):
self.blub = 'hi6'
def __setattr__(self, name, value):
print self.__dict__['blub']
测试:
try:
TestX().bip = 'bap'
except Exception as ex:
print ex
X
从1
到6
输出:
'Test1' object has no attribute 'blub'
type object 'object' has no attribute '__getattr__'
'Test3' object has no attribute 'blub'
'Test4' object has no attribute '__getattr__'
'Test5' object has no attribute 'blub'
'blub'
有什么建议吗?
答案 0 :(得分:4)
因为在__init__
内部,它试图设置调用blub
的{{1}};它没有设置任何东西,只是试图访问(和打印)__setattr__
,什么也没找到并引发错误。检查一下:
blub
答案 1 :(得分:2)
TestX().bip = 'bap'
您运行的代码如下:
try:
TestX().bip = 'bap'
except Exception as ex:
print ex
有很大的不同。你为什么问?好吧,您的输出似乎乍一看表示Test6
有效,并且有几条评论和答案假定它确实有效。为什么它似乎有用?阅读代码,无法它应该工作。仔细检查源代码会发现,如果 有效,它应该打印hi6
,而不是'blub'
。
我在print ex
的{{1}}行放置一个断点来检查异常:
pdb
出于某种原因,(Pdb) ex
KeyError('blub',)
(Pdb) print ex
'blub'
不会像您期望的那样打印print ex
,而只是KeyError: blub
,这就是'blub'
似乎有用的原因。
所以我们已经清除了这一点。将来,请不要遗漏这样的代码,因为它可能很重要。
所有其他答案都正确地指出您尚未设置您尝试打印的属性,这是您的问题。在您接受此答案之前,您之前接受的答案仍然是,规定了以下解决方案:
Test6
虽然这个解决方案确实有效,但它并不是一个好的设计。这是因为您可能希望在某个时刻更改基类,并且该基类在设置和/或获取属性时可能会产生重要的副作用,或者它可能根本不会将属性存储在def __setattr__(self, name, value):
self.__dict__[name] = value
print self.__dict__[name]
中!更好的设计是为了避免弄乱self.__dict__
。
正确的解决方案是调用父__dict__
方法,这是由至少一个其他答案建议的,尽管python 2.x的语法错误。我就是这样做的:
__setattr__
如您所见,我正在使用def __setattr__(self, name, value):
super(Test6, self).__setattr__(name, value)
print getattr(self, name)
代替getattr
来动态查找属性。与直接使用__dict__
不同,这会在适当时调用__dict__
或self.__getattr__
。
答案 2 :(得分:1)
print self.__dict__['blub']
打印出blub
这是正确的。你必须先设置新值,因为python不会那样做,就像那样:
def __setattr__(self, name, value):
self.__dict__[name] = value
print self.__dict__[name]
然后test6.blub = 'test'
应打印出test
修改强>
根据@Lauritz的建议,您也可以使用
def __setattr__(self, name, value):
super(Test6, self).__setattr__(name, value)
print self.__dict__[name]
调用父函数,所以如果你的超类已经有__setattr__
函数,它就不会被覆盖。
答案 3 :(得分:1)
您实际上从未在__setattr__
中设置属性,因此对象当然没有。
def __setattr__(self, name, value):
self.name = value
# this doesn't work, since it calls itself (the __setattr__)
def __setattr__(self, name, value):
super().__setattr__(name, value)
# call the default implementation directly in Py 3.x
def __setattr__(self, name, value):
super(TestX, self).__setattr__(name, value) # for Python 2.x
当然,单独做这件事是没有用的,你通常想要添加一些功能,如某些条件,调试打印,缓存或任何你需要的。
答案 4 :(得分:1)
__setattr__
适用于课程,所以当你超越时 - 你需要让它实际设置属性......否则,它永远不会存在..例如:
object.__setattr__(self, name, value)
所以,在你的__init__
中,当你self.blub = 'hi'
实际上是一个无操作时。