Python 如何限制可传递给方法参数的允许值(使用类型提示允许静态代码分析)

Python 如何限制可传递给方法参数的允许值(使用类型提示允许静态代码分析),python,enums,enumeration,type-hinting,Python,Enums,Enumeration,Type Hinting,在Python 3中,我想限制传递给此方法的允许值: my_request(protocol_type, url) 使用类型提示,我可以写: my_request(protocol_type: str, url: str) 因此,协议和url仅限于字符串,但如何验证协议类型只接受有限的值集,例如'http'和'https'?我想您可以使用装饰器,我有类似的情况,但我想验证参数类型: def accepts(*types): """ Enforce parameter type

在Python 3中,我想限制传递给此方法的允许值:

my_request(protocol_type, url)
使用类型提示,我可以写:

my_request(protocol_type: str, url: str)

因此,协议和url仅限于字符串,但如何验证
协议类型
只接受有限的值集,例如
'http'
'https'

我想您可以使用装饰器,我有类似的情况,但我想验证参数类型:

def accepts(*types):
    """
    Enforce parameter types for function
    Modified from https://stackoverflow.com/questions/15299878/how-to-use-python-decorators-to-check-function-arguments
    :param types: int, (int,float), if False, None or [] will be skipped
    """
    def check_accepts(f):
        def new_f(*args, **kwds):
            for (a, t) in zip(args, types):
                if t:
                    assert isinstance(a, t), \
                           "arg %r does not match %s" % (a, t)
            return f(*args, **kwds)
        new_f.func_name = f.__name__
        return new_f
    return check_accepts
然后用作:

@accepts(Decimal)
def calculate_price(monthly_item_price):
    ...

您可以修改我的装饰器以实现所需的功能。

如果协议类型不在允许值列表中,请使用if语句引发异常:

allowed_protocols = ['http', 'https']
if protocol_type not in allowed_protocols:
    raise ValueError()

您只需检查函数中的输入是否正确:

def my_request(protocol_type: str, url: str):
    if protocol_type in ('http', 'https'):
        # Do x
    else:
        return 'Invalid Input'  # or raise an error

一种方法是在方法中编写代码,以验证传入的值是否为“http”或“https”,如下所示:

if (protocol_type == 'http') or (protocol_type == 'https'):
  Do Something
else:
  Throw an exception
这将在运行时正常工作,但在编写代码时不会提供问题指示

这就是为什么我更喜欢使用Enum和Pycharm和mypy实现的类型暗示机制

对于下面的代码示例,您将从Pycharm的代码检查中得到一条警告,请参见所附的屏幕截图。 屏幕截图显示,如果输入的值不是enum,则会出现“预期类型:…”警告

代码:

输出:

<enum 'ProtocolEnum'>
http
HTTP

http
超文本传输协议

此答案仅在运行时提醒问题,该问题用于静态分析。此答案是否回答了您的问题?
<enum 'ProtocolEnum'>
http
HTTP