我尝试学习python装饰器,因为这些东西非常有用。我了解简单的装饰器是如何工作的,但我试图围绕需要 *args 的功能制作装饰器并且它不起作用。当然,我缺少一些元素。我一直在浏览互联网寻找答案,但我找不到。
内部函数添加列表中的所有整数,包装器应检查列表中的所有元素是否都是整数。
def wrapper(func):
def inner(*args):
for i in range(0, len(args[0])): #It does not iven get there.
if not isinstance(i, int):
return 'Invaild values.'
else:
return func(*args)
return inner
def add(*args):
result = 0
for i in range(0, len(args[0])):
result += args[0][i]
return result
def main():
numbers = [1, '2', 3, 4]
print(add(numbers))
numbers = [1, 2, 3, 4]
print(add(numbers))
if __name__ == '__main__':
main()
我得到的错误。
Traceback (most recent call last):
File "wrapper_of_function.py", line 23, in <module>
main()
File "wrapper_of_function.py", line 20, in main
print(add(numbers))
File "wrapper_of_function.py", line 15, in add
result += args[0][i]
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
你测试i
是否是int的实例,当你应该测试args[0][i]
是否是int
的实例时:
def wrapper(func):
def inner(*args):
for i in range(len(args[0])): #It does not iven get there.
if not isinstance(args[0][i], int):
return 'Invalid values.'
return func(*args)
return inner
@wrapper
def add(*args):
result = 0
for i in range(0, len(args[0])):
result += args[0][i]
return result
def main():
numbers = [1, '2', 3, 4]
print(add(numbers))
numbers = [1, 2, 3, 4]
print(add(numbers))
if __name__ == '__main__':
main()
也许你打算实际使用你的装饰器
def wrapper(func):
def inner(*args):
for i in args[0]:
if not isinstance(i, int):
raise Exception('a non integer was encountered')
else:
return func(*args)
return inner
@wrapper
def add(*args):
total = 0
for i in args[0]:
total += i
return total
def main():
numbers = [1, '2', 3, 4]
try:
print(add(numbers))
except Exception as e:
print 'invalid input %r - %s' % (numbers, e)
numbers = [1, 2, 3, 4]
print(add(numbers))
if __name__ == '__main__':
main()
请注意,此实现的一个弱点是wrapped
必须了解传递给它的内容才能正常工作。它需要知道检查第 0 个元素。对于其他目的,这将不是一个非常有用的功能。即使您使用的是*args
,您仍然只将一个参数传递给add
。您可能会发现,如果您确实将多个参数传递给它装饰的任何内容,wrapped
通常更有用。
为此
def wrapper(func):
def inner(*args):
for i in args:
if not isinstance(i, int):
raise Exception('a non integer was encountered')
else:
return func(*args)
return inner
@wrapper
def add(*args):
total = 0
for i in args:
total += i
return total
def main():
numbers = [1, '2', 3, 4]
try:
print(add(*numbers))
except Exception as e:
print 'invalid input %r - %s' % (numbers, e)
numbers = [1, 2, 3, 4]
print(add(*numbers))
if __name__ == '__main__':
main()
引发的类型错误是因为您无法像 [1,'2',3,4] 那样添加 Int 和 Str。您的装饰器应该在系统抛出错误之前执行检查,但您并没有真正使用它。
此外,那里还有一些错误。
def wrapper(func):
def inner(*args):
# 1, you don't use args other than args[0], what's the point of using list arguments?
for i in range(0, len(args[0])): #It does not iven get there.
# 2, you are running isinstance on array indexes, you should run this on values.
if not isinstance(i, int):
# 3, it's a bad practice to return different types in different scenarios. Return a special value and print the error message, or just raise a exception
return 'Invaild values.'
# 4, else keyword is redundant. the if statement is inside the loop.
else:
return func(*args)
return inner
# 5, you didn't use wrapper at the first place.
def add(*args):
result = 0
# 6, only using the first argument rather than the list
for i in range(0, len(args[0])):
result += args[0][i]
return result
我为您重写了这段代码,希望它能满足您的需要。
def wrapper(func):
def inner(*args):
for arg in args:
if not isinstance(arg, int):
raise TypeError('Invalid values')
return func(*args)
return inner
@wrapper
def add(*args):
result = 0
for arg in args:
result += arg
return result
检查它是否有效
add
函数上使用@wrapper
:
def wrapper(func):
def inner(args):
for item in args:
if not isinstance(item, int):
return 'Invalid value found'
return func(args)
return inner
@wrapper
def add(args):
return sum(args)
def main():
numbers = [1, '2', 3, 4]
print(add(numbers))
numbers = [1, 2, 3, 4]
print(add(numbers))
if __name__ == '__main__':
main()
@Zetys : 在数字 = [1, '2', 3, 4] 中,第二个元素是一个字符串因此,它不能添加到result
,因为它是一个int
(结果 = 0)。如果您希望string
参数转换为int
以防它们是数字,则应使用 int(str)
函数。所以你的代码将是:
def add(*args):
result = 0
for i in range(0, len(args[0])):
result += int(args[0][i])
return result
顺便说一句,您没有在代码中的任何位置使用wrapper
类,因此它不会运行:)