Cú pháp ưa thích để khởi tạo một dict: hàm ngoặc kép {} hoặc hàm dict () là gì?


212

Tôi đang nỗ lực để học Python và tôi rất chú ý đến các tiêu chuẩn mã hóa phổ biến. Đây có vẻ như là một câu hỏi khó hiểu vô nghĩa, nhưng tôi đang cố gắng tập trung vào các thực hành tốt nhất khi tôi học, vì vậy tôi không phải học bất kỳ thói quen 'xấu' nào.

Tôi thấy hai phương thức phổ biến để khởi tạo một lệnh:

a = {
    'a': 'value',
    'another': 'value',
}

b = dict( 
    a='value',
    another='value',
)

Cái nào được coi là "nhiều pythonic"? Bạn dùng cái nào Tại sao?


5
Hướng dẫn nào bạn đang sử dụng? Trường hợp bạn đã thấy các ví dụ dẫn đến nhầm lẫn?
S.Lott

2
Chà, tôi đã sử dụng hướng dẫn Python, Lặn vào Python và sau đó là một loạt các blog, bài đăng SO và các tài nguyên khác của Google. Các tài liệu chính thức sử dụng {}khá thống nhất, nhưng tôi thấy rất nhiều cách dict()tiếp cận rõ ràng ở nơi khác. Tôi có thể thấy lợi ích của một cú pháp rõ ràng, nhưng sự vắng mặt của cách tiếp cận trong các tài liệu chính thức khiến tôi nghi ngờ. Sau khi đăng bài này, tôi đã xem các tài liệu của thư viện dictvà nhận thấy sự thận trọng rằng các khóa phải là định danh hợp lệ khi một bản tường minh dictđược sử dụng để khởi tạo một lệnh.
daotoad

2
Làm thế nào là "dict ()" rõ ràng hơn "{}"? Tôi không hiểu sự nhầm lẫn của bạn. Cả hai dường như rõ ràng với tôi. Bạn có thể cung cấp một trích dẫn hoặc tài liệu tham khảo khiến bạn nói "dict" là "tường minh" và "{}" không rõ ràng không? Bạn nghĩ sự khác biệt này phát sinh từ đâu?
S.Lott

21
Sự phân biệt là chính tả. dict()được đánh vần dict--it sử dụng tên của loại. Các dấu ngoặc ( {}) dựa vào dấu câu để xác định loại.
daotoad

Câu trả lời:


235

Dấu ngoặc nhọn. Truyền các đối số từ khóa vào dict(), mặc dù nó hoạt động rất đẹp trong nhiều tình huống, chỉ có thể khởi tạo bản đồ nếu các khóa là định danh Python hợp lệ.

Những công việc này:

a = {'import': 'trade', 1: 7.8}
a = dict({'import': 'trade', 1: 7.8})

Điều này sẽ không hoạt động:

a =                  dict(import='trade', 1=7.8)
>> SyntaxError: invalid syntax  ^

85

Đầu tiên, niềng răng xoăn. Mặt khác, bạn gặp phải các vấn đề về tính nhất quán với các khóa có các ký tự kỳ lạ trong đó =.

# Works fine.
a = {
    'a': 'value',
    'b=c': 'value',
}

# Eeep! Breaks if trying to be consistent.
b = dict( 
    a='value',
    b=c='value',
)

11
Đây chính xác là lý do tại sao người ta có thể thích phương thức dict () để khởi tạo, nó buộc các khóa từ điển phải là định danh hợp lệ, vì vậy chúng tương thích với, ví dụ, ** kwargs và khóa là tên thuộc tính hợp lệ.
RufusVS

57

Phiên bản đầu tiên là thích hợp hơn:

  • Nó hoạt động cho tất cả các loại khóa, vì vậy, ví dụ, bạn có thể nói {1: 'one', 2: 'two'}. Biến thể thứ hai chỉ hoạt động cho (một số) khóa chuỗi. Sử dụng các loại cú pháp khác nhau tùy thuộc vào loại khóa sẽ là một sự không nhất quán không cần thiết.
  • Nó nhanh hơn:

    $ python -m timeit "dict(a='value', another='value')"
    1000000 loops, best of 3: 0.79 usec per loop
    $ python -m timeit "{'a': 'value','another': 'value'}"
    1000000 loops, best of 3: 0.305 usec per loop
  • Nếu cú ​​pháp đặc biệt cho nghĩa đen của từ điển không được sử dụng, nó có thể sẽ không tồn tại.

3

Tôi nghĩ rằng tùy chọn đầu tiên tốt hơn bởi vì bạn sẽ truy cập các giá trị dưới dạng ['a'] hoặc ['khác']. Các khóa trong từ điển của bạn là các chuỗi và không có lý do gì để giả vờ chúng không có. Đối với tôi cú pháp từ khóa thoạt nhìn có vẻ thông minh, nhưng tối nghĩa ở cái nhìn thứ hai. Điều này chỉ có ý nghĩa với tôi nếu bạn đang làm việc __dict__và các từ khóa sẽ trở thành thuộc tính sau này, đại loại như thế.


3

FYI, trong trường hợp bạn cần thêm thuộc tính vào từ điển của mình (những thứ được đính kèm với từ điển, nhưng không phải là một trong các khóa), thì bạn sẽ cần mẫu thứ hai. Trong trường hợp đó, bạn có thể khởi tạo từ điển của mình bằng các khóa có các ký tự tùy ý, mỗi lần một ký tự, như vậy:

    class mydict(dict): pass
    a = mydict()        
    a["b=c"] = 'value'
    a.test = False

2

Đôi khi dict()là một lựa chọn tốt:

a=dict(zip(['Mon','Tue','Wed','Thu','Fri'], [x for x in range(1, 6)]))

mydict=dict(zip(['mon','tue','wed','thu','fri','sat','sun'],

[Random.randint (0,100) cho x trong phạm vi (0,7)]))


2
Có một chức năng liệt kê có thể làm điều này tốt hơn. Đối với vấn đề đó, có một loại Enum có thể làm những gì bạn đang làm ở đây tốt hơn. Ngoài ra, đây thực sự không phải là một câu trả lời cho câu hỏi.
dusktreader

2

Tôi hầu như luôn luôn sử dụng niềng răng xoăn; tuy nhiên, trong một số trường hợp tôi đang viết bài kiểm tra, tôi thực hiện đóng gói / giải nén từ khóa và trong những trường hợp này, dict () có thể duy trì nhiều hơn, vì tôi không cần phải thay đổi:

a=1,
b=2,

đến:

'a': 1,
'b': 2,

Nó cũng giúp ích trong một số trường hợp mà tôi nghĩ rằng tôi có thể muốn biến nó thành một thể hiện tên hoặc lớp sau đó.

Trong quá trình thực hiện, vì nỗi ám ảnh của tôi đối với việc tối ưu hóa và khi tôi không thấy lợi ích bảo trì đặc biệt lớn, tôi sẽ luôn ưu tiên niềng răng xoăn.

Trong các thử nghiệm và triển khai, tôi sẽ không bao giờ sử dụng dict () nếu có khả năng các khóa được thêm vào sau đó hoặc trong tương lai sẽ:

  • Không phải lúc nào cũng là một chuỗi
  • Không chỉ chứa chữ số, chữ cái ASCII và dấu gạch dưới
  • Bắt đầu với một số nguyên ( dict(1foo=2)tăng SyntaxError)
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.