检查参数是通过位置传递还是通过关键字

时间:2019-06-05 21:11:38

标签: python python-3.x

考虑带有签名f(a, b)的函数。将来,我想将签名更改为f(a, *, b),不允许b作为位置参数传递。 为了减少更改的影响,我想首先弃用位置b,警告用户这样做。

为此,我想写一些类似的东西:

def f(a, b):
    frame = inspect.currentframe()
    if b in frame.specified_as_positional:
        print('Do not do that')
    else:
        print('Good')

结果将是

>>> f(1, 2)
'Do not do that'
>>> f(1, b=2)
'Good'

inspect.getargvalues(frame)似乎还不够。 ArgInfo对象仅提供

>>> f(1,b=2)
ArgInfo(args=['a', 'b'], varargs=None, keywords=None, locals={'a': 1, 'b': 2})

这样的检查甚至可以在Python中进行吗?从概念上讲,似乎不需要记住解释器是在位置上指定还是作为关键字指定参数。

Python 2支持会很不错,但并非严格要求。

2 个答案:

答案 0 :(得分:4)

您可以使用包装器在用户和函数之间添加额外的步骤。在这一步中,您可以在名称很重要之前检查参数。请注意,这取决于<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> <style> .nav-tabs .nav-link { color: gray; border: 0; border-bottom: 1px solid grey; } .nav-tabs .nav-link:hover { border: 0; border-bottom: 1px solid grey; } .nav-tabs .nav-link.active { color: #000000; border: 0; border-radius: 0; border-bottom: 2px solid blue; } </style> <ul class="nav nav-tabs" id="myTab" role="tablist"> <li class="nav-item"> <a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true">SavedAssets</a> </li> <li class="nav-item"> <a class="nav-link" id="profile-tab" data-toggle="tab" href="#submitted" role="tab" aria-controls="profile" aria-selected="false">SubmittedAssets</a> </li> </ul> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>没有默认值,并且必须始终以arg给出的事实。

b用于使修饰后的功能在很多方面类似于原始功能。

functools.wraps
import functools
import warnings

def deprecate_positional(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        if 'b' not in kwargs:
            warnings.warn(
                'b will soon be keyword-only',
                DeprecationWarning,
                stacklevel=2
                )
        return fun(*args, **kwargs)
    return wrapper

@deprecate_positional
def f(a, b):
    return a + b

答案 1 :(得分:2)

这是一个非常棘手的解决方案:

def f(a, c=None, b=None):
    if (b == None):
        print("do not do that")
    else:
        print("good")

其中输入: f(1, b=2)打印good,而f(1, 2)打印do not do that