我需要为没有属性的字段定义__setattr__,但对有属性的字段使用setter/getter函数
定义 __setattr__
会覆盖我在类中定义的所有设置方法和属性。我想在属性存在的情况下使用已定义的设置方法,如果没有属性,就用 self.__dict__[name] = value
来处理。
求助!我找到一个使用 __setitem__
的解决方案,但对我来说不管用。
在 Python 类中,属性存储在哪里?我该如何访问它们?
我该如何定义 __setattr__
,以便在有设置方法的字段上使用这些属性?
class test(object):
def _get_gx(self):
print "get!"
return self.__dict__['gx']
def _set_gx(self, gx):
print "set!"
self.__dict__['gx'] = gx
gx = property(_get_gx, _set_gx)
def __setattr__(self, name, value):
self.__dict__[name] = value
def __init__(self):
pass
还有,
为什么当我执行时,“get!” 会被打印两次,
x = test()
x.gx = 4
x.gx
prints:
"gets!"
"gets!"
4
1 个回答
10
你需要重新写一下你的 __setattr__
函数。根据文档,新风格的类应该使用 baseclass.__setattr__(self, attr, value)
,而不是 self.__dict__[attr] = value
。前者会查找任何描述符,而后者只是直接给字典赋值。
所以把你的方法改成
def __setattr__(self, name, value):
object.__setattr__(self, name, value)
或者
def __setattr__(self, name, value):
super(Test, self).__setattr__(name, value)
这样就没问题了。代码
class Test(object):
@property
def gx(self):
print "getting gx"
return self.__dict__['gx']
@gx.setter
def gx(self, value):
print "setting gx"
self.__dict__['gx'] = value
def __setattr__(self, attr, value):
print "using setattr"
object.__setattr__(self, attr, value)
t = Test()
t.gx = 4
t.dummy = 5
print t.gx
print t.dummy
print dir(Test)
输出
using setattr
setting gx
getting gx
using setattr
4
5
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gx']
我不知道你版本的代码为什么会调用获取器两次,而这个版本不会。此外,关于描述符的位置,你可以很清楚地看到它在类字典的最后一项。
值得注意的是,你在例子中并不需要 __setattr__
来实现你想要的功能。Python 总是会把赋值 foo.bar = x
写成 foo.__dict__['bar'] = x
,无论 foo.__dict__
中是否有这个条目。__setattr__
是用来当你想要改变值、记录赋值或者其他类似操作时使用的。