Если вы не отделяете аргументы от вызываемого, я не думаю, что это возможно. Однако это должно работать:
class MySettingsDict(dict):
def __getitem__(self, item):
function, arg = dict.__getitem__(self, item)
return function(arg)
def expensive_to_compute(arg):
return arg * 3
И сейчас:
>>> settings = MySettingsDict({
'expensive1': (expensive_to_compute, 1),
'expensive2': (expensive_to_compute, 2),
})
>>> settings['expensive1']
3
>>> settings['expensive2']
6
Редактировать:
Вы также можете кэшировать результаты 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.
21.05.2013
__getitem__
— это умно, хотя я думаю, что было бы лучше наследовать abc.Mapping вместо встроенного dict. В противном случае он не поддерживает .get(). Вы можете проверить мой пример здесь gist.github.com/ligyxy/9b50bb8537069b4e154fec41a4b5995a 10.11.2017