问题
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