将字符串转换为数字的装饰器
A decorator which converts string to number
我想使用装饰器将字符串格式的数字转换为 int/float 值,这是我正在尝试的方法
def str_to_int(func):
"""
This wrapper converts string value into integer
"""
def wrapper(*args, **kwargs):
for arg in args:
arg = int(arg)
return func(*args, **kwargs)
return wrapper
@str_to_int
def number_as_string(a, b, c):
return a,b,c
print (number_as_string('1', '2', '3'))
输出
('1', '2', '3')
不过,我想要下面这样的东西
(1, 2, 3)
我可以用下面的代码生成上面的输出
def str_to_int(func):
"""
This wrapper converts string value into integer
"""
def wrapper(x, y, z):
return int(x), int(y), int(z)
return wrapper
@str_to_int
def number_as_string(a, b, c):
return a,b,c
print (number_as_string('1', '2', '3'))
但是上面的代码首先违背了使用装饰器的目的,因为我想转换字符串值而不考虑原始函数的参数。
任何人都可以建议第一个程序有什么问题以及如何解决它。
它没有按预期工作的原因是因为您从未更新传入的 args
,您只是不断覆盖循环中的值。
考虑这个修订版:
>>> def str_to_int(f):
... def wrapper(*args, **kwargs):
... args = map(int, args)
... return f(*args, **kwargs)
... return wrapper
...
>>> @str_to_int
... def foo(a,b,c):
... return a,b,c
...
>>> foo('1','2','3')
(1, 2, 3)
关键是列表行:
args = map(int, args)
它确保原始 args 元组被完全替换,在您的循环中您默默地丢弃了该值。
对于Python3,你应该使用:
args = tuple(map(int, args))
因为地图将 return 一个地图对象。
当然我希望你意识到这个装饰器只有在你传递给它的东西不能实际转换为数字时才有效,如果你传递一个字符串那么它会引发一个 ValueError
:
>>> foo('hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in wrapper
ValueError: invalid literal for int() with base 10: 'hello'
如果你想防止这种情况发生,你必须忽略那些不能转换为整数的值:
def wrapper(*args, **kwargs):
_temp = []
for i in args:
try:
_temp.append(int(i))
except ValueError:
_temp.append(i)
args = tuple(_temp)
return f(*args, **kwargs)
现在它会简单地忽略它不能转换的东西:
>>> foo('hello', '1', '2')
('hello', 1, 2)
您可以稍微缩短您的代码,因为 *
会自动扩展参数,您可以利用它来发挥您的优势:
# args = tuple(_temp)
return f(*_temp, **kwargs)
我想使用装饰器将字符串格式的数字转换为 int/float 值,这是我正在尝试的方法
def str_to_int(func):
"""
This wrapper converts string value into integer
"""
def wrapper(*args, **kwargs):
for arg in args:
arg = int(arg)
return func(*args, **kwargs)
return wrapper
@str_to_int
def number_as_string(a, b, c):
return a,b,c
print (number_as_string('1', '2', '3'))
输出
('1', '2', '3')
不过,我想要下面这样的东西
(1, 2, 3)
我可以用下面的代码生成上面的输出
def str_to_int(func):
"""
This wrapper converts string value into integer
"""
def wrapper(x, y, z):
return int(x), int(y), int(z)
return wrapper
@str_to_int
def number_as_string(a, b, c):
return a,b,c
print (number_as_string('1', '2', '3'))
但是上面的代码首先违背了使用装饰器的目的,因为我想转换字符串值而不考虑原始函数的参数。
任何人都可以建议第一个程序有什么问题以及如何解决它。
它没有按预期工作的原因是因为您从未更新传入的 args
,您只是不断覆盖循环中的值。
考虑这个修订版:
>>> def str_to_int(f):
... def wrapper(*args, **kwargs):
... args = map(int, args)
... return f(*args, **kwargs)
... return wrapper
...
>>> @str_to_int
... def foo(a,b,c):
... return a,b,c
...
>>> foo('1','2','3')
(1, 2, 3)
关键是列表行:
args = map(int, args)
它确保原始 args 元组被完全替换,在您的循环中您默默地丢弃了该值。
对于Python3,你应该使用:
args = tuple(map(int, args))
因为地图将 return 一个地图对象。
当然我希望你意识到这个装饰器只有在你传递给它的东西不能实际转换为数字时才有效,如果你传递一个字符串那么它会引发一个 ValueError
:
>>> foo('hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in wrapper
ValueError: invalid literal for int() with base 10: 'hello'
如果你想防止这种情况发生,你必须忽略那些不能转换为整数的值:
def wrapper(*args, **kwargs):
_temp = []
for i in args:
try:
_temp.append(int(i))
except ValueError:
_temp.append(i)
args = tuple(_temp)
return f(*args, **kwargs)
现在它会简单地忽略它不能转换的东西:
>>> foo('hello', '1', '2')
('hello', 1, 2)
您可以稍微缩短您的代码,因为 *
会自动扩展参数,您可以利用它来发挥您的优势:
# args = tuple(_temp)
return f(*_temp, **kwargs)