Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 方法链接时保留参数默认值_Python - Fatal编程技术网

Python 方法链接时保留参数默认值

Python 方法链接时保留参数默认值,python,Python,如果我必须包装一个现有的方法,比如说包装器()来自一个新方法,并且包装器()为一些参数提供了默认值,那么如何在不引入不必要的依赖关系和维护的情况下保留其语义呢?比方说,目标是能够使用wrapper()代替wrapee(),而无需更改客户端代码。例如,如果wrapee()定义为: def wrapee(param1, param2="Some Value"): # Do something 然后,定义wrapper()的一种方法是: 但是,wrapper()必须对param2的默认值进行假设

如果我必须包装一个现有的方法,比如说包装器()来自一个新方法,并且包装器()为一些参数提供了默认值,那么如何在不引入不必要的依赖关系和维护的情况下保留其语义呢?比方说,目标是能够使用wrapper()代替wrapee(),而无需更改客户端代码。例如,如果wrapee()定义为:

def wrapee(param1, param2="Some Value"):
  # Do something
然后,定义wrapper()的一种方法是:

但是,wrapper()必须对param2的默认值进行假设,这是我不喜欢的。如果我有wrapee()上的控件,我会这样定义它:

def wrapee(param1, param2=None):
  param2 = param2 or "Some Value"
  # Do something
def wrapper(param1, *args, **argv):
  # Do something
  wrapee(param1, *args, **argv)
  # Do something else.
然后,wrapper()将更改为:

def wrapper(param1, param2=None):
  # Do something
  wrapee(param1, param2)
  # Do something else.
如果我无法控制wrappe()的定义方式,那么如何最好地定义wrapper()?想到的一个选项是使用非None参数创建dict,并将其作为字典参数传递,但它似乎不必要地单调乏味

更新:

解决方案是同时使用列表和字典参数,如下所示:

def wrapee(param1, param2=None):
  param2 = param2 or "Some Value"
  # Do something
def wrapper(param1, *args, **argv):
  # Do something
  wrapee(param1, *args, **argv)
  # Do something else.
然后,以下所有调用均有效:

wrapper('test1')
wrapper('test1', 'test2')
wrapper('test1', param2='test2')
wrapper(param2='test2', param1='test1')
查看Python文档

>>> def wrapper(param1, *stuff, **kargs):
...  print(param1)
...  print(stuff)
...  print(args)
...
>>> wrapper(3, 4, 5, foo=2)
3
(4, 5)
{'foo': 2}
然后要传递参数,请执行以下操作:

wrapee(param1, *stuff, **kargs)
*stuff
是数量可变的非命名参数,
**kargs
是数量可变的命名参数。

这就是您想要的吗

def wrapper(param1, param2=None):
    if param2:
        wrapee(param1, param2)
    else:
        wrapee(param1)
#!/usr/bin/python

from functools import wraps
def my_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        print 'Calling decorated function'
        return f(*args, **kwds)
    return wrapper


def f1(x, y):
  print x, y

def f2(x, y="ok"):
  print x, y

my_decorator(f1)(1,2)
my_decorator(f2)(1,2)
my_decorator(f2)(1)

根据

改编,我很难说这并不乏味,但我能想到的唯一方法是反思正在包装的函数,以确定其任何参数是否具有默认值。您可以获取参数列表,然后确定哪个参数是第一个具有默认值的参数:

from inspect import getargspec

method_signature = getargspec(method)
param_names = method_signature[0]
default_values = method_signature[3]
params = []

# If any of method's parameters has default values, we need
# to know the index of the first one that does.
param_with_default_loc = -1
if default_values is not None and len(default_values) > 0:
    param_slice_index = len(default_values) * -1
    param_with_default = param_names[param_slice_index:][0]
    param_with_default_loc = param_names.index(param_with_default)
此时,您可以迭代参数名,复制到传递给wrappee的dict中。一旦您的索引>=param_with_default_loc,您就可以通过在default_values列表中查找索引-param_with_default_loc的索引来获得默认值

这有什么意义吗


当然,要使其通用,您需要将其定义为包装函数,添加另一层包装。

这不会使新方法完全兼容。虽然我可以说wrappe(param2=“value”,param1),但我不能对wrapper()做同样的操作。如果将wrapper()定义为
def wrapper(**args)
,则
args
将是提供的所有命名参数的字典。这对假定param2位置的调用方不起作用,例如wrappe(param1,param2)(它们被强制使用命名参数)。
wrappee(param2=“value”,param1)
甚至无效(在kwarg之后是非kwarg)。你能提供一个你所说的例子吗?事实上,这应该是可行的,我没有看到你同时使用*和**形式。我在第一条评论中也犯了一个错误,你必须传递第二个参数,也命名为,否则它会变成语法错误。虽然这对于这个特定的例子是可行的,但我正在寻找一个泛型解决方案(例如,如果有几个默认参数怎么办?)。非常有用的方法内省,谢谢分享。