Python和类字典对象

Python和类字典对象,python,dictionary,duck-typing,Python,Dictionary,Duck Typing,我需要一个用于字典的python 3.1深度更新函数(一个递归更新父字典中的子字典的函数) 但我认为,在未来,我的函数可能必须处理行为类似于字典但不是字典的对象。此外,我想避免使用isinstance和类型(因为它们被认为是不好的,因为我几乎可以在每一个Pythonista的博客上读到) 但是duck类型是Python哲学的一部分,所以我如何检查对象是否像字典一样 谢谢 编辑:谢谢大家的回答。为了以防万一,我编写的函数可以在这里找到:使用isinstance,它没有任何问题,并且在需要递归的代码

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

但我认为,在未来,我的函数可能必须处理行为类似于字典但不是字典的对象。此外,我想避免使用
isinstance
类型
(因为它们被认为是不好的,因为我几乎可以在每一个Pythonista的博客上读到)

但是duck类型是Python哲学的一部分,所以我如何检查对象是否像字典一样

谢谢


编辑:谢谢大家的回答。为了以防万一,我编写的函数可以在这里找到:

使用
isinstance
,它没有任何问题,并且在需要递归的代码中经常使用它

如果您所说的dictionary like是指对象的类继承自
dict
isinstance
也将返回
True

>>> class A(dict):
    pass

>>> a = A()
>>> isinstance(a, dict)
True

Duck类型是你做你想做的事情的地方,如果你的对象没有按你所期望的方式运行,那么你可以处理它带来的后果

您想检查某个内容是否与dict类似,如果是,则进行更新,对吗?只要调用对象的update方法,如果没有这样的方法,就可以处理得到的异常

当然,如果您处理的自定义类对象具有完全执行其他操作的更新方法,则这一点将变得平淡无奇。我不太确定如何处理这一点。

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

我会考虑用IS实例检查映射,比如如下:

>>> import collections
>>> isinstance({},collections.Mapping)
True
然后,如果您创建了自己的类似dict的类,那么就创建集合。映射它的一个基

另一种方法是尝试并捕获字典操作的任何异常,-但是对于您所说的递归,我宁愿先检查基类型,而不是处理确定什么dict或subct或其他dict成员在那里抛出异常


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

如果您还必须处理行为类似字典但不是dict的子类的自定义类,您可以使用getattr获取所需的函数

# loop
# ... more code
someObject = getObject(..)
try:
    getattr(someObject, "update")("someValue")
except AttributeError:
    # Wasn't a type we can handle

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

所以我建议,你只要:

try :
    for key, value in data.items() :
         # recursive call
except AttributeError :
    # handling the trouble

我想检查“\uuuuu setitem\uuuu”魔术方法。。。这就是允许foo['bar]=baz行为的原因

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

以下是绝对正确的

:ABC让您“针对接口编程,而不是实现”,正如Gof4所敦促的那样Gof4是“四人帮”的缩写,这本书的作者通常被称为“四人帮”,因为这比说出他们所有的名字要容易:是的,顺便说一句,我强烈推荐这本书,尽管我的同事乔·格雷戈里奥也强烈反对(他声称Python中没有DPs——呵呵——希望我们能在本地Python用户组未来的某个会议上就这个问题进行辩论!-)。这个例子应该一直适用于Python 2.4(当collections模块出现时)。它在Python 2.7上工作。请参见Py 2和Py 3.8。Support始终对博客上的笼统陈述持保留态度。我非常喜欢duck类型和“请求原谅比允许更容易”的说法方法,但请参阅PEP 3119关于ABC的内容,如下面我的回答中所述,以获得更细致的讨论:--您可以在此处测试所述方法的存在性。fac是我不想针对dict类而针对其接口进行编码:)我不使用dict类中的update方法。相反,我手动遍历字典,当一个值是一个类似字典的对象时,我尝试递归调用我的函数来更新它。列表还有
\uuuuuuu setitem\uuuuuu
\uuuu getitem\uuuuu