按需设置字典

2024-10-01 11:41:14 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我在python中有一个在模块级别(mysettings.py)定义的字典:

settings = {
    'expensive1' : expensive_to_compute(1),
    'expensive2' : expensive_to_compute(2),
    ...
}

我希望在访问密钥时计算这些值:

^{pr2}$

这可能吗?怎样?在


Tags: 模块topy字典settings定义密钥级别
3条回答

不要继承dict中的内部版本。即使重写dict.__getitem__()方法,dict.get()也不会如预期的那样工作。在

正确的方法是从collections继承abc.Mapping。在

from collections.abc import Mapping

class LazyDict(Mapping):
    def __init__(self, *args, **kw):
        self._raw_dict = dict(*args, **kw)

    def __getitem__(self, key):
        func, arg = self._raw_dict.__getitem__(key)
        return func(arg)

    def __iter__(self):
        return iter(self._raw_dict)

    def __len__(self):
        return len(self._raw_dict)

然后您可以:

^{pr2}$

我还列出了示例代码和示例:https://gist.github.com/gyli/9b50bb8537069b4e154fec41a4b5995a

如果你不把论点和可调用的分开,我认为这是不可能的。但是,这应该是有效的:

class MySettingsDict(dict):

    def __getitem__(self, item):
        function, arg = dict.__getitem__(self, item)
        return function(arg)


def expensive_to_compute(arg):
    return arg * 3

现在:

^{pr2}$

编辑:

如果要多次访问expensive_to_compute的结果,则可能还需要缓存这些结果。像这样的东西

class MySettingsDict(dict):

    def __getitem__(self, item):
        value = dict.__getitem__(self, item)
        if not isinstance(value, int):
            function, arg = value
            value = function(arg)
            dict.__setitem__(self, item, value)
        return value

现在:

>>> settings.values()
dict_values([(<function expensive_to_compute at 0x9b0a62c>, 2),
(<function expensive_to_compute at 0x9b0a62c>, 1)])
>>> settings['expensive1']
3
>>> settings.values()
dict_values([(<function expensive_to_compute at 0x9b0a62c>, 2), 3])

根据您希望如何使用dict,您可能还希望重写其他dict方法

将对函数的引用存储为键的值,即:

def A():
    return "that took ages"
def B():
    return "that took for-ever"
settings = {
    "A": A,
    "B": B,
}

print(settings["A"]())

这样,只有在访问并调用与键相关联的函数时,才能计算它。可以处理非延迟值的合适类是:

^{pr2}$

用法:

settings = LazyDict([("A",A),("B",B)])
print(settings["A"])
>>> 
that took ages

相关问题 更多 >