问题
I have a dictionary that has values sometimes as strings, and sometimes as a functions. For the values that are functions is there a way to execute the function without explicitly typing ()
when the key is accessed?
Example:
d = {1: "A", 2: "B", 3: fn_1}
d[3]() # To run function
I want:
d = {1: "A", 2: "B", 3: magic(fn_1)}
d[3] # To run function
回答1:
Another possible solution, is to create a custom dictionary object that implements this behavior:
>>> 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
A perhaps more idiomatic solution would be to use try/except
:
def __getitem__(self, key):
val = super().__getitem__(key)
try:
return val()
except TypeError:
return val
Note however the method above is really for completness. I would not reccomend using it. As pointed out in the comments, it would mask TypeError
's raised by the function. You could test the exact content of TypeError
, but at that point, you'd be better of using the LBYL style.
回答2:
I don't think that's (easily) possible with the standard library but you could use lazy_object_proxy.Proxy
from the module lazy_object_proxy (it's third party so you need to install it):
>>> 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
回答3:
Use callable()
to check if variable is, well, callable:
d = {1: "A", 2: "B", 3: fn_1}
if callable(d[3]):
d[3]()
else:
d[3]
回答4:
You can try this:
declare the dictionary with its keys and the name of each
function without the()
functions = {'1': function1, '2':fuction2, '3':fuction3 ,...}
pass the function/value by using the method get, which returns None
if the key doesn't exists
action = functions.get(key)
- call the function ,which is stored in the var action, + ()
action()
- your function will be executed.
回答5:
Another solution: you can also pass some class method decorated using @property
:
class Test:
@property
def method(self):
return 'X'
d = {'a': 1, 'b': Test().method}
print(d)
print(d['a'])
print(d['b'])
来源:https://stackoverflow.com/questions/46106779/dictionary-value-as-function-to-be-called-when-key-is-accessed-without-using