Python-将伪参数添加到函数签名

时间:2019-06-05 05:29:06

标签: python function

我有一个功能:

def dummy_func(a, b: float, c: int = 1) -> float:
    #some code

我想编写一个通用函子(dummy_prepender),该函子将使用该函数并构造一个新的函子,它与原始函子的唯一区别是在签名之前附加了一个未使用的参数:

dummy_method1 = dummy_prepender(dummy_func)

#dummy_method1 should behave exactly like the following code:

def dummy_method(dummy, a, b: float, c: int = 1) -> float:
    #some code

因此对于任何一组参数和dummy_arg

dummy_method(dummy_arg, arguments...)的行为与dummy_func(arguments...) 完全相同

我认为@staticmethod可以解决问题,但是在某些地方,调度的执行方式有所不同,并且应用静态方法无效。

一些行为测试:

help(dummy_method)应该显示正确的签名

dummy_method(dummy='', a=1)应该失败

dummy_method(dummy='', a=1, b=2, c=3, z=4)应该失败

更新

以下是staticmethod无法正常工作的示例:

示例1

factory_type = type('Typ1', (), {
    '__init__': staticmethod(dummy_func),
})

inspect.signature(factory_type)

#<Signature (b:float, c:int=1) -> float>
#BTW, in this case it's just the inspect.signature that is broken. The call behavior seems to be correct

示例2:

factory_type2 = type('Typ1', (), {
    '__new__': staticmethod(dummy_func),
})

#Call behavior is broken
factory_type2(a=1, b=2)
# TypeError: dummy_func() got multiple values for argument 'a'

factory_type2(7, 13)
# locals()={'c': 13, 'b': 7, 'a': <class '__main__.Typ1'>}
# See how the class got passed as `a` instead of `dummy`

staticmethod(func)的结果不是函数,而是描述符对象。有时行为是不一样的。

1 个答案:

答案 0 :(得分:0)

我的第一次尝试是这样的:

def dummy_method(*args, **kwargs) -> float:
    return dummy_func(*args[1:], **kwargs)

即将推出的Python 3.8实现了PEP 570,该语法允许以下语法:

# 'dummy' is a positional only argument, disallowing 'dummy=...'
def dummy_method(dummy, /, *args, **kwargs) -> float:
    return dummy_func(*args, **kwargs)

这里是Python 3.8的另一个版本,保留了签名:

def dummy_method(dummy, /, a, b: float, c: int = 1) -> float:
    return dummy_func(a, b, c)