2012-05-18 32 views
0

假設我想創建映射位數號碼小於100在這些數字結尾如下字典修改字典時:錯誤在python

d = {} 
for i in range(100): 
r = i % 10 
if r in d: 
    d[r] = d[r].append(i) 
else: 
    d[r] = [i] 
print d 

首先,當i爲20,d [ r]顯然是一個NoneType,當我嘗試附加到它時,拋出一個錯誤。爲什麼會這樣?其次,我覺得我的方法效率低下,因爲檢查d中的r是否沒有傳播。這樣的事情會更好,我覺得:

case(d[r]) of 
    SOME(L) => d[r] = L.append(i) 
| NONE => d[r] = [i] 

有沒有辦法在Python中有這種邏輯?

+3

'd [r] = d [r] .append(i)'應該是'd [r] .append(i)'。 'list.append'修改列表,並且不返回新列表 –

回答

1

首先,當我20時,d [r]顯然是一個NoneType,當我嘗試附加到它時,拋出一個錯誤。爲什麼會這樣?

這是因爲下面的代碼是錯誤的:

d[r] = d[r].append(i) 

.append修改列表作爲一個副作用,並返回None。所以在列表被追加後,它會被丟棄,並被現在被重新分配到d[r]中的None值替換。

有沒有辦法讓Python中的邏輯?

可以使用各種各樣的黑客,但它們都不適合在這裏。

相反,解決具體問題:「修改字典值如果存在,否則創建一個新的值」。這可以細化爲「如果不存在,創建一個空的默認值,然後修改現在保證存在的值」。

你可以做,使用.setdefault,或更優雅,你可以替換字典有collections.defaultdict

from collections import defaultdict 

d = defaultdict(list) 
for i in range(100): 
    r = i % 10 
    d[r].append(i) 

或者你可以解決更具體的問題:「創建一個字典,一個給定的模式」從應用規則或公式的輸入序列(在這種情況下,即輸入是range(100)

from itertools import groupby 

def last_digit(i): return i % 10 
d = {k: list(v) for k, v in groupby(sorted(range(100), key=last_digit), last_digit)} 

或者你可以解決更具體的問題,採取的事實,即range另需參數來指定一個步長:

d = {i: range(i, 100, 10) for i in range(10)} 
+0

字典解析僅在Python 3中,是否正確? –

+3

Python 2.7及以上版本。 – Blender

0

與安德魯的建議,使用d[r].append(i),你得到想要的答案:

In [3]: d 
Out[3]: 
{0: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90], 
1: [1, 11, 21, 31, 41, 51, 61, 71, 81, 91], 
2: [2, 12, 22, 32, 42, 52, 62, 72, 82, 92], 
3: [3, 13, 23, 33, 43, 53, 63, 73, 83, 93], 
4: [4, 14, 24, 34, 44, 54, 64, 74, 84, 94], 
5: [5, 15, 25, 35, 45, 55, 65, 75, 85, 95], 
6: [6, 16, 26, 36, 46, 56, 66, 76, 86, 96], 
7: [7, 17, 27, 37, 47, 57, 67, 77, 87, 97], 
8: [8, 18, 28, 38, 48, 58, 68, 78, 88, 98], 
9: [9, 19, 29, 39, 49, 59, 69, 79, 89, 99]} 

你可以這樣做:

In [7]: for onesdigit in range(10): 
    ...:  d[onesdigit] = range(onesdigit, 100, 10)