类型转换(同一类型的多个参数)
Type casting (multiple parameters of the same type)
我有以下方法声明:
def method(alpha, size=10, logged_in=False, interactions=False):
if not isinstance(logged_in, bool):
logged_in = str(logged_in).lower() in ['true']
if not isinstance(interactions, bool):
interactions = str(interactions).lower() in ['true']
if
语句是必需的,因为例如,如果我将 interaction="False"
作为参数传递,interactions
将被错误地设置为 True
(因此,我传递一个字符串)。虽然上面的技巧有效,但我想知道是否有更优雅的方法来实现它(请注意,除了 logged_in
和 interactions
之外,我还有很多布尔参数,而且我还有一些 int
和 float
参数。这里如何使用装饰器?可以将一个装饰器用于所有 bool
参数吗?我如何制作一个通用的装饰器(即支持 bool
, float
, int
, string
)? 我发现 问题的答案可能有用,但仍想检查是否有更好的方法。
你可以尝试这样的事情。
def bool_fixer(func):
table = {"true": True, "false": False}
def wrapper(*args, **kwargs):
for key, val in kwargs.items():
if isinstance(val, str) and val.lower() in table:
kwargs[key] = table[val.lower()]
return func(*args, **kwargs)
return wrapper
@bool_fixer
def method(...):
do something
在装饰器发挥它的魔力之后,所有字符串“true”和“false”都将变成它们的 python bool
等价物,您可以跳过 [=14 中的所有检查=]函数。
如果您希望它也包含 ints
和 floats
:
import re
def converter(func):
patterns = {r"\d*": int, r"\d*?\.\d*": float}
table = {"true": True, "false": False}
def wrapper(*args, **kwargs):
for key, val in kwargs.items():
if isinstance(val, str):
if val.lower() in table:
kwargs[key] = table[val.lower()]
continue
for pattern in patterns:
if re.match(pattern, val):
kwargs[key] = patterns[pattern](val)
return func(*args, **kwargs)
return wrapper
或
def converter(func):
table = {"true": True, "false": False}
def wrapper(*args, **kwargs):
for key, val in kwargs.items():
if isinstance(val, str):
if val.lower() in table:
kwargs[key] = table[val.lower()]
elif val.isdigit():
kwargs[key] = int(val)
elif re.match(r"\d*?\.\d*", val):
kwargs[key] = float(val)
return func(*args, **kwargs)
return wrapper
这个装饰器应该可靠地处理布尔值、整数和浮点数。如所写,这将修改 str 类型的关键字参数。它首先检查 str 是单词“[Tt]rue”还是“[Ff]alse”。下一个测试是检查 str 是否为整数(一个简单的转换测试有效)。首先检查int是因为格式比float更讲究,因为int只能是数字,而float可以包含小数点。最后,它尝试强制转换为浮动。如果所有这些转换都失败了,那么我们假设它是一个不应被篡改的实际 str。
def cast_arguments(method):
"""decorator"""
def wrapper(*args, **kwargs):
for key, value in kwargs.items():
# change special strings to bools
if isinstance(value, str):
if value.lower() == "true":
kwargs[key] = True
elif value.lower() == "false":
kwargs[key] = False
else:
try:
# change ints to int (int cannot have ".")
kwargs[key] = int(value)
except ValueError:
try:
# change floats to float (can have ".")
kwargs[key] = float(value)
except ValueError:
# this is an actual string
pass
return method(*args, **kwargs)
return wrapper
class Test:
@cast_arguments
def method(self, logged_in=False, interactions=False, other=False):
print("logged_in: ", logged_in, type(logged_in))
print("interactions: ", interactions, type(interactions))
print("other: ", other, type(other))
c = Test()
c.method(logged_in="1", interactions="True", other="3.14")
输出:
$ python test.py
logged_in: 1 <class 'int'>
interactions: True <class 'bool'>
other: 3.14 <class 'float'>
我有以下方法声明:
def method(alpha, size=10, logged_in=False, interactions=False):
if not isinstance(logged_in, bool):
logged_in = str(logged_in).lower() in ['true']
if not isinstance(interactions, bool):
interactions = str(interactions).lower() in ['true']
if
语句是必需的,因为例如,如果我将 interaction="False"
作为参数传递,interactions
将被错误地设置为 True
(因此,我传递一个字符串)。虽然上面的技巧有效,但我想知道是否有更优雅的方法来实现它(请注意,除了 logged_in
和 interactions
之外,我还有很多布尔参数,而且我还有一些 int
和 float
参数。这里如何使用装饰器?可以将一个装饰器用于所有 bool
参数吗?我如何制作一个通用的装饰器(即支持 bool
, float
, int
, string
)? 我发现
你可以尝试这样的事情。
def bool_fixer(func):
table = {"true": True, "false": False}
def wrapper(*args, **kwargs):
for key, val in kwargs.items():
if isinstance(val, str) and val.lower() in table:
kwargs[key] = table[val.lower()]
return func(*args, **kwargs)
return wrapper
@bool_fixer
def method(...):
do something
在装饰器发挥它的魔力之后,所有字符串“true”和“false”都将变成它们的 python bool
等价物,您可以跳过 [=14 中的所有检查=]函数。
如果您希望它也包含 ints
和 floats
:
import re
def converter(func):
patterns = {r"\d*": int, r"\d*?\.\d*": float}
table = {"true": True, "false": False}
def wrapper(*args, **kwargs):
for key, val in kwargs.items():
if isinstance(val, str):
if val.lower() in table:
kwargs[key] = table[val.lower()]
continue
for pattern in patterns:
if re.match(pattern, val):
kwargs[key] = patterns[pattern](val)
return func(*args, **kwargs)
return wrapper
或
def converter(func):
table = {"true": True, "false": False}
def wrapper(*args, **kwargs):
for key, val in kwargs.items():
if isinstance(val, str):
if val.lower() in table:
kwargs[key] = table[val.lower()]
elif val.isdigit():
kwargs[key] = int(val)
elif re.match(r"\d*?\.\d*", val):
kwargs[key] = float(val)
return func(*args, **kwargs)
return wrapper
这个装饰器应该可靠地处理布尔值、整数和浮点数。如所写,这将修改 str 类型的关键字参数。它首先检查 str 是单词“[Tt]rue”还是“[Ff]alse”。下一个测试是检查 str 是否为整数(一个简单的转换测试有效)。首先检查int是因为格式比float更讲究,因为int只能是数字,而float可以包含小数点。最后,它尝试强制转换为浮动。如果所有这些转换都失败了,那么我们假设它是一个不应被篡改的实际 str。
def cast_arguments(method):
"""decorator"""
def wrapper(*args, **kwargs):
for key, value in kwargs.items():
# change special strings to bools
if isinstance(value, str):
if value.lower() == "true":
kwargs[key] = True
elif value.lower() == "false":
kwargs[key] = False
else:
try:
# change ints to int (int cannot have ".")
kwargs[key] = int(value)
except ValueError:
try:
# change floats to float (can have ".")
kwargs[key] = float(value)
except ValueError:
# this is an actual string
pass
return method(*args, **kwargs)
return wrapper
class Test:
@cast_arguments
def method(self, logged_in=False, interactions=False, other=False):
print("logged_in: ", logged_in, type(logged_in))
print("interactions: ", interactions, type(interactions))
print("other: ", other, type(other))
c = Test()
c.method(logged_in="1", interactions="True", other="3.14")
输出:
$ python test.py
logged_in: 1 <class 'int'>
interactions: True <class 'bool'>
other: 3.14 <class 'float'>