是否有一种pythonic /有效的方法对任意类的对象列表中的每个元素(或更准确地说是元素的子集)执行简单的递减操作?
我可能有一个大型(~10K)对象列表,每个对象都会根据倒计时“更新时间”(TTU)值定期更新。
处理此问题的简单方法是在每个元素中减少此值,如下所示:
def BatesNumber(start = 0):
n = start
while True:
yield n
n += 1
class foo:
index = BatesNumber()
def __init__(self, ttu):
self.id = next(foo.index)
self.time = ttu
self.ttu = ttu
def __repr__(self):
return "#{}:{}/{}".format(self.id, self.ttu, self.time)
def Decrement(self):
self.ttu -= 1
def Reset(self):
print("Reset {} to {}".format(self.id, self.time))
self.ttu = self.time
def IsReadyForUpdate(self):
if self.ttu == 0:
return True
else:
return False
bar = [foo(i) for i in range(10, 20, 2)]
for n in range(50):
for p in bar:
if p.IsReadyForUpdate():
print("{} {}".format(n, p))
p.Reset()
else:
p.Decrement()
所以我猜我所追求的是一种“向量化”递减操作的Pythonic方式 - 即以适当优雅的方式递减列表中的所有元素;理想情况下,返回那些需要更新/重置的元素。
我可以(尽管看起来有点不必要)生成一个按TTU值排序的列表,并且具有相对于其邻居的所有TTU值。这样我每个周期只需要减少一次,但是当我重置计数器时,我很难重建列表。我想这对于一个具有相当高的TTU值的很长的列表会更好。
我假设使用列表理解来检查哪些元素已准备好进行更新的最佳/ Pythonic方法。
有什么建议吗?
答案 0 :(得分:1)
也许您可以使用heapq
模块将优先级队列替换为平面列表。优先级将是当前时间,加上对象ttu
。当前时间与最高元素的优先级匹配时,您可以将其弹出,执行更新,然后以新的优先级将其推回队列。
代码看起来像这样:
import heapq
items = [foo(i) for i in range(10,20)]
queue = [(f.ttu, f.id, f) for f in items]
heapq.heapify(queue)
for t in range(50):
while t >= queue[0][0]:
_, _, f = heapq.heappop(queue)
# update f here
heapq.heappush(queue, (t + f.ttu, f.id, f))
当需要同时更新两个对象时,我使用对象的id
属性作为平局判断器。如果您愿意,可以通过在对象中实现__lt__
运算符来简化优先级队列的实现,以允许直接比较它们。如果你让它们跟踪自己的更新时间,那么队列可以直接包含对象(比如items
列表)而不是元组,以使它们按优先级排序。
类似的东西:
class foo:
index = BatesNumber()
def __init__(self, ttu):
self.id = next(index)
self.next_update = ttu
self.ttu = ttu
def __lt__(self, other):
return (self.next_update, self.id) < (other.next_update, other.id)
# ideally you'd also write __eq__, __gt__, etc. methods, but heapq only needs __lt__
def update(self):
self.next_update += self.ttu
# maybe do other update stuff here?
顺便说一下,您的BatesNumber
课程基本上与itertools.count
相同。
答案 1 :(得分:0)
我认为你的代码已经很好了;也许你可以添加一个名为&#34; beat&#34;执行这两件事:
它会使你的循环更清洁,更简单。它对#34;矢量化&#34;它不会有多大帮助。你问题的一部分,但它会更深入地面向对象&#34;编程方式。
对于&#34;矢量化&#34;部分;你的清单会在整个过程中发生很大变化吗?一个想法可能是:有一个单独的Numpy数组,其中包含要递减的值,并使表与索引的列表匹配。当然,如果你必须在计算过程中抑制实例,那将是不太方便的,但如果不是这样,那么可能就是这样。