class PropertyDict
A specialized dictionary subclass that treats None values and missing keys as semantically identical, automatically removing None values and returning None for missing keys instead of raising KeyError.
/tf/active/vicechatdev/resources/py2html.py
842 - 928
moderate
Purpose
PropertyDict provides a mutable key-value store with special None-handling semantics. It's designed for scenarios where the absence of a property and a property with a None value should be treated identically. This is particularly useful for configuration management, optional property storage, and data structures where None values should not be persisted. The class extends Python's built-in dict and overrides key methods to implement its unique behavior: setting a key to None deletes it, and accessing missing keys returns None instead of raising exceptions.
Source Code
class PropertyDict(dict):
""" Mutable key-value property store.
A dictionary for property values that treats :const:`None`
and missing values as semantically identical.
PropertyDict instances can be created and used in a similar way
to a standard dictionary. For example::
>>> fruit = PropertyDict({"name": "banana", "colour": "yellow"})
>>> fruit["name"]
'banana'
The key difference with a PropertyDict is in how it handles
missing values. Instead of raising a :py:class:`KeyError`,
attempts to access a missing value will simply return
:py:const:`None` instead.
These are the operations that the PropertyDict can support:
.. describe:: len(d)
Return the number of items in the PropertyDict `d`.
.. describe:: d[key]
Return the item of `d` with key `key`. Returns :py:const:`None`
if key is not in the map.
.. describe:: d == other
Return ``True`` if ``d`` is equal to ``other`` after all
``None`` values have been removed from ``other``.
.. describe:: properties != other
Return ``True`` if ``d`` is unequal to ``other`` after all
``None`` values have been removed from ``other``.
.. describe:: d[key]
Return the value of *d* with key *key* or ``None`` if the key
is missing.
.. describe:: d[key] = value
Set the value of *d* with key *key* to *value* or remove the
item if *value* is ``None``.
"""
def __init__(self, iterable=None, **kwargs):
dict.__init__(self)
self.update(iterable, **kwargs)
def __eq__(self, other):
if other is None:
return False
return dict.__eq__(self, {key: value for key, value in other.items() if value is not None})
def __ne__(self, other):
return not self.__eq__(other)
def __getitem__(self, key):
return dict.get(self, key)
def __setitem__(self, key, value):
if value is None:
try:
dict.__delitem__(self, key)
except KeyError:
pass
else:
dict.__setitem__(self, key, value)
def setdefault(self, key, default=None):
""" If *key* is in the PropertyDict, return its value. If not,
insert *key* with a value of *default* and return *default*
unless *default* is ``None``, in which case do nothing.
The value of *default* defaults to ``None``.
:param key:
:param default:
:return:
"""
if key in self:
value = self[key]
elif default is None:
value = None
else:
value = dict.setdefault(self, key, default)
return value
def update(self, iterable=None, **kwargs):
""" Update the PropertyDict with the key-value pairs from
*iterable* followed by the keyword arguments from *kwargs*.
Individual properties already in the PropertyDict will be
overwritten by those in *iterable* and subsequently by those
in *kwargs* if the keys match. Any value of ``None`` will
effectively delete the property with that key, should it exist.
:param iterable:
:param kwargs:
:return:
"""
for key, value in dict(iterable or {}, **kwargs).items():
self[key] = value
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
dict | - |
Parameter Details
iterable: Optional iterable of key-value pairs (dict, list of tuples, etc.) to initialize the PropertyDict. Can be None if initializing empty or using only kwargs. Any key-value pairs where value is None will not be stored.
kwargs: Keyword arguments representing additional key-value pairs to initialize the PropertyDict. These are applied after the iterable parameter. Keys with None values will not be stored.
Return Value
Instantiation returns a PropertyDict instance that behaves like a dictionary but with special None-handling. The __getitem__ method returns None for missing keys instead of raising KeyError. The __setitem__ method deletes keys when set to None. The __eq__ method returns a boolean indicating equality after filtering None values from the comparison target.
Class Interface
Methods
__init__(self, iterable=None, **kwargs)
Purpose: Initialize a new PropertyDict instance with optional initial key-value pairs
Parameters:
iterable: Optional iterable of key-value pairs to initialize the dictionarykwargs: Keyword arguments for additional key-value pairs
Returns: None (constructor)
__eq__(self, other) -> bool
Purpose: Compare equality with another dictionary-like object, ignoring None values in the other object
Parameters:
other: Another dictionary-like object to compare against
Returns: True if equal after filtering None values from other, False otherwise (including if other is None)
__ne__(self, other) -> bool
Purpose: Compare inequality with another dictionary-like object
Parameters:
other: Another dictionary-like object to compare against
Returns: True if not equal, False if equal (inverse of __eq__)
__getitem__(self, key) -> Any
Purpose: Retrieve a value by key, returning None for missing keys instead of raising KeyError
Parameters:
key: The key to retrieve the value for
Returns: The value associated with the key, or None if the key doesn't exist
__setitem__(self, key, value) -> None
Purpose: Set a key-value pair, or delete the key if value is None
Parameters:
key: The key to setvalue: The value to associate with the key, or None to delete the key
Returns: None
setdefault(self, key, default=None) -> Any
Purpose: Return the value for key if it exists, otherwise set and return default (unless default is None)
Parameters:
key: The key to check or setdefault: The default value to set if key doesn't exist (defaults to None, which means don't set anything)
Returns: The existing value if key exists, the default value if key doesn't exist and default is not None, or None if default is None
update(self, iterable=None, **kwargs) -> None
Purpose: Update the PropertyDict with key-value pairs from an iterable and/or keyword arguments, deleting keys set to None
Parameters:
iterable: Optional iterable of key-value pairs to update withkwargs: Keyword arguments for additional key-value pairs to update with
Returns: None
Usage Example
# Create a PropertyDict with initial values
fruit = PropertyDict({'name': 'banana', 'colour': 'yellow', 'price': 1.50})
# Access existing key
print(fruit['name']) # Output: 'banana'
# Access missing key (returns None instead of KeyError)
print(fruit['weight']) # Output: None
# Set a value
fruit['organic'] = True
# Set a value to None (deletes the key)
fruit['price'] = None
print('price' in fruit) # Output: False
# Update with multiple values
fruit.update({'colour': 'green', 'ripe': False})
# Use setdefault
fruit.setdefault('origin', 'Ecuador')
print(fruit['origin']) # Output: 'Ecuador'
# Equality comparison (ignores None values in other)
other = {'name': 'banana', 'colour': 'green', 'ripe': False, 'extra': None}
print(fruit == other) # Output: True (extra=None is ignored)
# Create from keyword arguments
vegetable = PropertyDict(name='carrot', colour='orange')
# Length
print(len(fruit)) # Number of non-None items
Best Practices
- Use PropertyDict when you need to treat None values and missing keys identically, such as in configuration management or optional property storage.
- Remember that setting any key to None will delete that key from the dictionary entirely.
- When comparing PropertyDict instances with other dictionaries, be aware that None values in the other dictionary are ignored during equality checks.
- PropertyDict is safe to use with missing keys - it will never raise KeyError on access, always returning None instead.
- The update() method can be used to bulk-set properties, and any None values in the update will delete those keys.
- Use setdefault() when you want to provide a default value only if the key doesn't exist, but be aware that passing None as default will not set anything.
- PropertyDict inherits from dict, so all standard dict methods (keys(), values(), items(), etc.) are available and work as expected.
- This class is thread-safe to the same extent as the built-in dict class (not thread-safe for concurrent modifications).
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
class _Relationship 45.1% similar
-
class Node 42.4% similar
-
class Config_v7 39.8% similar
-
function _sanitize_properties 39.3% similar
-
function resolve_dependent_kwargs 38.2% similar