Use isinstance(ele, dict), which will return true for dict objects as well as subclasses of dict, such as OrderedDict and defaultdict:
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)
You can do if type(ele) is dict if you want to check strictly for instances of dict and not subclasses of it, though this is generally not recommended.
Use isinstance(ele, dict), which will return true for dict objects as well as subclasses of dict, such as OrderedDict and defaultdict:
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)
You can do if type(ele) is dict if you want to check strictly for instances of dict and not subclasses of it, though this is generally not recommended.
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.
Videos
Hi all, I have an object with many fields and attributes that I am usually get via `getattr()`. I want to determine from a list of keys, if any are equal to true in the fastest way possible. For example:
keys = ["apple", "banana"] // Only two for example purposes
dictionary = vars(MyObjectName)
// Sample dictionary contents:
// ["apple" = false, "banana" = True, "orange" = "Hoopla]
for item in dictionary:
if item in keys && dictionary[item]:
return True
return FalseIf "banana" was false, it should return false. Likewise, if "apple" was true and "banana" is false, it would still return True. If both were false, it would return false.
Is there a more efficient means than looping? Something like getattr() accepting a list would be great.
>>> d = {'1': 'one', '3': 'three', '2': 'two', '5': 'five', '4': 'four'}
>>> 'one' in d.values()
True
Out of curiosity, some comparative timing:
>>> T(lambda : 'one' in d.itervalues()).repeat()
[0.28107285499572754, 0.29107213020324707, 0.27941107749938965]
>>> T(lambda : 'one' in d.values()).repeat()
[0.38303399085998535, 0.37257885932922363, 0.37096405029296875]
>>> T(lambda : 'one' in d.viewvalues()).repeat()
[0.32004380226135254, 0.31716084480285645, 0.3171098232269287]
>>> T(lambda : 'four' in d.itervalues()).repeat()
[0.41178202629089355, 0.3959040641784668, 0.3970959186553955]
>>> T(lambda : 'four' in d.values()).repeat()
[0.4631338119506836, 0.43541407585144043, 0.4359898567199707]
>>> T(lambda : 'four' in d.viewvalues()).repeat()
[0.43414998054504395, 0.4213531017303467, 0.41684913635253906]
The reason is that each of the above returns a different type of object, which may or may not be well suited for lookup operations:
>>> type(d.viewvalues())
<type 'dict_values'>
>>> type(d.values())
<type 'list'>
>>> type(d.itervalues())
<type 'dictionary-valueiterator'>
In Python 3, you can use
"one" in d.values()
to test if "one" is among the values of your dictionary.
In Python 2, it's more efficient to use
"one" in d.itervalues()
instead.
Note that this triggers a linear scan through the values of the dictionary, short-circuiting as soon as it is found, so this is a lot less efficient than checking whether a key is present.
Hi all,
Funny enough, I got stuck at this bit while working on a personal project. I have a dictionary of the form:
dict = {
list1: [a, b, c],
list2: [d, e, f],
list3: [g, h],
sub_dict: {
list4: [i, j],
list5: [k, l],
list6: [m, n, o, p]
list7: [q, r, s, t]
}I am trying to see if an element is anywhere in this dictionary. What's the best way to do this? I have tried a nested loop but due to the fact I have a nested dictionary, it ends up "looping" through each element in the lists too and compares my search term, say "Dog" with every letter in the every word of the lists.
Any help is appreciated.