[英]A way to automatically pass parameters to a function?
I have a bunch of callback functions in a module.我在一个模块中有一堆回调函数。 They all call
some_func()
with the first, say, couple of arguments always the same and derived from their own arguments, while other arguments vary.它们都调用
some_func()
,第一个参数总是相同的,并且来自它们自己的参数,而其他参数则不同。 Like so:像这样:
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, ..., ...)
...
And it's all over the code.这在代码中无处不在。 And uglier than just param2+param1.
而且比 param2+param1 更丑陋。
In C/C++, I'd just do a macro在 C/C++ 中,我只是做一个宏
#define S_F(a,b) some_func(param2+param1, param3, a, b)
and start using S_F inside callbacks instead of some_func
.并开始在回调中使用 S_F 而不是
some_func
。 What can I do in Python?我可以用 Python 做什么?
You can use functools.partial
您可以使用
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)
Edit:编辑:
Since you do not have these values in advance you can't use partial
or lambda
.由于您事先没有这些值,因此您不能使用
partial
或lambda
。 You may be tempted to do this:您可能会尝试这样做:
>>> 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
But as can you see it does not work.但正如你所见,它不起作用。 Why?
为什么? Because when you define a function python saves the scope in which you defined it and uses it to resolve the
global
/ nonlocal
variables.因为当你定义一个函数时,python 会保存你定义它的范围,并用它来解析
global
/ nonlocal
变量。
If you had access to some_func
it would be possible to do what you want by "hacking" the interpreter stack using inspect
but this is not a robust nor elegant thing to do, so do not do that.如果您可以访问
some_func
则可以通过使用inspect
“破解”解释器堆栈来做您想做的事情,但这不是一件健壮或优雅的事情,所以不要这样做。
What I'd do in your case is to simply rewrite the statement.在你的情况下,我会做的是简单地重写语句。
If you really want to avoid this, you can try something using exec
:如果你真的想避免这种情况,你可以尝试使用
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)
But this is ugly .但这是丑陋的。
If you use only positional arguments to your function you may do something more elegant such as:如果你只对你的函数使用位置参数,你可以做一些更优雅的事情,比如:
>>> 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)
But at this point you are just repeating a different text, and you lost much readability.但此时你只是在重复不同的文本,你失去了很多可读性。 If you want to have preprocessing features in python you may try Python Preprocessing , even though, in your case, I'd rather just repeat the function calls.
如果您想在 python 中具有预处理功能,您可以尝试Python Preprocessing ,即使在您的情况下,我宁愿只是重复函数调用。
You could base it on decorators:你可以基于装饰器:
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)
The wrapped functions will all have signature f(param1, param2, param3, *args)
包装的函数都将具有签名
f(param1, param2, param3, *args)
S_F = lambda a, b: some_func(param2+params1, param3, a, b)
请记住, param1
、 param2
和param3
必须在 lambda 语句的范围内可用,就像some_func
。
How about with keyword arguments instead of positional arguments in the function signature:如何在函数签名中使用关键字参数而不是位置参数:
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=..., ...)
Edit编辑
If you cannot change the function signature to some_func
then you can wrap it:如果您无法将函数签名更改为
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)
prints: some_funct(1, 4, default c, default d, default e)
打印:
some_funct(1, 4, default c, default d, default e)
Simplely you can just use globals()/locals()
to automatically get the context variables.简单地说,您可以使用
globals()/locals()
来自动获取上下文变量。
But if your functions saved in different files, then you can try inspect
module to access caller's variables.但是如果你的函数保存在不同的文件中,那么你可以尝试
inspect
模块来访问调用者的变量。
import inspect
def f1():
v=11111
f2()
def f2():
v = inspect.stack()[1][0].f_locals['v']
print(v)
f1() # print 11111
Here is another similar question: Access variables of caller function in Python这是另一个类似的问题: Access variables of caller function in Python
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.