gpt4 book ai didi

python - 如何使 __getattr__ 可以正确选择的类?

转载 作者:太空宇宙 更新时间:2023-11-03 15:39:41 28 4
gpt4 key购买 nike

我以一种简单的方式扩展了 dict,以使用 d.key 表示法而不是 d['key'] 直接访问它的值:

class ddict(dict):

def __getattr__(self, item):
return self[item]

def __setattr__(self, key, value):
self[key] = value

现在,当我尝试pickle它时,它会调用__getattr__来查找__getstate__,这既不存在也没有必要。使用 __setstate__ 解封时也会发生同样的情况:

>>> import pickle
>>> class ddict(dict):
... def __getattr__(self, item):
... return self[item]
... def __setattr__(self, key, value):
... self[key] = value
...
>>> pickle.dumps(ddict())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __getattr__
KeyError: '__getstate__'

如何修改 ddict 类才能正确选择?

最佳答案

问题不在于 pickle ,而是您的 __getattr__ 方法通过引发 KeyError 异常破坏了预期的约定。您需要修复 __getattr__ 方法以引发 AttributeError 异常:

def __getattr__(self, item):
try:
return self[item]
except KeyError:
raise AttributeError(item)

现在,pickle 已获得缺少 __getstate__ 自定义 Hook 的预期信号。

来自object.__getattr__ documentation :

This method should return the (computed) attribute value or raise an AttributeError exception.

(粗体强调我的)。

如果您坚持保留 KeyError,那么至少您需要跳过以双下划线开头和结尾的名称,并针对以下情况引发 AttributeError:

def __getattr__(self, item):
if isinstance(item, str) and item[:2] == item[-2:] == '__':
# skip non-existing dunder method lookups
raise AttributeError(item)
return self[item]

请注意,您可能想要为您的 ddict() 子类 an empty __slots__ tuple ;您不需要在实例上进行额外的 __dict__ 属性映射,因为您将属性转移到键值对。这可以为每个实例节省大量内存。

演示:

>>> import pickle
>>> class ddict(dict):
... __slots__ = ()
... def __getattr__(self, item):
... try:
... return self[item]
... except KeyError:
... raise AttributeError(item)
... def __setattr__(self, key, value):
... self[key] = value
...
>>> pickle.dumps(ddict())
b'\x80\x03c__main__\nddict\nq\x00)\x81q\x01.'
>>> type(pickle.loads(pickle.dumps(ddict())))
<class '__main__.ddict'>
>>> d = ddict()
>>> d.foo = 'bar'
>>> d.foo
'bar'
>>> pickle.loads(pickle.dumps(d))
{'foo': 'bar'}

pickle 在实例上测试 __getstate__ 方法,而不是在类上测试,如 is the norm for special methods ,改天再讨论。

关于python - 如何使 __getattr__ 可以正确选择的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42272335/

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