我想构建一个系统,其中每个其他对象都使用一个基类。每个基础对象在内部都有一个_fields
字典,其中基类的实现可以存储其信息。结合__setattr__和__getattr__导致无限循环
基类的实现很简单:
class A(object):
def __init__(self, fields=dict()):
self._fields = fields
类的实现可以设置在__init__
调用其super()
领域。
我想补充说的是,这些字段可以作为属性访问,而不必将@property
修饰器添加到一大堆函数中。我已经重写了__getattr__
用于此目的的基类,像这样:
class A_impl(A):
def __init__(self):
super(A_impl, self).__init__(
fields=dict(
val_1="foo",
val_2="",
val_3="bar",
)
)
通过它创建该类的实现提供:
class A(object):
def __init__(self, fields=dict()):
self._fields = fields
def __getattr__(self, name):
if hasattr(self, name):
return object.__getattribute__(self, name)
elif name in self._fields:
return self._fields.get(name)
else:
raise AttributeError
现在对于这个类实现可以这样工作你选择做:
test = A_imp()
print test.val_1
print test.val_2
print test.val_3
它返回
foo
bar
我甚至可以通过@property
装饰覆盖此,改变类,像这样:
class A_impl(A):
def __init__(self):
super(A_impl, self).__init__(
fields=dict(
val_1="foo",
val_2="",
val_3="bar",
)
)
@property
def val_1(self):
return self._fields.get('val_1') + "_getter"
,让我来操纵数据的回报。唯一的问题是,如果我想能够设置这些字段变量之一,我必须实现描述符设置函数,这也需要我做属性描述符,它创造了很多重复的工作(即我必须定义我的所有字段描述这是我想避免在这里。
我实现了__setattr__
功能的基类来解决地方如果我手动实现它应该在默认这是self._field[name] = value
选择一个描述符setter函数问题基类现在看起来像这样(类似于__getattr__
):
class A(object):
def __init__(self, fields=dict()):
self._fields = fields
def __getattr__(self, name):
if hasattr(self, name):
return object.__getattribute__(self, name)
elif name in self._fields:
return self._fields.get(name)
else:
raise AttributeError
def __setattr__(self, name, value):
if hasattr(self, name):
object.__setattr__(self, name, value)
elif name in self._fields:
self._fields[name] = value
else:
raise AttributeError
现在,如果我再次运行相同的代码测试:
test = A_imp()
print test.val_1
print test.val_2
print test.val_3
,瞬间陷在一个无限循环,它开始在__setattr__
但跳进右后__getattr__
,并保持该循环。
我一直在阅读很多关于这个stackoverflow的问题,无法弄清楚,这就是为什么我建立这个测试用例,以清楚地弄清楚它。希望有人能够为我澄清这一点,并帮助我解决问题。
'hasattr'是不必要的。 – o11c