如何在python中对生成器类型进行排序

如何在python中对生成器类型进行排序,python,sorting,generator,Python,Sorting,Generator,我的代码有以下几行 get_alarm_list = conn.query_alarms(query.filter_expr, query.orderb) print "type is:", type(get_alarm_list) for alarm in get_alarm_list: if alarm.severity == 'critical': alarm.severity = 2

我的代码有以下几行

get_alarm_list = conn.query_alarms(query.filter_expr,
                                   query.orderb) 
print "type is:", type(get_alarm_list)
for alarm in get_alarm_list:
    if alarm.severity == 'critical':
        alarm.severity = 2
    elif alarm.severity == 'moderate':
        alarm.severity = 1
    else:
        alarm.severity = 0

alarm_list = sorted(get_alarm_list),
                    key=lambda a: a.severity,
                    reverse=True)
return [alarms.Alarm.from_db_model(alarm)
        for alarm in alarm_list]
输出:

type is <type 'generator'>
如何迭代生成器

alarm_list = sorted(get_alarm_list,
                    key=lambda a: a.severity,
                    reverse=True)

但是这里的报警列表是空的。如何在生成器上使用排序功能
get\u alarm\u list

代码中的问题是您正在尝试对耗尽的生成器进行排序(您在
之后对
循环思维生成器进行排序)。您可以对generator对象生成的结果进行排序,因此您可以选择将generator耗尽到变量中,换句话说,根据
get\u alarm\u list
作为
list(generator)
创建新列表,然后使用简单函数或
list对其进行迭代和排序。排序方法:

get_alarm_list = conn.query_alarms(query.filter_expr, query.orderb) 
sorted_alarm_list = sorted(list(get_alarm_list),
                               key=lambda a: a.severity,
                               reverse=True)
for alarm in sorted_alarm_list:
    print alarm
注1:执行
列表(获取报警列表)
-
获取报警列表后,生成器变为空。存储
conn.query\u报警结果的唯一项目是
sorted\u get\u alarm\u列表
。您可以在和上阅读有关发电机的更多信息


注2:实际上,您可以将生成器对象传递给
已排序的
,您将得到与传递
列表(生成器)
相同的列表,但是如果您将列表传递给它,则
已排序的
工作得更快(请参阅更多关于此答案的信息).

您遇到的问题是,当您修改对象的
严重性
属性时,您在
for
循环中消耗了整个生成器。这意味着当您调用排序后的
时,没有什么可以重复的了,因为生成器只适合一次使用

您可以通过去掉第一个循环,并将严重性转换逻辑放入
key
lambda函数来解决此问题:

alarms_gen = conn.query_alarms(query.filter_expr, query.orderb) 
alarms_list = sorted(alarms_gen,
                     key=lambda x: {'critical': -2, 'moderate': -1}.get(x.severity, 0))

请注意,我已经重命名了
get\u alarms\u list
变量,以减少误导(它不是一个列表)。通过将较高优先级映射到负键值,我还使排序调用中不需要
reverse=True

基本上,我在代码中尝试的是类似于get\u alarm\u list中报警的
:如果alarm.severity==2,则alarm\u list.append(报警)
。在修改对象的内容后,我在这里添加了一个列表
报警列表
。是否正确?我按照您的建议尝试了
list(获取报警列表)
。但它是空的<代码>打印列表(获取报警列表)
。输出为
[]
是,因为在第一次执行列表(获取报警列表)后,生成器为空。感谢您的详细解释。我使用了一个列表,在修改严重性后将报警对象附加到该列表中。然后我将这个列表传递给排序方法。你认为这样做可以吗?你的笔记得到了正确的答案,但我认为你真的应该改变你的第一句话。说你不能对生成器进行排序是完全错误的。
sorted
对生成器有效。它将返回一个排序列表。你能发布足够的代码来重现你的问题吗?@khelwood我已经编辑了我的问题,并根据你的建议发布了更多的代码。在第2版中,你可以使用
作为索引,枚举(获取报警列表)中的值
,并将
获取报警列表
更新为
获取报警列表[index]
,因此,您不需要创建分离列表……问题是,您首先迭代
get\u alarm\u list
,从而使用该生成器,下面对
sorted(get\u alarm\u list)
的调用将导致空列表,因为
get\u alarm\u list
没有更多元素。非常简洁,工作非常完美。这样可以保留对象的严重性值,而不会将其转换为整数+1与使用容易遗漏和混淆的
-2
-1
相比,为什么不使用
reverse=True
?@NicHartley:这可能有效。您还可以使用按需要排序的任何其他值,因此可以执行
{'critical':0,'mediate':1}.get(x.severity,2)
get_alarm_list = conn.query_alarms(query.filter_expr, query.orderb) 
sorted_alarm_list = sorted(list(get_alarm_list),
                               key=lambda a: a.severity,
                               reverse=True)
for alarm in sorted_alarm_list:
    print alarm
alarms_gen = conn.query_alarms(query.filter_expr, query.orderb) 
alarms_list = sorted(alarms_gen,
                     key=lambda x: {'critical': -2, 'moderate': -1}.get(x.severity, 0))