我尝试学习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'
答案 0 :(得分:3)
也许你打算真正使用你的装饰
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 :(得分:3)
您测试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()
答案 2 :(得分:2)
你应该在@wrapper
函数上使用add
:
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()
答案 3 :(得分:1)
抛出的类型错误是因为你不能像[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
检查它是否有效
答案 4 :(得分:0)
@Zetys:在数字= [1,&#39; 2&#39;,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
类,所以它不会运行:)