gpt4 book ai didi

python - __getattr__ 的对应部分

转载 作者:太空宇宙 更新时间:2023-11-03 14:31:32 26 4
gpt4 key购买 nike

我正在尝试找到一种方法来设置封装到 class 中的 dict 值,例如使用 __getattr__ 我可以返回内部 dict 值,但是即使属性存在,也会调用 __setattr__,这让我的实现变得丑陋。下面的示例简化了我的实际类继承自 Subject class(观察者模式的主题部分)

我正在努力实现这样的目标:

obj = Example()
obj.username = 'spidername' # all OK username is a key in the internal dict
# but company is not a key in the internal dict so
obj.company = 'ABC' # will raise AttributeError

我想问是否有比我在下面做的方式更好的方法:

class Example(object):
def __init__(self, table=None):
self._fields = {}
self._table = table

def _set_fields(self):
"""
this method will be implemented by
subclasses and used to set fields names and values
i.e.
self._field['username'] = Field(default='unknown', is_primary=False)
"""
raise NotImplementedError

def __getattr__(self, name):
"""
great this method is only called when "name"
is not an attribute of this class
"""
if name in self._fields:
return self._fields[name].value
return None

def __setattr__(self, name, value):
"""
not so great, this method is called even for
attributes that exists in this class

is there a better way to do the following?
this can be in __init__, but its still ugly
"""
attribs = ['_fields', '_table']
if name in attribs:
super(Example, self).__setattr__(name, value)
else:
if name in self._fields:
self._fields[name].value = value
else:
raise AttributeError

编辑:调整了代码中的注释,添加了遗漏的引号

最佳答案

问题是属性在第一次赋值时并不存在。在 __init__ 中,当您第一次将字典分配给 _fields 时,_fields 不是属性。它只有在分配后才成为现有属性。如果您事先知道属性是什么,则可以使用 __slots__,但我猜您不知道。所以我的建议是手动将它们插入到实例字典中:

class Example(object):
def __init__(self, table=None):
self.__dict__['_fields'] = {}
self.__dict__['_table'] = table

...

def __setattr__(self, name, value):
if name in self._fields:
self._fields[name].value = value
else:
raise AttributeError

但是,对于此实现,您以后可以添加或更改实例属性的唯一方法是通过 __dict__。但我认为这不太可能。

关于python - __getattr__ 的对应部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9987473/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com