问题描述
因此,我最近在尝试实现某种 DotDict
时想出了一个拙劣的可憎的类:
- 启用键值点访问。
- 接受
defaults
Namespace
/Dataclass
作为包含默认值的额外参数。 - 在点访问时执行修改的
get()
,通过检查是否可以在defaults
中找到默认值,否则返回None
。
此外,该类应在初始化时将其值中找到的任何 dict
递归转换为 Dotdict
,并将每个新值转换为 class DotDict(dict):
def __init__(self,base_dict=None,defaults=None):
self.defaults = defaults if defaults is not None else SimpleNamespace()
base_dict = base_dict if base_dict is not None else {}
super().__init__(**base_dict)
for key,value in base_dict.items():
self[key] = self._convert(value)
def __getattr__(self,key):
if key in self:
return self[key]
elif hasattr(self.defaults,key):
return getattr(self.defaults,key)
else:
return None
def __setattr__(self,key,value):
self[key] = value
def __delattr__(self,key):
try:
del self[key]
except KeyError as error:
raise AttributeError(error)
def _convert(self,element):
if isinstance(element,dict):
return DotDict(
{key: self._convert(value) for key,value in element.items()},defaults=self.defaults,)
elif isinstance(element,list):
return [self._convert(subelement) for subelement in element]
else:
return element
。
外观如下:
default
尽管它可能违背了所有常识和大约十几种最佳实践,但这种方法确实有效 - 除了一个细节:我还没有找到一种方法来分配 de items()
属性而不将其添加到实例的 __setattr__
。这是有道理的,因为 __setattr__
方法会立即被其点访问版本覆盖。
为清晰起见进行了编辑
上面的段落措辞非常糟糕,以至于实际上问错了问题。我知道有几种方法可以在不诉诸类自己的 user2357112 supports Monica
的情况下分配属性,正如 {{1}} 所指出的那样,确实可以解决这个特定问题。
上面描述的代码是为了说明导致我问自己这篇文章的实际问题的过程。现在以全新的眼光阅读整件事让我意识到最初问题的大部分细节充其量是不必要的,并且可能会令人困惑。我会把它留给透明,但如果我要从头开始重写这个问题,那就是:
有没有办法在实例初始化之后覆盖任何类方法?
解决方法
如果要使用标准的__setattr__
,只需使用标准的__setattr__
:
object.__setattr__(self,'defaults',defaults)
其他选项包括使用 super
通过 super().__setattr__('defaults',defaults)
调用它或使用 self.__dict__
手动将属性粘贴到 self.__dict__['defaults'] = defaults
中。