函数参数继承其他函数的默认值

时间:2015-08-18 00:04:59

标签: python

让我们说在Python库中有一个函数(让我们称之为mymodule):

def some_func(a,b='myDefaultValue'):
    return some_computation

然后在另一个调用它的模块中有另一个函数,

import mymodule
def wrapper(a,b):
    return some_transform(mymodule.some_func(a,b))

如何使wrapper继承some_func参数的b默认值?我可以做类似的事情:

def wrapper(a,b=None):
    if b:
        return some_transform(some_func(a,b))
    else:
        return some_transform(some_func(a))

但这似乎是不必要的繁琐,导致多个可选参数的可能性的组合爆炸,并使我无法明确地将None传递给wrapper

有没有办法获取函数的默认args,或者通常的做法是简单地将该值拉出到两个函数声明都可以使用的共享常量中?

3 个答案:

答案 0 :(得分:2)

您可以使用 func_defaults https://docs.python.org/2/library/inspect.html?highlight=func_defaults#types-and-members

  

func_defaults参数的任何默认值的元组

def some_func(a,b='myDefaultValue'):
    print a, b

def wrapper(a,b):
    b = some_func.func_defaults[0] if b is None else b
    some_func(a,b)


print "b is 'there'"
a = "hello"
b = "there"
wrapper(a,b)

print "b is 'None'"
b = None
wrapper(a,b)

输出:

b is 'there'
hello there
b is 'None'
hello myDefaultValue

编辑:要从评论中回答您的问题,我们没有任何内置功能可以按名称查找默认值的函数参数。但是,您知道具有默认值的参数必须位于非可选参数之后。因此,如果您知道所拥有的参数总数以及它们中有多少具有默认值,则可以减去2以使用默认值获取参数的起始点。然后,您可以将参数列表(从先前计算的参数索引开始)与默认参数值列表一起压缩,并从列表中创建字典。使用inspect模块获取所需的所有信息:

像这样:

>>> import inspect
>>> def some_func(a,b,c,d="dee",e="ee"):
...     print a,b,c,d,e
... 
>>> some_func("aaa","bbb","ccc",e="EEE")
aaa bbb ccc dee EEE
>>> some_funcspec = inspect.getargspec(some_func)
>>> some_funcspec
ArgSpec(args=['a', 'b', 'c', 'd', 'e'], varargs=None, keywords=None, defaults=('dee', 'ee'))
>>> defargsstartindex = len(some_funcspec.args) - len(some_funcspec.defaults)
>>> defargsstartindex
3
>>> namedargsdict = dict(zip([key for key in some_funcspec.args[defargsstartindex:]], list(some_funcspec.defaults)))
>>> namedargsdict
{'e': 'ee', 'd': 'dee'}

在上面的示例中, namedargsdict 是包含some_func默认值的参数列表。

进一步阅读:

https://docs.python.org/2/library/inspect.html#inspect.getargspec

  

inspect.getargspec(func)获取Python的名称和默认值   函数的论点。返回四个元组的元组:( args,   varargs,关键字,默认值)。 args是参数名称的列表(它   可能包含嵌套列表)。 varargs和关键字是*的名称   和**参数或无。 defaults是默认参数的元组   如果没有默认参数,则为values或None;如果这个元组有n   元素,它们对应于args中列出的最后n个元素。

     

在2.6版中更改:返回一个命名元组ArgSpec(args,varargs,   关键字,默认值)。

答案 1 :(得分:1)

您可以使用argument unpacking来完成此操作:

In [1]: def some_func(a,b='myDefaultValue'):
   ...:     print a, b
   ...:

In [2]: def wrapper(a, *args, **kwargs):
   ...:     some_func(a, *args, **kwargs)
   ...:

In [3]: some_func('foo', 'bar')
foo bar

In [4]: some_func('baz')
baz myDefaultValue

In [5]: wrapper('foo', 'bar')
foo bar

In [6]: wrapper('baz')
baz myDefaultValue

如果您打算以这种方式包装多个功能,可以考虑将wrapper设为decorator

In [1]: from functools import wraps

In [2]: def wrapper(func):
   ...:     @wraps(func)
   ...:     def decorated(a, *args, **kwargs):
   ...:         print 'wrapper invoked with a = {}'.format(a)
   ...:         return func(a, *args, **kwargs)
   ...:     return decorated
   ...:

In [3]: @wrapper
   ...: def some_func(a, b='myDefaultValue'):
   ...:     print a, b
   ...:

In [4]: some_func('foo', 'bar')
wrapper invoked with a = foo
foo bar

In [5]: some_func('baz')
wrapper invoked with a = baz
baz myDefaultValue

答案 2 :(得分:0)

你的问题不够明确。但据我理解你的问题,你应该使用class,这样你就可以轻松地在班级内的多个职能中分享价值

class SomeClass:

  def __init__(self, b='defaultvalue'):
    self.b = b

  def some_func(self, a, b):
    pass

  def wrapper(self, a):
    self.some_func(a, self.b)