2014-10-14 37 views
29

Có cách nào thanh lịch hơn để viết mã này không?Thêm vào danh sách trong từ điển Python

Điều tôi đang làm: Tôi có khóa và ngày. Có thể có một số ngày được chỉ định cho một khóa và vì vậy tôi đang tạo một từ điển danh sách các ngày để biểu diễn điều này. Mã sau hoạt động tốt, nhưng tôi đã hy vọng cho một phương pháp thanh lịch và Pythonic hơn.

dates_dict = dict() 
for key, date in cur: 
    if key in dates_dict: 
     dates_dict[key].append(date) 
    else: 
     dates_dict[key] = [date] 

Tôi đã mong đợi những điều sau đây hoạt động, nhưng tôi tiếp tục nhận được NoneType không có lỗi thêm thuộc tính.

dates_dict = dict() 
for key, date in cur: 
    dates_dict[key] = dates_dict.get(key, []).append(date) 

này có lẽ có cái gì để làm với thực tế rằng

print([].append(1)) 
None 

nhưng tại sao?

+2

Bạn nên nhìn vào [ 'collections.defaultdict'] (https://docs.python.org/2/library/collections.html#collections.defaultdict) – CoryKramer

+0

bạn có thể thử sử dụng extend() thay vì append() – weefwefwqg3

Trả lời

48

list.append lợi nhuận None, vì nó là một hoạt động tại chỗ và bạn đang gán cho nó trở lại dates_dict[key]. Vì vậy, lần sau khi bạn thực hiện dates_dict.get(key, []).append, bạn đang thực sự đang thực hiện None.append. Đó là lý do tại sao nó thất bại. Thay vào đó, bạn có thể chỉ cần thực hiện

dates_dict.setdefault(key, []).append(date) 

Nhưng, chúng tôi chỉ có collections.defaultdict cho mục đích này. Bạn có thể làm điều gì đó như thế này

from collections import defaultdict 
dates_dict = defaultdict(list) 
for key, date in cur: 
    dates_dict[key].append(date) 

Điều này sẽ tạo một đối tượng danh sách mới nếu không tìm thấy key trong từ điển.

Lưu ý:defaultdict sẽ tạo danh sách mới nếu khóa không được tìm thấy trong từ điển, điều này sẽ có tác dụng phụ không chủ ý. Ví dụ, nếu bạn chỉ muốn lấy một giá trị cho khóa, mà không có ở đó, nó sẽ tạo một danh sách mới và trả về nó.

+1

@chepner: Lưu ý rằng '__missing __()' không được gọi cho bất kỳ thao tác nào ngoài '__getitem __()'. Điều này có nghĩa là 'get()' sẽ giống như các từ điển thông thường, trả về 'None' làm mặc định thay vì sử dụng' default_factory' tức là 'key trong date_dict' và' date_dict.get (key) 'hoạt động như mong đợi – jfs

+0

Giống như một theo sát.Tôi đã kết thúc bằng cách sử dụng setdefault như git tôi chính xác những gì tôi muốn mà không cần nhập thêm. Cảm ơn sự giúp đỡ –

+0

Giải thích của bạn về lý do tại sao '[] .append' trả về' None' không có ý nghĩa với tôi. Nếu bạn đang ấn định hoặc in nó ngay lập tức, tại sao nó lại là một hoạt động tại chỗ? Tại sao 'date_dict.get (key, []). Append' yield' None' trừ khi 'date_dict [key] == None'? – cfwschmidt

2

dates_dict[key] = dates_dict.get(key, []).append(date) đặt dates_dict[key] thành Nonelist.append trả về None.

In [5]: l = [1,2,3] 

In [6]: var = l.append(3) 

In [7]: print var 
None 

Bạn nên sử dụng collections.defaultdict

import collections 
dates_dict = collections.defaultdict(list) 
+0

Vâng, đó là những gì tôi nghĩ. Vì không có giá trị nào được trả về. Nó sẽ trả về None là mặc định. Cảm ơn –

+0

@MichaelMurphy, sử dụng defaultdict sẽ là cách hiệu quả nhất để làm những gì bạn muốn –

11

Có cách nào thanh lịch hơn để viết mã này không?

Sử dụng collections.defaultdict:

from collections import defaultdict 

dates_dict = defaultdict(list) 
for key, date in cur: 
    dates_dict[key].append(date) 
Các vấn đề liên quan