backtrader.utils.autodict 源代码

#!/usr/bin/env python
"""AutoDict Module - Enhanced dictionary classes.

This module provides dictionary subclasses with automatic key creation,
dot notation access, and ordered dict support.

Classes:
    AutoDict: Dict with automatic nested dict creation.
    AutoOrderedDict: OrderedDict with automatic nested dict creation.
    DotDict: Dict with attribute-style access (obj.key).
    AutoDictList: Dict with automatic list creation for missing keys.

Example:
    >>> d = AutoOrderedDict()
    >>> d['a']['b']['c'] = 1  # Automatically creates nested dicts
    >>> print(d['a']['b']['c'])
    1
"""

from collections import OrderedDict, defaultdict

# from .py3 import values as py3lvalues
from backtrader.utils.py3 import values as py3lvalues  # Changed relative import to absolute import


[文档] def Tree(): """Create a recursive defaultdict structure. Returns a defaultdict that automatically creates nested defaultdicts for any missing key, allowing for infinite nesting. Returns: defaultdict: A recursive defaultdict structure. """ return defaultdict(Tree)
[文档] class AutoDictList(dict): """Dictionary that creates an empty list for missing keys. When accessing a key that doesn't exist, automatically creates a new empty list for that key. Example: >>> d = AutoDictList() >>> d['key'].append('value') >>> print(d['key']) ['value'] """ # Inherits dict, when accessing missing key, will automatically generate a key value, corresponding value is an empty list # This newly created class is only used in collections.defaultdict(AutoDictList) line def __missing__(self, key): value = self[key] = list() return value
[文档] class DotDict(dict): """Dictionary with attribute-style access. Allows accessing dictionary values as attributes using dot notation. If an attribute is not found in the usual places, the dict itself is checked. Example: >>> d = DotDict() >>> d['key'] = 'value' >>> print(d.key) 'value' """ # If the attribute is not found in the usual places, try the dict itself # This class is only used in the following line, when accessing attributes, if attribute doesn't exist, __getattr__ will be called # _obj.dnames = DotDict([(d._name, d) for d in _obj.datas if getattr(d, '_name', '')]) def __getattr__(self, key): if key.startswith("__"): return super().__getattr__(key) return self[key]
# This function has slightly wider usage, mainly called in tradeanalyzer and ibstore, is an extension of Python dict # Compared to Python built-in dict, added an attribute: _closed, added functions _close, _open, __missing__, __getattr__, overrode __setattr__
[文档] class AutoDict(dict): """Dictionary with automatic nested dict creation and closeable state. Extends dict with: - Automatic nested dict creation for missing keys - Closeable state (_closed) to prevent further auto-creation - Attribute-style access Attributes: _closed: If True, __missing__ raises KeyError instead of creating nested dicts. Methods: _close(): Set _closed to True to prevent auto-creation. _open(): Set _closed to False to enable auto-creation. """ # Initialize default attribute _closed to False _closed = False # _close method
[文档] def _close(self): # Change class attribute to True self._closed = True # For values in dict, if they are instances of AutoDict or AutoOrderedDict, call _close method to set attribute _closed to True for key, val in self.items(): if isinstance(val, (AutoDict, AutoOrderedDict)): val._close()
# _open method, set _closed attribute to False
[文档] def _open(self): self._closed = False
# __missing__ method handles case when key doesn't exist, if _closed, return KeyError, if not, create an AutoDict() instance for this key def __missing__(self, key): if self._closed: raise KeyError value = self[key] = AutoDict() return value # __getattr__ method is redundant, if will never be reached, can delete if statement, even this method can be deleted def __getattr__(self, key): if False and key.startswith("_"): raise AttributeError return self[key] # __setattr__ method is also redundant, can consider deleting def __setattr__(self, key, value): if False and key.startswith("_"): self.__dict__[key] = value return self[key] = value
# Created a new ordered dict, added some functions, similar to AutoDict
[文档] class AutoOrderedDict(OrderedDict): """OrderedDict with automatic nested dict creation and closeable state. Combines OrderedDict's insertion ordering with AutoDict's automatic nested dict creation and closeable state. Attributes: _closed: If True, __missing__ raises KeyError instead of creating nested dicts. Methods: _close(): Set _closed to True to prevent auto-creation. _open(): Set _closed to False to enable auto-creation. Example: >>> d = AutoOrderedDict() >>> d['a']['b'] = 1 # Automatically creates nested dicts >>> d._close() # Prevent further auto-creation """ _closed = False
[文档] def _close(self): self._closed = True for key, val in self.items(): if isinstance(val, (AutoDict, AutoOrderedDict)): val._close()
[文档] def _open(self): self._closed = False
def __missing__(self, key): if self._closed: raise KeyError # value = self[key] = type(self)() value = self[key] = AutoOrderedDict() return value # __getattr__ and __setattr__ functions are much more normal compared to AutoDict def __getattr__(self, key): if key.startswith("_"): raise AttributeError return self[key] def __setattr__(self, key, value): if key.startswith("_"): self.__dict__[key] = value return self[key] = value # Defined math operations, not sure what they mean for now, but it seems only __iadd__ and __isub__ are normal # Define math operations def __iadd__(self, other): if not isinstance(other, type(self)): return type(other)() + other return self + other def __isub__(self, other): if not isinstance(other, type(self)): return type(other)() - other return self - other def __imul__(self, other): if not isinstance(other, type(self)): return type(other)() * other return self + other def __idiv__(self, other): if not isinstance(other, type(self)): return type(other)() // other return self + other def __itruediv__(self, other): if not isinstance(other, type(self)): return type(other)() / other return self + other
[文档] def lvalues(self): """Return dictionary values as a list. Provides Python 2/3 compatible list of values. Returns: list: List of all values in the dictionary. """ return py3lvalues(self)
if __name__ == "__main__": aod = AutoOrderedDict() print("aod", dir(aod)) od = OrderedDict() print("od", dir(od))