V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
dxandlight
V2EX  ›  Python

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

  •  
  •   dxandlight · 2017-04-10 10:51:12 +08:00 · 2695 次点击
    这是一个创建于 2795 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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__
    4 条回复    2017-04-11 10:29:31 +08:00
    XYxe
        1
    XYxe  
       2017-04-10 12:45:14 +08:00
    在 deepcopy 里面会去找参数对象的__deepcopy__方法,如果可以找到这个方法就直接调用它进行拷贝。
    但是在这里 DotDict 对象没有__deepcopy__,所以就会有 KeyError 。
    deepcopy 里面调用 getattr 的时候会 except AttributeError ,所以在__getattr__里面抛出这个异常可以正常运行了。
    dxandlight
        2
    dxandlight  
    OP
       2017-04-10 19:57:01 +08:00
    @XYxe dict 本身是有__deepcopy__这个的,不会继承么? 还有就是抛出异常,所以也能捕获到啊,然后打印出异常了,那没有,是怎么处理的。
    XYxe
        3
    XYxe  
       2017-04-10 20:27:20 +08:00   ❤️ 1
    @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
        4
    dxandlight  
    OP
       2017-04-11 10:29:31 +08:00
    @XYxe OK 我大概了解了, dict 确实没有__deepcopy__这样的属性,我在仔细研究下,谢谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1015 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 20:44 · PVG 04:44 · LAX 12:44 · JFK 15:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.