【发布时间】:2021-07-07 03:00:28
【问题描述】:
我一直在玩反转单链表,一切正常,但后来我决定添加一个装饰器来计时函数的执行。现在,当我尝试运行代码时,会出现这样的错误:
Traceback (most recent call last):
File "C:/Users/cherp2/AppData/Roaming/JetBrains/PyCharmCE2020.3/scratches/scratch_7.py", line 86, in <module>
main()
File "C:/Users/cherp2/AppData/Roaming/JetBrains/PyCharmCE2020.3/scratches/scratch_7.py", line 78, in main
print_ll(ll)
File "C:/Users/cherp2/AppData/Roaming/JetBrains/PyCharmCE2020.3/scratches/scratch_7.py", line 10, in wrapped
f(*args, **kwargs)
File "C:/Users/cherp2/AppData/Roaming/JetBrains/PyCharmCE2020.3/scratches/scratch_7.py", line 37, in print_ll
vals.append(str(node.val))
AttributeError: 'NoneType' object has no attribute 'val'
我的装饰器代码如下。我查了一下,和here的答案差不多:
def func_time(f):
def wrapped(*args, **kwargs):
t = dt.datetime.now()
f(*args, **kwargs)
print(f'{f.__name__} -- elapsed: {dt.datetime.now() - t}')
return wrapped
问题是否会因为我在大多数函数中使用递归而出现?这是链表节点定义和错误函数之一:
from dataclasses import dataclass, field
import datetime as dt
from typing import Optional
import random
@dataclass(order=True)
class Node:
val: int
next: 'Node' = field()
def make_ll(n, head: Optional[Node] = None, node: Optional[Node] = None):
if not head:
head = Node(random.randint(0, 20), None)
node = head
node.next = Node(random.randint(0, 20), None)
if n == 0:
return head
else:
return make_ll(n-1, head, node.next)
@func_time
def print_ll(node: Node, vals: Optional[list] = None):
if not vals:
vals = []
vals.append(str(node.val))
if node.next:
return print_ll(node.next, vals)
else:
vals.append('None')
print(' -> '.join(vals))
def main():
ll = make_ll(10, None)
print('Original list: ')
print_ll(ll)
if __name__ == '__main__':
main()
编辑: 看起来这绝对是递归的问题。我在非递归函数上测试了装饰器,它按预期工作:
@func_time
def add(l):
running_sum = 0
for a in l:
running_sum += a
return running_sum
>>> l = [i for i in range(10**6)]
>>> x = add(l)
Out: add -- elapsed: 0:00:00.052296
EDIT2: 测试问题中的代码:
def main():
# ll = make_ll(10, None)
ll = Node(1, None)
ll.next = Node(2, None)
ll.next.next = Node(3, None)
ll.next.next.next = Node(4, None)
ll.next.next.next.next = Node(5, None)
print('Original list: ')
print_ll(ll)
rev = reverse_ll(ll)
print('Reversed list: ')
print_ll(rev)
>>> main()
Out:
Original list:
1 -> 2 -> 3 -> 4 -> 5 -> None
Reversed list:
5 -> 4 -> 3 -> 2 -> 1 -> None
【问题讨论】:
-
我认为问题在于你的装饰器 isn't 写得正确(不是递归)。但是我无法测试该理论,因为您没有提供minimal reproducible example。请编辑您的问题并添加一个。
-
我已在问题中附加了代码以使其成为 MRE。我还在底部的 EDIT 部分添加了一个示例,说明装饰器可以很好地处理非递归函数。
-
您添加的代码不会产生问题中显示的
AttributeError- 尽管它没有做非递归所做的事情(也不是您想要的)。 -
您评论的第二部分非常神秘。你是什么意思:它不做非递归所做的(也不是你想要的)
-
哪部分不清楚?您问题中现在版本中的代码不会导致错误,但无法正常工作并且也无法执行您想要的操作。 (有一个不同的修复方法——装饰器问题不会影响它。)
标签: python recursion decorator