2016-06-10 98 views
1
發電機類型

我的代碼有以下行如何排序在Python

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'> 

在列表中的對象是:

for alarm in get_alarm_list: 
    print alarm 

Output: 
<aodh.storage.models.Alarm object at 0x7fa4c0cb1c50> 
<aodh.storage.models.Alarm object at 0x7fa4c0cb17d0> 
<aodh.storage.models.Alarm object at 0x7fa4c0d86f10> 
<aodh.storage.models.Alarm object at 0x7fa4ca372110> 
<aodh.storage.models.Alarm object at 0x7fa4ca372190> 
<aodh.storage.models.Alarm object at 0x7fa4c0c55d90> 

而且每個警報由以下數據

{'alarm_actions': [u'log://'], 'ok_actions': [], 'description': u'instance running hot', 'state': u'insufficient data', 'fields': ['alarm_actions', 'ok_actions', 'severity', 'timestamp', 'description', 'time_constraints', 'enabled', 'state_timestamp', 'rule', 'alarm_id', 'state', 'insufficient_data_actions', 'repeat_actions', 'user_id', 'project_id', 'type', 'name'], 'repeat_actions': False, 'enabled': True, 'state_timestamp': datetime.datetime(2016, 5, 27, 6, 41, 5, 987428), 'rule': {u'meter_name': u'cpu_util', u'evaluation_periods': 3, u'period': 600, u'statistic': u'avg', u'threshold': 70.0, u'query': [], u'comparison_operator': u'gt', u'exclude_outliers': False}, 'name': u'ddd', 'alarm_id': u'f5045ed5-5c53-4a6e-be53-23d3368f40c6', 'time_constraints': [], 'insufficient_data_actions': [], 'timestamp': datetime.datetime(2016, 5, 27, 6, 41, 5, 987428), 'user_id': u'9a65b258b5a24e74ac5feae2f6c54229', 'project_id': u'28d1c27e782c4448bf53da00f49d3e1b', 'type': u'threshold', 'severity': 2} 

如何迭代發生器?

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

但是這裏的alarm_list是空的。我如何使用發生器的排序功能get_alarm_list

+0

'sorted'在發電機上工作。它會返回一個排序列表。你能發佈足夠的代碼來重現你的問題嗎? – khelwood

+0

@khelwood我編輯了我的問題,併發布了更多代碼作爲您的建議。 – NSP

+0

在版本2中,您可以使用'for index,枚舉值(get_alarm_list)'並將'get_alarm_list'更新爲'get_alarm_list [index]',因此您不需要創建分列表... –

回答

3

您的代碼中的問題是,您正在嘗試排序耗盡的發生器(在for循環思想發生器之後排序)。您可以按發電機對象生成的結果,這樣對你的選擇是排發電機進換句話說可變基於get_alarm_listlist(generator)創造新的名單,然後進行迭代,並用簡單的sorted功能或list.sort方法對其進行排序:

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:執行list(get_alarm_list) - get_alarm_list發生器變空。而唯一存放conn.query_alarms結果的項目是sorted_get_alarm_list。你可以閱讀更多關於發電機上​​和Understanding Generators in Python

注2:其實你可以通過發電機對象sorted,你會得到相同的列表,通過list(generator),但是sorted工作更快,如果你傳遞一個列表(見更多關於SO的回答sorted() using Generator Expressions Rather Than Lists)。

+0

基本上我在代碼中試過的東西就像''在get_alarm_list中報警:如果alarm.severity == 2,alarm_list.append(alarm)'。這裏我修改了ob對象後附加了一個名爲'alarm_list'的列表。這是對的嗎? – NSP

+0

我嘗試了'list(get_alarm_list)'按照你的建議。但它是空的。 '打印清單(get_alarm_list)'。輸出是'[]' – NSP

+0

是的,因爲在第一次執行列表(get_alarm_list)後發生器是空的。 –

0

您遇到的問題是當您修改對象的severity屬性時,您正在使用for循環中的整個生成器。這意味着當您撥打sorted時,沒有什麼可重複使用的,因爲發電機僅適用於一種用途。

您可以擺脫第一循環的解決這個問題,並且把嚴重性,邏輯轉化成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_alarms_list變量要少誤導(這不是一個列表)。我也做到了這樣,reverse=True是不需要在排序的調用通過映射更高的優先級爲負值鍵值。

+0

非常簡潔,完美的作品。通過這種方式,對象的嚴重性值將保留並不會轉換爲整數。 +1 – 2016-06-12 01:22:40