问题:如何检查变量是否是Python中的字典?
您如何检查变量是否是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)
回答 0
您可以使用if type(ele) is dict
或使用isinstance(ele, dict)
将子类化后将起作用的方法dict
:
d = {'abc':'abc','def':{'ghi':'ghi','jkl':'jkl'}}
for ele in d.values():
if isinstance(ele,dict):
for k, v in ele.items():
print(k,' ',v)
回答 1
您如何检查变量是否是Python中的字典?
这是一个很好的问题,但不幸的是,最受支持的答案导致推荐不力type(obj) is dict
。
(请注意,您也不应将其dict
用作变量名-这是内置对象的名称。)
如果您正在编写将要由其他人导入和使用的代码,请不要假定他们将直接使用内置的dict-假定这种假定会使您的代码更加不灵活,在这种情况下,请创建容易隐藏的错误,这些错误不会使程序出错。
我强烈建议,出于将来用户的正确性,可维护性和灵活性的目的,当存在更灵活,惯用的表达式时,请不要在代码中使用较不灵活,唯一的表达式。
is
是对对象身份的测试。它不支持继承,不支持任何抽象,并且不支持接口。
因此,我将提供几种选择。
支持继承:
这是第一个建议,我会做,因为它允许用户提供自己的字典的子类,或者OrderedDict
,defaultdict
或者Counter
从收藏模块:
if isinstance(any_object, dict):
但是,还有更灵活的选择。
支持的抽象:
from collections.abc import Mapping
if isinstance(any_object, Mapping):
这使你的代码使用抽象映射,其中还包括的任何子类的自己的定制实现的用户dict
,并仍然得到正确的行为。
使用界面
您通常会听到OOP建议“接口编程”。
这种策略利用了Python的多态性或鸭子式输入。
因此,只需尝试访问该接口,并通过合理的回退捕获特定的预期错误(AttributeError
在没有错误.items
和无法调用的TypeError
情况下items
)-现在,实现该接口的任何类都将为您提供其项(注意.iteritems()
在Python中已消失) 3):
try:
items = any_object.items()
except (AttributeError, TypeError):
non_items_behavior(any_object)
else: # no exception raised
for item in items: ...
也许您可能会认为,使用这种鸭子式输入方式会导致过多的误报,而且可能取决于您的代码目标。
结论
不要is
用于检查标准控制流的类型。使用isinstance
,考虑类似Mapping
或的抽象MutableMapping
,并考虑直接使用接口完全避免类型检查。
回答 2
OP没有排除起始变量,因此为了完整起见,这里是如何处理处理可能包含条目作为字典的假定字典的一般情况。
还遵循上述注释中纯Python(3.8)建议的测试字典的方法。
from collections.abc import Mapping
dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
def parse_dict(in_dict):
if isinstance(in_dict, Mapping):
for k, v in in_dict.items():
if isinstance(v, Mapping):
for k, v in v.items():
print(k, v)
else:
print(k, v)
parse_dict(dict)