[英]A way to automatically pass parameters to a function?
我在一個模塊中有一堆回調函數。 它們都調用some_func()
,第一個參數總是相同的,並且來自它們自己的參數,而其他參數則不同。 像這樣:
from outer.space import some_func
def callback_A(param1, param2, param3):
...
some_func(param2+param1, param3, ..., ...)
...
def callback_B(param1, param2, param3, param4):
...
some_func(param2+param1, param3, ..., ...)
...
這在代碼中無處不在。 而且比 param2+param1 更丑陋。
在 C/C++ 中,我只是做一個宏
#define S_F(a,b) some_func(param2+param1, param3, a, b)
並開始在回調中使用 S_F 而不是some_func
。 我可以用 Python 做什么?
您可以使用functools.partial
>>> from functools import partial
>>> def my_function(a,b,c,d,e):
... print (a,b,c,d,e)
...
>>> func_with_defaults = partial(my_function, 1, 2, e=5)
>>> func_with_defaults(3, 4)
(1, 2, 3, 4, 5)
編輯:
由於您事先沒有這些值,因此您不能使用partial
或lambda
。 您可能會嘗試這樣做:
>>> A = lambda x: x + y
>>> def do_something(y):
... return A(2) # hope it uses the `y` parameter...
...
>>> do_something(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in do_something
File "<stdin>", line 1, in <lambda>
NameError: global name 'y' is not defined
但正如你所見,它不起作用。 為什么? 因為當你定義一個函數時,python 會保存你定義它的范圍,並用它來解析global
/ nonlocal
變量。
如果您可以訪問some_func
則可以通過使用inspect
“破解”解釋器堆棧來做您想做的事情,但這不是一件健壯或優雅的事情,所以不要這樣做。
在你的情況下,我會做的是簡單地重寫語句。
如果你真的想避免這種情況,你可以嘗試使用exec
:
>>> def some_function(a,b,c):
... print(a,b,c)
...
>>> code = 'some_function(a+b,c,%s)'
>>>
>>> def func_one(a,b, c):
... exec code % 1
...
>>> def func_two(a,b,c):
... exec code % 2
...
>>> func_one(1,2,3)
(3, 3, 1)
>>> func_two(1,2,3)
(3, 3, 2)
但這是丑陋的。
如果你只對你的函數使用位置參數,你可以做一些更優雅的事情,比如:
>>> def compute_values(a,b,c):
... return (a+b, c)
...
>>> def func_one(a,b,c):
... some_function(*(compute_values(a,b,c) + (1,)))
...
>>> def func_two(a,b,c):
... some_function(*(compute_values(a,b,c) + (2,)))
...
>>> func_one(1,2,3)
(3, 3, 1)
>>> func_two(1,2,3)
(3, 3, 2)
但此時你只是在重復不同的文本,你失去了很多可讀性。 如果您想在 python 中具有預處理功能,您可以嘗試Python Preprocessing ,即使在您的情況下,我寧願只是重復函數調用。
你可以基於裝飾器:
import functools
from outer.space import some_func
def with_some(f):
@functools.wraps(f)
def wrapper(param1, param2, param3, *args):
new_args = f(*args)
return some_func(param1+param2, param3, *new_args)
return wrapper
@with_some
def callback_A():
return () # Will call some_func(param1 + param2, param3)
...
@with_some
def callback_B(param4):
return param4, # some_func(param1 + param2, param3, param4)
包裝的函數都將具有簽名f(param1, param2, param3, *args)
S_F = lambda a, b: some_func(param2+params1, param3, a, b)
請記住, param1
、 param2
和param3
必須在 lambda 語句的范圍內可用,就像some_func
。
如何在函數簽名中使用關鍵字參數而不是位置參數:
some_func(**kwargs):
Instead of position arguments, just use the keys that some_func can respond to.
You can defaults to the ones not included...
if key1 in kwargs:
#use key1...
#...
def callback_A(param1, param2, param3):
some_func(key1=param1+parma2,key2=param3, other_key=...)
def callback_B(param1, param2, param3, param4):
some_func(key1=param2+param1, key2=param3, other_keys=..., ...)
編輯
如果您無法將函數簽名更改為some_func
則可以將其包裝:
def some_func(a,b,c,d,e):
print 'some_funct({}, {}, {}, {}, {})'.format(a,b,c,d,e)
def some_func_wrap(**kwargs):
params={'p1':'default a','p2':'default b',
'p3':'default c','p4':'default d','p5':'default e'}
for p,arg in kwargs.items():
try:
del params[p] # to raise an error if bad key
params[p]=arg
except KeyError:
print 'bad param to some_func_wrap()\n'
raise
some_func(*[params[k] for k in sorted(params.keys())])
some_func_wrap(p1=1,p2=1+3)
打印: some_funct(1, 4, default c, default d, default e)
簡單地說,您可以使用globals()/locals()
來自動獲取上下文變量。
但是如果你的函數保存在不同的文件中,那么你可以嘗試inspect
模塊來訪問調用者的變量。
import inspect
def f1():
v=11111
f2()
def f2():
v = inspect.stack()[1][0].f_locals['v']
print(v)
f1() # print 11111
這是另一個類似的問題: Access variables of caller function in Python
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.