在Python中如何检查变量是否是字典?

例如,我希望它循环遍历字典中的值,直到找到一个字典。然后,循环它找到的一个:

dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
for k, v in dict.iteritems():
    if ###check if v is a dictionary:
        for k, v in v.iteritems():
            print(k, ' ', v)
    else:
        print(k, ' ', v)

当前回答

你可以使用if type(ele) is dict,或者使用isinstance(ele, dict),如果你有dict的子类,它就会工作:

d = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
for element in d.values():
    if isinstance(element, dict):
       for k, v in element.items():
           print(k,' ',v)

其他回答

你可以使用if type(ele) is dict,或者使用isinstance(ele, dict),如果你有dict的子类,它就会工作:

d = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
for element in d.values():
    if isinstance(element, dict):
       for k, v in element.items():
           print(k,' ',v)

OP并没有排除起始变量,因此为了完整起见,这里将介绍如何处理一个假定的字典的一般情况,该字典可能包含作为字典的项。

也遵循纯Python(3.8)推荐的方法来测试上面注释中的字典。

from collections.abc import Mapping

my_dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}

def parse_dict(in_dict): 
    if isinstance(in_dict, Mapping):
        for k_outer, v_outer in in_dict.items():
            if isinstance(v_outer, Mapping):
                for k_inner, v_inner in v_outer.items():
                    print(k_inner, v_inner)
            else:
                print(k_outer, v_outer)

parse_dict(my_dict)

在Python中如何检查变量是否是字典?

这是一个很好的问题,但不幸的是,被点赞最多的答案引出了一个糟糕的推荐,type(obj) is dict。

(注意,你也不应该使用dict作为变量名——它是内置对象的名称。)

如果您编写的代码将被其他人导入和使用,不要假定他们将直接使用内置的dict——这种假设会使您的代码更加不灵活,在这种情况下,会创建容易隐藏的错误,而不会使程序出错。

为了将来用户的正确性、可维护性和灵活性,我强烈建议,当代码中有更灵活、更习惯的表达式时,不要使用更不灵活、更不习惯的表达式。

Is是对对象同一性的测试。它不支持继承,不支持任何抽象,也不支持接口。

因此,我将提供几个选项。

支持继承:

这是我提出的第一个建议,因为它允许用户从collections模块中提供自己的dict子类,或者OrderedDict、defaultdict或Counter:

如果isinstance(any_object, dict):

但还有更灵活的选择。

支持抽象:

from collections.abc import Mapping

if isinstance(any_object, Mapping):

这允许代码的用户使用他们自己的抽象映射的自定义实现,它还包括dict的任何子类,并且仍然获得正确的行为。

使用界面

你经常听到面向对象的建议,“编程到接口”。

这种策略利用了Python的多态性或duck-typing。

因此,只需尝试访问接口,捕获特定的预期错误(如果没有.items,则捕获AttributeError,如果项目不可调用,则捕获TypeError),并进行合理的回退-现在任何实现该接口的类都会给你它的项目(注意.iteritems()在Python 3中消失了):

try:
    items = any_object.items()
except (AttributeError, TypeError):
    non_items_behavior(any_object)
else: # no exception raised
    for item in items: ...

也许您会认为使用这样的duck-typing会产生太多的误报,这可能是真的,这取决于代码的目标。

结论

不要使用is检查标准控制流的类型。使用isinstance,考虑像Mapping或MutableMapping这样的抽象,并考虑完全避免类型检查,直接使用接口。

我的测试发现这可以工作,现在我们有类型提示:

from typing import Dict

if isinstance(my_dict, Dict):
    # True
else:
    # False

旁注:一些关于输入的讨论。东西在这里

在python 3.6中

    typeVariable = type(variable)
    
    print('comparison',typeVariable == dict)

    if typeVariable == dict:
        #'true'
    else:
        #'false'