使用元组的两个类,拆包和打包。 为什么这两个类的性能如此不同 - 2000 倍。这条线这么贵吗?
*self.stack, outitem = self.stack
from time import time
class StackT:
def __init__(self):
self.stack = tuple()
def push(self, otheritem):
self.stack = (*self.stack, otheritem)
def pop(self):
*self.stack, outitem = self.stack
return outitem
class Stack:
def __init__(self):
self._items = None
self._size = 0
def push(self, item):
self._items = (item, self._items)
def pop(self):
(item, self._items) = self._items
return item
def timer(func):
def wrapper(*args, **kwargs):
print("starting count.")
now = time()
result = func(*args, **kwargs)
print(f"counted {time() - now} seconds")
return result
return wrapper
@timer
def f(cls, times):
print(f"class {cls.__name__}, {times} times")
stack = cls()
for i in range(times):
stack.push(i)
for i in range(times):
stack.pop()
f(StackT, 100_000)
f(Stack, 100_000)
# starting count.
# class StackT, 100000 times
# counted 63.61870002746582 seconds
# starting count.
# class Stack, 100000 times
# counted 0.02500009536743164 seconds
您的
Stacks
具有不同类型的属性。我的意思是:
StackT.stack
是 items
Stack.items
是元组的元组你的直觉和@zvone 的评论是正确的。
push/pop
的 StackT
函数更昂贵,因为您使用 * operator
来取消列出 tuple
StackT.stack
的元素,成本高昂,因为它具有与元组循环相同的复杂性。
StackT
更加灵活且易于操作,因为每个元素都在一个元组中,访问元素相当于拥有其索引/顺序,但在实现时计算量很大。
Stack
更优化,但具有更复杂的属性来操作,因为仅拥有其索引是不够的。您需要使用一些循环机制。