如何限制可以传递给方法参数的允许值(使用类型提示允许静态代码分析)
How to limit the permitted values that can be passed to a method parameter (Using Type Hinting to allow Static Code Analysis)
在 Python 3 中,我想限制传递给此方法的允许值:
my_request(protocol_type, url)
使用类型提示我可以写:
my_request(protocol_type: str, url: str)
所以协议和 url 仅限于字符串,但我如何验证 protocol_type
只接受有限的一组值,例如'http'
和 'https'
?
我想你可以使用装饰器,我有类似的情况但我想验证参数类型:
def accepts(*types):
"""
Enforce parameter types for function
Modified from
: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):
...
你可以修改我的装饰器来实现你想要的。
如果 protocol_type 不在允许值列表中,则使用引发异常的 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 中从其代码检查中收到警告,请参阅随附的屏幕截图。
屏幕截图显示,如果您输入的值不是枚举,您将收到 "Expected Type:..." 警告。
代码:
"""Test of ENUM"""
from enum import Enum
class ProtocolEnum(Enum):
"""
ENUM to hold the allowed values for protocol
"""
HTTP: str = 'http'
HTTPS: str = 'https'
def try_protocol_enum(protocol: ProtocolEnum) -> None:
"""
Test of ProtocolEnum
:rtype: None
:param protocol: a ProtocolEnum value allows for HTTP or HTTPS only
:return:
"""
print(type(protocol))
print(protocol.value)
print(protocol.name)
try_protocol_enum(ProtocolEnum.HTTP)
try_protocol_enum('https')
输出:
<enum 'ProtocolEnum'>
http
HTTP
在 Python 3 中,我想限制传递给此方法的允许值:
my_request(protocol_type, url)
使用类型提示我可以写:
my_request(protocol_type: str, url: str)
所以协议和 url 仅限于字符串,但我如何验证 protocol_type
只接受有限的一组值,例如'http'
和 'https'
?
我想你可以使用装饰器,我有类似的情况但我想验证参数类型:
def accepts(*types):
"""
Enforce parameter types for function
Modified from
: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):
...
你可以修改我的装饰器来实现你想要的。
如果 protocol_type 不在允许值列表中,则使用引发异常的 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 中从其代码检查中收到警告,请参阅随附的屏幕截图。 屏幕截图显示,如果您输入的值不是枚举,您将收到 "Expected Type:..." 警告。
代码:
"""Test of ENUM"""
from enum import Enum
class ProtocolEnum(Enum):
"""
ENUM to hold the allowed values for protocol
"""
HTTP: str = 'http'
HTTPS: str = 'https'
def try_protocol_enum(protocol: ProtocolEnum) -> None:
"""
Test of ProtocolEnum
:rtype: None
:param protocol: a ProtocolEnum value allows for HTTP or HTTPS only
:return:
"""
print(type(protocol))
print(protocol.value)
print(protocol.name)
try_protocol_enum(ProtocolEnum.HTTP)
try_protocol_enum('https')
输出:
<enum 'ProtocolEnum'>
http
HTTP