19

我需要一个用于字典的 python 3.1 深度更新函数(一个将递归更新父字典内的子字典的函数)。

但我认为,在未来,我的函数可能不得不处理行为像字典但不是的对象。此外,我想避免使用isinstanceand type(因为它们被认为是不好的,因为我几乎可以在每个 Pythonista 的博客上阅读)。

但是鸭子类型是 Python 哲学的一部分,那么我如何检查一个对象是否类似于字典呢?

谢谢!

编辑:谢谢大家的回答。以防万一,我编写的函数可以在这个地方找到:http: //blog.cafeaumiel.com/public/python/dict_deep_update.py

4

6 回答 6

22

查看集合模块中的(3.x 中新增的)抽象基类(ABC):

http://docs.python.org/3.1/library/collections.html

我会考虑使用 isinstance 对 Mapping 进行检查,如下所示:

>>> import collections
>>> isinstance({},collections.Mapping)
True

然后,如果您制作自己的类似 dict 的类,请制作 collections.Mapping 它的基础之一。

另一条路线是尝试并捕获字典操作的任何异常,但是对于您正在谈论的递归,我宁愿先检查基本类型,也不愿处理找出 dict 或 subdict 或其他 dict 成员曾经或曾经是什么不在那里抛出异常。

编辑添加:检查 Mapping ABC 而不是 dict 的好处是,相同的测试将适用于类似 dict 的类,无论它们是否是 dict 的子类,因此它更灵活,以防万一。

于 2009-08-14T14:08:58.143 回答
3

use isinstance,它没有任何问题,它通常用于需要递归的代码中。

如果通过类似字典的意思是对象的类继承自dict,isinstance也将返回True

>>> class A(dict):
    pass

>>> a = A()
>>> isinstance(a, dict)
True
于 2009-08-14T13:43:29.797 回答
1

Duck typing 是你做你想做的事情的地方,如果你的对象的行为不像你期望的那样,你可以处理后果。

您想检查某些内容是否类似于 dict,如果是,则对其进行更新,对吗?只需调用对象的更新方法,如果没有这样的方法,则处理您得到的异常。

当然,如果您处理具有完全执行其他操作的更新方法的自定义类对象,这将失败——我不太确定如何处理。

于 2009-08-14T13:45:06.660 回答
1

好吧,要递归更新字典,您必须调用“items”方法对其进行迭代。

所以我建议,你只是这样做:

try :
    for key, value in data.items() :
         # recursive call
except AttributeError :
    # handling the trouble
于 2009-08-14T19:47:54.947 回答
0

如果您还必须处理行为类似于字典但不是从 dict 子类化的自定义类,则可以使用 getattr 来获取所需的功能。

# loop
# ... more code
someObject = getObject(..)
try:
    getattr(someObject, "update")("someValue")
except AttributeError:
    # Wasn't a type we can handle
于 2009-08-14T14:45:47.060 回答
0

我喜欢检查' __setitem__ '魔法方法......这就是允许 foo['bar'] = baz 行为的原因。

if getattr(obj, '__setattr__'):
    obj[key] = val

这是python 2.7 文档

于 2014-06-26T18:40:42.357 回答