2009-05-11 44 views
7

Giả sử tôi đã có hai dicts bằng Python:Có cách nào để đặt nhiều mặc định trên một dict Python sử dụng một dict?

mydict = { 'a': 0 } 

defaults = { 
    'a': 5, 
    'b': 10, 
    'c': 15 
} 

Tôi muốn để có thể mở rộng mydict sử dụng các giá trị mặc định từ defaults, sao cho 'a' vẫn giữ nguyên nhưng 'b' và 'c' được điền vào. Tôi biết về dict.setdefault()dict.update(), nhưng mỗi chỉ làm một nửa những gì tôi muốn - với dict.setdefault(), tôi phải lặp qua từng biến trong defaults; nhưng với dict.update(), defaults sẽ thổi bay mọi giá trị đã tồn tại trước đó trong mydict.

Có một số chức năng mà tôi không tìm thấy được tích hợp trong Python có thể thực hiện được không? Và nếu không muốn nói, là có một cách Pythonic hơn về cách viết một vòng lặp để liên tục gọi dict.setdefaults() hơn thế này:

for key in defaults.keys(): 
    mydict.setdefault(key, defaults[key]) 

Bối cảnh: Tôi đang viết một số dữ liệu bằng Python điều khiển như thế nào để phân tích một cây XML. Có một dict cho mỗi nút (tức là, làm thế nào để xử lý mỗi nút), và tôi muốn dữ liệu tôi viết lên được thưa thớt, nhưng điền vào với mặc định. Mã ví dụ chỉ là một ví dụ ... mã thực có nhiều cặp khóa/giá trị hơn trong dict mặc định.

(Tôi nhận ra toàn bộ câu hỏi này chỉ là một phân minh nhỏ, nhưng nó được làm phiền tôi, vì vậy tôi đã tự hỏi nếu có một cách tốt hơn để làm điều này mà tôi không biết.)

Trả lời

7

Bạn không thể làm cho bản sao của tôi là một bản sao của mặc định, Bằng cách đó, mydict sẽ có tất cả các giá trị chính xác để bắt đầu với?

mydict = default.copy() 
+0

Vâng, đây là những gì tôi thường làm quá .. – Macke

+0

Tôi nghĩ về điều này, nhưng sẽ không sao chép toàn bộ mặc định là khá kém hiệu quả (đặc biệt là mydict có tất cả các giá trị thiết lập để bắt đầu với)? Bạn sẽ tạo ra một dict mới, sao chép tất cả các giá trị của một số khác, sau đó viết lại toàn bộ dict một lần nữa trong trường hợp đó. –

+2

@Daniel Lew: các giá trị sẽ không được sao chép, chỉ cần tham chiếu đến chúng. Các dict mới sẽ có tài liệu tham khảo mới để các giá trị tương tự trong bộ nhớ. – nosklo

0
defaults.update(mydict) 
+0

Sau đó, làm cách nào để tôi có thể áp dụng các giá trị mặc định cho một nút khác? –

+0

giữ một bản sao của bản gốc ở đâu đó. – SilentGhost

+0

Trước tiên, bạn phải tạo bản in ngầm mặc định, sau đó ... – Stephan202

3

Nếu bạn không nhớ tạo ra một từ điển mới trong quá trình này, điều này sẽ làm các trick:

newdict = dict(defaults) 
newdict.update(mydict) 

Bây giờ newdict chứa những gì bạn cần.

5

Bạn có thể làm điều này theo cùng một cách collections.DefaultDict Python của hoạt động:

class MultiDefaultDict(dict): 
    def __init__(self, defaults, **kwargs): 
     self.defaults = defaults 
     self.update(kwargs) 
    def __missing__(self, key): 
     return self.defaults[key] 

>>> mydict2 = MultiDefaultDict(defaults, a=0) 
>>> mydict2['a'] 
0 
>>> mydict2['b'] 
10 
>>> mydict2 
{'a': 0} 

Các giải pháp khác được đăng cho đến nay lặp lại tất cả các giá trị mặc định; cái này chia sẻ chúng, theo yêu cầu. Bạn có thể hoặc không muốn ghi đè lên các phương thức dict khác như __contains __(), __iter __(), items(), keys(), values ​​() - lớp này như được định nghĩa ở đây lặp lại trên các mục không mặc định.

+0

+1 Cũng cần nhấn mạnh rằng không giống như 'defaultdict' (và' setdefault() ') bất kỳ khóa bị thiếu nào và các giá trị mặc định liên quan là * không * thực sự được thêm vào từ điển cơ bản - có thể hoặc không mong muốn. Trong mọi trường hợp, tất nhiên, có thể thay đổi ... – martineau

0

Cá nhân tôi muốn nối thêm đối tượng từ điển. Nó hoạt động chủ yếu giống như một từ điển ngoại trừ việc bạn phải tạo đối tượng đầu tiên.

class d_dict(dict): 
    'Dictionary object with easy defaults.' 
    def __init__(self,defaults={}): 
     self.setdefault(defaults)   
    def setdefault(self,defaults): 
     for key, value in defaults.iteritems(): 
      if not key in self: 
       dict.__setitem__(self,key,value) 

Điều này cung cấp chức năng chính xác giống như loại dict ngoại trừ việc nó ghi đè phương thức setdefault() và sẽ lấy từ điển chứa một hoặc nhiều mục. Bạn có thể đặt các giá trị mặc định khi tạo.

Đây chỉ là sở thích cá nhân. Khi tôi hiểu tất cả những gì dict.setdefault() làm là thiết lập các mục chưa được thiết lập. Vì vậy, có lẽ tùy chọn đơn giản nhất là:

new_dict = default_dict.copy() 
new_dict.update({'a':0}) 

Tuy nhiên, nếu bạn làm điều này nhiều lần bạn có thể thực hiện một chức năng trong số này.Tại thời điểm này, bạn có thể dễ dàng sử dụng đối tượng dict tùy chỉnh hơn là liên tục thêm các giá trị mặc định vào từ điển của bạn.

Các vấn đề liên quan