python los Valor del diccionario como función que se debe invocar cuando se accede a la clave, sin usar "()"




usar diccionario python (4)

Tengo un diccionario que tiene valores a veces como cadenas, y a veces como funciones. Para los valores que son funciones ¿hay alguna manera de ejecutar la función sin escribir explícitamente () cuando se accede a la tecla?

Ejemplo:

d = {1: "A", 2: "B", 3: fn_1}
d[3]() # To run function

Yo quiero:

d = {1: "A", 2: "B", 3: magic(fn_1)}
d[3] # To run function

Use callable() para verificar si la variable es, bueno, invocable:

d = {1: "A", 2: "B", 3: fn_1}
if callable(d[3]):
    d[3]()
else:
    d[3]

Otra posible solución es crear un objeto de diccionario personalizado que implemente este comportamiento:

>>> class CallableDict(dict):
...     def __getitem__(self, key):
...         val = super().__getitem__(key)
...         if callable(val):
...             return val()
...         return val
...
>>>
>>> d = CallableDict({1: "A", 2: "B", 3: lambda: print('run')})
>>> d[1]
'A'
>>> d[3]
run

Una solución quizás más idiomática sería usar try/except :

def __getitem__(self, key):
    val = super().__getitem__(key)
    try:
        return val()
    except TypeError:
        return val

Sin embargo, tenga en cuenta que el método anterior es realmente para la completitud. No recomendaría usarlo. Como se señaló en los comentarios , enmascararía TypeError 's provocado por la función. Podría probar el contenido exacto de TypeError , pero en ese punto, sería mejor que use el estilo LBYL.


Otra solución: también puede pasar algún método de clase decorado con @property :

class Test:
    @property
    def method(self):
        return 'X'

d = {'a': 1, 'b': Test().method}
print(d)
print(d['a'])
print(d['b'])

No creo que eso (sea) posible con la biblioteca estándar, pero podrías usar lazy_object_proxy.Proxy desde el módulo lazy_object_proxy (es un tercero, así que debes instalarlo):

>>> import lazy_object_proxy
>>> def fn_1():
...     print('calculation')
...     return 1000
...
>>> d = {1: "A", 2: "B", 3: lazy_object_proxy.Proxy(fn_1)}
>>> print(d[3])
calculation
1000




callback