问题:如何检查变量是否是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)

How would you check if a variable is a dictionary in python?

For example, I’d like it to loop through the values in the dictionary until it finds a dictionary. Then, loop through the one it finds:

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)

You could use if type(ele) is dict or use isinstance(ele, dict) which would work if you had subclassed 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是对对象身份的测试。它不支持继承,不支持任何抽象,并且不支持接口。

因此,我将提供几种选择。

支持继承:

这是第一个建议,我会做,因为它允许用户提供自己的字典的子类,或者OrderedDictdefaultdict或者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,并考虑直接使用接口完全避免类型检查。

How would you check if a variable is a dictionary in Python?

This is an excellent question, but it is unfortunate that the most upvoted answer leads with a poor recommendation, type(obj) is dict.

(Note that you should also not use dict as a variable name – it’s the name of the builtin object.)

If you are writing code that will be imported and used by others, do not presume that they will use the dict builtin directly – making that presumption makes your code more inflexible and in this case, create easily hidden bugs that would not error the program out.

I strongly suggest, for the purposes of correctness, maintainability, and flexibility for future users, never having less flexible, unidiomatic expressions in your code when there are more flexible, idiomatic expressions.

is is a test for object identity. It does not support inheritance, it does not support any abstraction, and it does not support the interface.

So I will provide several options that do.

Supporting inheritance:

This is the first recommendation I would make, because it allows for users to supply their own subclass of dict, or a OrderedDict, defaultdict, or Counter from the collections module:

if isinstance(any_object, dict):

But there are even more flexible options.

Supporting abstractions:

from collections.abc import Mapping

if isinstance(any_object, Mapping):

This allows the user of your code to use their own custom implementation of an abstract Mapping, which also includes any subclass of dict, and still get the correct behavior.

Use the interface

You commonly hear the OOP advice, “program to an interface”.

This strategy takes advantage of Python’s polymorphism or duck-typing.

So just attempt to access the interface, catching the specific expected errors (AttributeError in case there is no .items and TypeError in case items is not callable) with a reasonable fallback – and now any class that implements that interface will give you its items (note .iteritems() is gone in Python 3):

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

Perhaps you might think using duck-typing like this goes too far in allowing for too many false positives, and it may be, depending on your objectives for this code.

Conclusion

Don’t use is to check types for standard control flow. Use isinstance, consider abstractions like Mapping or MutableMapping, and consider avoiding type-checking altogether, using the interface directly.


回答 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)

The OP did not exclude the starting variable, so for completeness here is how to handle the generic case of processing a supposed dictionary that may include items as dictionaries.

Also following the pure Python(3.8) recommended way to test for dictionary in the above comments.

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_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(dict)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。