我刚刚开始使用python进行编程,并且非常喜欢生成器的概念。
所以我有一个字典列表,每个字典都包含一个id和一个状态,例如前两个元素可能看起来像这样
lst =[{ "id":1, "status": "new"}, {"id": 2, "status"="finished"}]
实际列表最多可包含10个项目。每个id对应一个作业,通常作业完成的顺序是随机的。
我想检查作业是否完成,如果是,请处理它。如果没有完成,(由于随机性)我想检查另一个工作,直到所有工作完成(通常他们将在某个时间)
所以对我而言,这对发电机来说是一个很好的用途,特别是在管道中(尽管效率在这里可能并不重要)。
def gener(lst):
while lst:
for item in lst:
if item["status"] == "finished":
yield lst.pop(list.index(item))
else:
check_and_update_status(item)
检查和更新功能可能如下所示:
def check_and_update_status(item):
item["status"]=finished
所以我的第一个问题是:这是一种有意义的方法吗?或者这是一个不好的选择。
所以,希望我能在这里添加这两个问题:
有时在列表中可能会出现没有状态键的词典。在这种情况下,我想在else分支中执行任务。我怎样才能做到这一点?异常处理?
在一些关于python /编程的文献中,我了解到设置和程序应该被划分。所以我想知道我是否应该硬编码“完成”(也许还有“状态”)。术语“完成”源于外部文件,可能在将来的某个时候更改。是否有一种优雅的方法来解决这个问题?
答案 0 :(得分:1)
在迭代期间变异list
是不安全的,通常不受支持。即使它有效,但只有lst.pop(lst.index(item))
才能使用for i, item in enumerate(lst):
这样做是愚蠢的,因此您可以免费获得索引。您可以采取的一种方法是避免在迭代时删除,只需将索引存储为delete,并使用list comprehension在最后重新生成lst
。例如:
while lst:
todel = set()
for i, item in enumerate(lst):
if item["status"] == "finished":
todel.add(i)
yield item
else:
check_and_update_status(item)
if todel:
lst = [x for i, x in enumerate(lst) if i not in todel]
如果你有更大的列表和更频繁的从列表中删除,其他方法可能会更好地工作,但这种方法可以优化不频繁的删除,而无需在迭代副作用时注册危险的突变。
为了处理不存在的"status"
键,您可以使用item.get("status")
而不是索引语法来避免抛出异常(使用一个参数,get
返回None
如果key不存在,或者您可以传递第二个参数以用作默认值)。或者,要获取现有值(如果它存在),并设置并获取默认状态(如果它尚不存在),请使用item.setdefault("status", "new")
(其中"new"
应为您的默认起始状态)。
例如,要检查和设置,您可以使用:
if item.setdefault("status", "new") == "finished":
问题3在一般情况下难以回答;如果你有一个适当的数据模式,那么使用它而不是在魔术字符串中进行硬编码是一个好主意,但这取决于你的用例。