- Is it reasonable to use None as a dictionary key in Python?
- 6 Answers 6
- Python dict none values
- # Table of Contents
- # Remove None values from a Dictionary in Python
- # Remove None values from a Dictionary using a for loop
- # Adding the not-None key-value pairs to a new dictionary
- # Remove the None values from a nested Dictionary in Python
- # Replace None values in a Dictionary in Python
- # Replace None values in a Dictionary using dict comprehension
- # Additional Resources
- How I can get rid of None values in dictionary?
- 7 Answers 7
Is it reasonable to use None as a dictionary key in Python?
None seems to work as a dictionary key, but I am wondering if that will just lead to trouble later. For example, this works:
The actual data I am working with is educational standards. Every standard is associated with a content area. Some standards are also associated with content subareas. I would like to make a nested dictionary of the form > . Some of those contentSubArea keys would be None. In particular, I am wondering if this will lead to confusion if I look for a key that does not exist at some point, or something unanticipated like that.
What does cause trouble is using NaN as a key. It’s deceptive, because it’s hashable, but doesn’t compare equal to itself. That is: float(‘nan’) == float(‘nan’) returns False , as it should, on two Python implementations I’ve tried. If you use it as a key in a dictionary, it won’t raise an exception, and using it as an index will work if and only if it is the same NaN object (has the same id(..) ) — though this might be implementation-dependent. So it might work as expected for a while, and then fail. None of these troubles affect None , even just because there is only one None .
6 Answers 6
Any hashable value is a valid Python Dictionary Key. For this reason, None is a perfectly valid candidate. There’s no confusion when looking for non-existent keys — the presence of None as a key would not affect the ability to check for whether another key was present. Ex:
>>> d = >>> 1 in d True >>> 5 in d False >>> None in d True
There’s no conflict, and you can test for it just like normal. It shouldn’t cause you a problem. The standard 1-to-1 Key-Value association still exists, so you can’t have multiple things in the None key, but using None as a key shouldn’t pose a problem by itself.
The problem is when you want to sort the dict by key. I suppose for such case you need to create special object for replacing the None type.
You want trouble? here we go:
So yea, better stay away from json if you do use None as a key. You can patch this by custom (de/)serializer, but I would advise against use of None as a key in the first place.
None is not special in any particular way, it’s just another python value. Its only distinction is that it happens to be the return value of a function that doesn’t specify any other return value, and it also happens to be a common default value (the default arg of dict.get() , for instance).
You won’t cause any run-time conflicts using such a key, but you should ask yourself if that’s really a meaningful value to use for a key. It’s often more helpful, from the point of view of reading code and understanding what it does, to use a designated instance for special values. Something like:
NoSubContent = SubContentArea(name=None) >
Doesn’t this approach just move the use of None down a level? I was thinking it might be better to only set values that have meanings. Then None represents empty data, and errors indicate problems with data (assuming proper validation and requirements such as allowing null or requiring not null).
Like I said, there’s nothing really special about None , and I don’t think I’d hesitate to use it as a key in a dict if it were obvious what that must mean for that dict; but if the dict is reasonably heterogeneous, or visible across a large part of the program; adding some meaning to the type of the key could be helpful. It’s not so much a question of avoiding the None value as picking a unity value with a type that explains itself better than None can.
I accepted gddc’s answer, but upvoted this answer as well. Using None is working so far, but I can see the advantages to creating a specific key to represent None in a specific context.
I don’t think you want to ‘use a key to represent None ‘ that’s absurd, just use None if you need to represent None . On the other hand, you might use None to represent a degenerate case of your particular application domain, or that could be confusing so you use a designated instance of another class to represent that degenerate case.
Python dict none values
Last updated: Feb 18, 2023
Reading time · 5 min
# Table of Contents
# Remove None values from a Dictionary in Python
Use a dict comprehension to remove None values from a dictionary in Python.
The dict comprehension will get passed each key-value pair in the dictionary where we can check if the value is not None before including it in the final result.
Copied!my_dict = 'name': 'Bobby Hadz', 'age': None, 'country': None, 'language': 'German' > new_dict = key: value for key, value in my_dict.items() if value is not None > # 👇️ print(new_dict)
Dict comprehensions are very similar to list comprehensions.
They perform some operation for every key-value pair in the dictionary or select a subset of key-value pairs that meet a condition.
Note that this approach doesn’t remove the None values from the dictionary in place, it creates a new dictionary that doesn’t contain any None values.
An alternative approach is to use a for loop.
# Remove None values from a Dictionary using a for loop
This is a three-step process:
- Use a for loop to iterate over the dictionary’s items.
- On each iteration, check if the value is None .
- If the value is None , delete the corresponding key.
Copied!my_dict = 'name': 'Bobby Hadz', 'age': None, 'country': None, 'language': 'German', > for key, value in my_dict.copy().items(): if value is None: del my_dict[key] # 👇️ print(my_dict)
We created a copy of the dictionary because it’s not allowed to change the size of a dictionary while iterating over it.
The dict.items method returns a new view of the dictionary’s items ((key, value) pairs).
Copied!my_dict = 'id': 1, 'name': 'Bobby Hadz'> print(my_dict.items()) # 👉️ dict_items([('id', 1), ('name', 'Bobby Hadz')])
On each iteration, we check if the value is None, and if it is, we delete the corresponding key.
This approach mutates the original dictionary.
# Adding the not-None key-value pairs to a new dictionary
You can also add not-None key-value pairs to a new dictionary instead of mutating the original one.
Copied!my_dict = 'name': 'Bobby Hadz', 'age': None, 'country': None, 'language': 'German' > new_dict = > for key, value in my_dict.items(): if value is not None: new_dict[key] = value # 👇️ print(new_dict)
On each iteration, we check if the value is not None , and if it isn’t, we add the key-value pair to a new dictionary.
# Remove the None values from a nested Dictionary in Python
If you need to remove the None values from a nested dictionary, use a recursive function.
Copied!def remove_none_from_dict(dictionary): for key, value in list(dictionary.items()): if value is None: del dictionary[key] elif isinstance(value, dict): remove_none_from_dict(value) elif isinstance(value, list): for item in value: if isinstance(item, dict): remove_none_from_dict(item) return dictionary my_dict = 'name': 'Bobby Hadz', 'age': None, 'country': None, 'language': 'German', 'address': 'country': None, 'city': 'Example' > > # # 'address': > print(remove_none_from_dict(my_dict))
The function uses the dict.items() method to iterate over the supplied dictionary.
On each iteration, we check if the current value is None .
Copied!if value is None: del dictionary[key]
If the condition is met, we delete the key from the dictionary.
The first elif statement checks if the value is a dictionary.
Copied!elif isinstance(value, dict): remove_none_from_dict(value)
If the value is a nested dictionary, we pass it to the function, so it removes the direct None values.
The second elif statement checks if the value is a list.
Copied!elif isinstance(value, list): for item in value: if isinstance(item, dict): remove_none_from_dict(item)
If the value is a list, then it might be a list of dictionaries, so we iterate over the list.
On each iteration, we check if the current item is a dictionary.
If the condition is met, we call the function with the dictionary, so it can remove the direct None values.
# Replace None values in a Dictionary in Python
To replace the None values in a dictionary:
- Use the object_pairs_hook keyword argument of the json.loads() method.
- Check if each value the object_pairs_hook function gets called with is None .
- If it is, replace None with the specified replacement value.
Copied!import json person = 'name': None, 'address': 'country': None, 'city': None, 'street': 'abc 123'>, 'language': 'German', > def replace_none_in_dict(items): replacement = '' return k: v if v is not None else replacement for k, v in items> json_str = json.dumps(person) person = json.loads(json_str, object_pairs_hook=replace_none_in_dict) # 👇️ , 'language': 'German'> print(person)
You can update the replacement variable in the replace_none_in_dict function to change the replacement value.
The json module makes things a little more straightforward if you have nested objects that may have None values.
The json.dumps method converts a Python object to a JSON formatted string.
The json.loads method parses a JSON string into a native Python object.
We passed the object_pairs_hook keyword argument to the json.loads() method and set it to a function.
Copied!def replace_none_in_dict(items): replacement = '' return k: v if v is not None else replacement for k, v in items>
The function is going to get called with a list of key-value pair tuples, e.g. [(‘country’, None), (‘city’, None), (‘street’, ‘abc 123’)] .
In our function, we simply check if the value is not None and return it, otherwise, we return a replacement value.
# Replace None values in a Dictionary using dict comprehension
If your dictionary doesn’t contain nested objects, use a dict comprehension.
Copied!person = 'name': None, 'address': None, 'language': 'German', 'country': 'Germany', > # 👇️ change this if you need to update the replacement value replacement = '' employee = key: value if value is not None else replacement for key, value in person.items() > # 👇️ print(employee)
The dict.items method returns a new view of the dictionary’s items ((key, value) pairs).
Copied!my_dict = 'id': 1, 'name': 'Alice'> print(my_dict.items()) # 👉️ dict_items([('id', 1), ('name', 'Alice')])
In our dict comprehension, we check if each value isn’t None and return it, otherwise, we return a replacement.
Note that this approach wouldn’t work if your dictionary has nested dictionaries that have None values. If that’s the case, use the previous approach.
# Additional Resources
You can learn more about the related topics by checking out the following tutorials:
I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
How I can get rid of None values in dictionary?
This code raise exception because changing of dictionary when iterating. I discover only non pretty solution with another dictionary:
res =<> res.update((a,b) for a,b in kwargs.iteritems() if b is not None)
7 Answers 7
Another way to write it is
res = dict((k,v) for k,v in kwargs.iteritems() if v is not None)
d = dict(a = 1, b = None, c = 3) filtered = dict(filter(lambda item: item[1] is not None, d.items())) print(filtered)
d = print dict(filter(lambda x:x[1], d.items()))
I like the variation of your second method:
res = dict((a, b) for (a, b) in kwargs.iteritems() if b is not None)
it’s Pythonic and I don’t think that ugly. A variation of your first is:
for (a, b) in list(kwargs.iteritems()): if b is None: del kwargs[a]
If you need to handle nested dict s, then you can leverage a simple recursive approach:
# Python 2 from collections import Mapping def filter_none(d): if isinstance(d, Mapping): return dict((k, filter_none(v)) for k, v, in d.iteritems() if v is not None) else: return d # Python 3 from collections.abc import Mapping def filter_none(d): if isinstance(d, Mapping): return else: return d
To anybody who may interests, here’s another way to get rid of None value. Instead of deleting the key, I change the value of None with a placeholder for the same key.
One use case is applying with Spark RDD.map onto null valued JSON.
def filter_null(data, placeholder="[spark]nonexists"): # Replace all `None` in the dict to the value of `placeholder` return dict((k, filter_null(v, placeholder) if isinstance(v, dict) else v if v is not None else placeholder) for k, v in data.iteritems())
For python3, change the iteritems() to items() .