一种自动将参数传递给函数的方法?

时间:2012-11-14 13:48:41

标签: python parameter-passing

我在模块中有一堆回调函数。他们都称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做什么?

5 个答案:

答案 0 :(得分:3)

您可以使用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)

编辑:

由于您没有提前获得这些值,因此无法使用partiallambda。 你可能想要这样做:

>>> 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“解密”解释器堆栈来执行您想要的操作,但这不是一个强大而优雅的事情,所以< em>不那样做。

我要做的就是简单地重写声明。

如果您真的想避免这种情况,可以尝试使用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,即使在你的情况下,我宁愿只重复函数调用。

答案 1 :(得分:3)

你可以将它建立在装饰者身上:

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)

答案 2 :(得分:0)

S_F = lambda a, b: some_func(param2+params1, param3, a, b)

请注意,param1param2param3必须在lambda语句的范围内可用,就像some_func一样。

答案 3 :(得分:0)

如何使用keyword arguments而不是函数签名中的位置参数:

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)

答案 4 :(得分:0)

很简单,您可以使用 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