各位大神们,关于 dotdict 的 deepcopy 问题请教。

2017-04-10 10:51:12 +08:00
 dxandlight
class DotDict(dict):
"""Make attribute-style dict.

It allows dict.key to paly with the item.
"""

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

......



>>> a = DotDict({'name': 'Something'})
>>> a.name
'Something'
>>> b = copy.deepcopy(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python/2.7.2/lib/python2.7/copy.py", line 172, in deepcopy
copier = getattr(x, "__deepcopy__", None)
File "<stdin>", line 3, in __getattr__
KeyError: '__deepcopy__'


但是我网上查找答案把__getattr__改成这样
def __getattr__(self, key):
if key in self:
return self[key]
raise AttributeError(key)
就不报错了,但是不知道为什么,求大神解释啊,答案链接 https://www.peterbe.com/plog/must__deepcopy__
2666 次点击
所在节点    Python
4 条回复
XYxe
2017-04-10 12:45:14 +08:00
在 deepcopy 里面会去找参数对象的__deepcopy__方法,如果可以找到这个方法就直接调用它进行拷贝。
但是在这里 DotDict 对象没有__deepcopy__,所以就会有 KeyError 。
deepcopy 里面调用 getattr 的时候会 except AttributeError ,所以在__getattr__里面抛出这个异常可以正常运行了。
dxandlight
2017-04-10 19:57:01 +08:00
@XYxe dict 本身是有__deepcopy__这个的,不会继承么? 还有就是抛出异常,所以也能捕获到啊,然后打印出异常了,那没有,是怎么处理的。
XYxe
2017-04-10 20:27:20 +08:00
@dxandlight #2 dict 没有__deepcopy__吧,你什么版本的?
getattr 源代码里是这样的:
```
result = PyObject_GetAttr(v, name);
if (result == NULL && dflt != NULL && PyErr_ExceptionMatches(PyExc_AttributeError))
{
PyErr_Clear();
Py_INCREF(dflt);
result = dflt;
}
```
其中 v,name,dflt 是 getattr 的三个参数。
也就是如果在 v 里面没找到 name ,并且设置了 dflt 参数,并且发生的错误是 AttributeError ,就把错误清除,然后把 dflt 作为结果返回回去。
换成 Python 的代码大概是:
```
try:
result = v.name
except AttributeError:
result = dflt
return result
```
dxandlight
2017-04-11 10:29:31 +08:00
@XYxe OK 我大概了解了, dict 确实没有__deepcopy__这样的属性,我在仔细研究下,谢谢!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/353733

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX