Python: chuyển đổi defaultdict thành dict


91

Làm thế nào tôi có thể chuyển đổi một sắc lệnh mặc định

number_to_letter
defaultdict(<class 'list'>, {'2': ['a'], '3': ['b'], '1': ['b', 'a']})

là một mệnh lệnh chung?

{'2': ['a'], '3': ['b'], '1': ['b', 'a']}

10
dict(number_to_letter)
Tim Peters

2
@TimPeters vì đây thực sự là một câu hỏi được viết độc đáo, với tiêu đề rõ ràng (và nên hiển thị dễ dàng trong các tìm kiếm), để tham khảo trong tương lai, nên đặt nó như một câu trả lời nếu chúng tôi không thể tìm thấy một bản dupe tốt hơn .. .
Jon Clements

Câu trả lời này sẽ hữu ích: stackoverflow.com/a/3031915/1628832
karthikr

1
@JonClements, điểm tốt, nhưng DSM đã làm - tôi hy vọng câu trả lời của anh ấy được chấp nhận :-)
Tim Peters

2
@TimPeters chúc mừng bạn với 10k btw ... Tôi có cảm giác rằng bạn sẽ không mất nhiều thời gian - bạn nên (cắm mặt không biết xấu hổ) bật lên bằng chat.stackoverflow.com/rooms/6/python vào một lúc nào đó :)
Jon Clements

Câu trả lời:


122

Bạn chỉ cần gọi dict:

>>> a
defaultdict(<type 'list'>, {'1': ['b', 'a'], '3': ['b'], '2': ['a']})
>>> dict(a)
{'1': ['b', 'a'], '3': ['b'], '2': ['a']}

nhưng hãy nhớ rằng một sắc lệnh mặc định một mệnh lệnh:

>>> isinstance(a, dict)
True

chỉ với hành vi hơi khác, trong đó khi bạn cố gắng truy cập vào một khóa bị thiếu - thông thường sẽ nâng lên một KeyError- default_factorythay thế được gọi là:

>>> a.default_factory
<type 'list'>

Đó là những gì bạn thấy khi bạn print atrước khi phía dữ liệu của từ điển xuất hiện.

Vì vậy, một mẹo khác để khôi phục lại hành vi giống như độc tài hơn mà không thực sự tạo một đối tượng mới là đặt lại default_factory:

>>> a.default_factory = None
>>> a[4].append(10)
Traceback (most recent call last):
  File "<ipython-input-6-0721ca19bee1>", line 1, in <module>
    a[4].append(10)
KeyError: 4

nhưng hầu hết thời gian điều này không đáng để rắc rối.


tôi mới bắt đầu học lập trình với Python. Bạn có thể giải thích thêm về cách sử dụng default_factory? Tôi không biết chuyện gì đang xảy ra. Lấy làm tiếc.
user2988464

Và 'KeyError' là gì?
user2988464

4
@ user2988464: bạn đã sử dụng default_factory- đó là hàm mà bạn đã vượt qua khi thực hiện ngay defaultdicttừ đầu, như defaultdict(int)hoặc defaultdict(list). Bất cứ khi nào bạn cố gắng tra cứu một khóa trong từ điển, chẳng a['3']hạn như trong một từ điển thông thường, bạn sẽ nhận được giá trị hoặc nó tạo ra một KeyErrorngoại lệ (chẳng hạn như lỗi, cho bạn biết rằng không thể tìm thấy khóa đó). Nhưng defaultdictthay vào đó, nó gọi default_factoryhàm để tạo một giá trị mặc định mới (đó là "mặc định" trong defaultdict) cho bạn.
DSM

2
Hữu ích cần lưu ý rằng thuộc tính mẫu .items của Django sẽ không hoạt động với defaultdict, đó là lý do tại sao tôi kết thúc ở đây! Vì vậy, có một lý do chính đáng cho việc chuyển đổi
Ben,

2
Cũng hữu ích cần lưu ý rằng pickle(để lưu các đối tượng python vào một tệp) không thể xử lý defaultdicts trong nhiều trường hợp .
drevicko

28

Nếu câu lệnh mặc định của bạn được định nghĩa đệ quy, ví dụ:

from collections import defaultdict
recurddict = lambda: defaultdict(recurddict)
data = recurddict()
data["hello"] = "world"
data["good"]["day"] = True

một cách đơn giản khác để chuyển đổi defaultdict trở lại dict là sử dụng jsonmodule

import json
data = json.loads(json.dumps(data))

và tất nhiên, các giá trị có trong sắc lệnh mặc định của bạn cần được giới hạn trong các kiểu dữ liệu được json hỗ trợ, nhưng sẽ không thành vấn đề nếu bạn không có ý định lưu trữ các lớp hoặc hàm trong dict.


8
Ý kiến ​​hay, quá tệ là dữ liệu của tôi sẽ không được tuần tự hóa thành JSON: * (
Kasapo

15

Nếu bạn thậm chí muốn có một phiên bản đệ quy để chuyển đổi một đệ quy defaultdictcho một dictbạn có thể thử như sau:

#! /usr/bin/env python3

from collections import defaultdict

def ddict():
    return defaultdict(ddict)

def ddict2dict(d):
    for k, v in d.items():
        if isinstance(v, dict):
            d[k] = ddict2dict(v)
    return dict(d)

myddict = ddict()

myddict["a"]["b"]["c"] = "value"

print(myddict)

mydict = ddict2dict(myddict)

print(mydict)

Đó chính xác là những gì tôi cần! Thật không may, defaultdict của tôi có một số phím mà không phải là JSON serializable mà không có một bộ mã hóa tùy chỉnh (các phím là các bộ - không lựa chọn của tôi, chỉ là vấn đề của tôi)
Kasapo

Tốt. Sử dụng một sự hiểu biết từ điển là gọn gàng nếu nó chỉ có hai lớp sâu (ví dụ defaultdict(lambda: defaultdict(int))): {k: dict(v) for k, v in foo.items()}
ggorlen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.