5

モジュールにたくさんのコールバック関数があります。それらはすべて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で何ができますか?

4

5 に答える 5

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)

編集:

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前処理を試してみてください。ただし、あなたの場合は、関数呼び出しを繰り返すだけです。

于 2012-11-14T14:04:06.553 に答える
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)

于 2012-11-14T15:24:39.167 に答える
0
S_F = lambda a, b: some_func(param2+params1, param3, a, b)

param1、は、param2param3同様に、ラムダステートメントのスコープで使用可能である必要があることに注意してくださいsome_func

于 2012-11-14T13:52:12.010 に答える
0

関数シグニチャの位置引数の代わりにキーワード引数を使用するのはどうですか。

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)

于 2012-11-14T14:24:32.777 に答える
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

別の同様の質問があります: Pythonの呼び出し元関数の変数にアクセスします

于 2021-05-10T07:46:33.250 に答える