我正在实现某种延迟加载。我有一个字典,每个键的值都是一个空列表。当我访问一个键时,我需要运行一些加载逻辑来用相应的列表填充一些值。
因此,当我创建字典(让其命名为d
)时,会创建一些密钥:a:[], b:[]
。现在,当我访问字典中的一个键时:d['a']
我需要运行一些基本上返回计算列表的逻辑(让我们说[1, 2, 3]
)并且d
dict变为:a: [1, 2, 3], b:[]
。
我希望我能够很好地解释事情。据我所知,这与Python中的描述符类似,因为您可以将自定义逻辑附加到属性。但我需要的是将自定义逻辑附加到字典的键,这肯定不能与描述符一起使用。
有没有办法做到这一点?或者也许我可以使用描述符,但以其他方式?
答案 0 :(得分:2)
您可以在__getitem__
:
class LazyDict(dict):
def __init__(self, *args, **kwargs):
super(LazyDict, self).__init__(*args, **kwargs)
# init a set which will keep the already loaded keys
self._loaded = set()
def __getitem__(self, item):
if item in self and item not in self._loaded:
# do the "lazy" action
self[item] = some_function(item)
self._loaded.add(item)
# return the value
return super(LazyDict, self).__getitem__(self, item)
some_function
将填充各个键。
如果您的卸载密钥始终为空列表,__getitem__
也可能如下所示:
def __getitem__(self, item):
value = super(LazyDict, self).__getitem__(self, item)
if not value:
value = self[item] = some_function(item)
return value
此版本不需要额外的_loaded
设置来跟踪加载的是哪些密钥。
答案 1 :(得分:0)
您可以专门化dict
课程。
class MyDict(dict):
# __init__ here is redundant - it can safely be ommited.
def __init__(self, *args, **kwargs):
super(MyDict, self).__init__(*args, **kwargs)
def __getitem__(self, key):
print("Getting item")
return super(MyDict, self).__getitem__(key)
d = MyDict()
d[4] = 8
print(d[4])
打印:
>>> Getting item
>>> 8
class FunctionRel:
def __init__(self):
self.rel = {
1: self.function_1,
2: self.function_2,
3: self.function_3,
}
def __call__(self, key):
return self.rel[key]()
def function_1(self): return [1,1,1]
def function_2(self): return [2,2,2]
def function_3(self): return [3,3,3]
def wrapper(func):
rel = FunctionRel()
def black_magic(d, key, **kwargs):
if key not in d.visited_keys:
l = rel(key)
d[key] = l
d.visited_keys.append(key)
return l
return black_magic
class MyDict(dict):
def __init__(self, *args, **kwargs):
self.visited_keys = [] # Avoid recirsion in __getitem__ wrapper.
super(MyDict, self).__init__(*args, **kwargs)
@wrapper
def __getitem__(self, key):
return super(MyDict, self).__getitem__(key)
d = MyDict()
print(d[1])
print(d[2])
print(d[3])
输出:
>>> [1,1,1]
>>> [2,2,2]
>>> [3,3,3]
答案 2 :(得分:-3)
当您将值作为空列表时,如果d [key]为空列表,则可以首次检查,然后使用函数获取适当的值。如果从函数返回的值有可能是空列表,您可能希望使用另一个字典来跟踪到目前为止已访问的键。