Khi nào nên sử dụng từ điển vs tuple trong Python


31

Ví dụ cụ thể trong tâm trí là một danh sách tên tệp và kích thước của chúng. Tôi không thể quyết định liệu mỗi mục trong danh sách nên có dạng {"filename": "blabla", "size": 123}hay chỉ ("blabla", 123). Một từ điển có vẻ hợp lý hơn đối với tôi bởi vì để truy cập kích thước, ví dụ, file["size"]có nhiều giải thích hơn file[1]... nhưng tôi thực sự không biết chắc chắn. Suy nghĩ?


Là một phụ lục, hãy xem xét việc giải nén tuple , nếu bạn lo lắng về khả năng đọc của các bộ fname, file_size = filedữ liệu - , trong đó dữ liệu là bộ dữ liệu trên của bạn, sẽ loại bỏ file[1]và thay thế bằng file_size. Tất nhiên điều này dựa vào một tài liệu tốt.
nlsdfnbch

2
Nó phụ thuộc vào cấu trúc dữ liệu nào bạn đang xây dựng và bạn dự định truy cập nó như thế nào? (theo tên tệp? theo chỉ mục? cả hai?) Đây chỉ là một biến số / cấu trúc dữ liệu, hoặc bạn có thể sẽ thêm các mục (/ thuộc tính) khác cũng như kích thước không? Có cấu trúc cần phải nhớ một đơn đặt hàng; Bạn có muốn sắp xếp danh sách kích thước hoặc truy cập nó theo vị trí (ví dụ: "tệp lớn nhất / nhỏ nhất") không? Tùy thuộc vào những câu hỏi đó, câu trả lời 'tốt nhất' có thể là dict, OrderedDict, namtuple, danh sách cũ đơn giản hoặc một lớp tùy chỉnh của riêng bạn. Cần thêm bối cảnh từ bạn.
smci

Câu trả lời:


78

Tôi sẽ sử dụng một namedtuple:

from collections import namedtuple
Filesize = namedtuple('Filesize', 'filename size')
file = Filesize(filename="blabla", size=123)

Bây giờ bạn có thể sử dụng file.sizefile.filenametrong chương trình của mình, IMHO là hình thức dễ đọc nhất. Lưu ý namedtupletạo ra các đối tượng bất biến như bộ dữ liệu và chúng nhẹ hơn từ điển, như được mô tả ở đây .


1
Cảm ơn, ý kiến ​​hay, chưa bao giờ nghe về chúng trước ngày hôm nay (Tôi khá mới lạ với Python). Câu hỏi: điều gì xảy ra nếu ai đó trong mã cũng định nghĩa cùng một "lớp", có thể hơi khác nhau. ví dụ: trong một số tệp nguồn khác, đồng nghiệp Bob đã cóFilesize = namedtuple('Filesize', 'filepath kilobytes')
user949300

Bạn cũng có thể sử dụng attrsmô-đun rất đẹp (có thể tìm thấy nó thông qua piphoặc chỉ tìm kiếm nó), cho phép bạn có các tiện ích cú pháp rất giống với tên tuple, nhưng có thể cung cấp cho bạn khả năng biến đổi (nhưng cũng có thể được tạo thành bất biến). Sự khác biệt về chức năng chính là attrscác lớp được tạo không so sánh bằng với các bộ dữ liệu đơn giản, cách namedtuplelàm.
mtraceur

3
@DocBrown Python không có khái niệm khai báo. class, def=tất cả chỉ ghi đè lên bất kỳ việc sử dụng trước đó. repl.it
Challenger5

@ Challenger5: bạn đã đúng, lỗi của tôi, vì vậy câu trả lời đúng là: tính định nghĩa mới nhất, không có lỗi từ thời gian chạy Python, nhưng vẫn hoạt động tương tự như với bất kỳ biến nào khác.
Doc Brown

8
Lưu ý rằng namedtuplevề cơ bản là một khai báo tay ngắn cho một loại mới với các thuộc tính bất biến. Điều này có nghĩa là câu trả lời có hiệu quả, "Không tuplephải cũng không phải dict, mà là một object." +1
jpmc26

18

{"tên tệp": "blabla", "size": 123} hoặc chỉ ("blabla", 123)

Đây là câu hỏi cũ về việc nên mã hóa định dạng / lược đồ của bạn trong băng tần hay ngoài băng tần.

Bạn đánh đổi một số bộ nhớ để có được khả năng đọc và tính di động xuất phát từ việc thể hiện định dạng của dữ liệu ngay trong dữ liệu. Nếu bạn không làm điều này, kiến ​​thức rằng trường đầu tiên là tên tệp và thứ hai là kích thước phải được giữ ở nơi khác. Điều đó giúp tiết kiệm bộ nhớ nhưng chi phí dễ đọc và tính di động. Điều này sẽ làm chi phí công ty của bạn nhiều tiền hơn?

Đối với vấn đề bất di bất dịch, hãy nhớ rằng bất biến không có nghĩa là vô dụng khi đối mặt với sự thay đổi. Điều đó có nghĩa là chúng ta cần lấy thêm bộ nhớ, thực hiện thay đổi trong một bản sao và sử dụng bản sao mới. Điều đó không miễn phí nhưng nó thường không phải là một công cụ thỏa thuận. Chúng tôi sử dụng các chuỗi bất biến để thay đổi mọi thứ mọi lúc.

Một xem xét khác là khả năng mở rộng. Khi bạn chỉ lưu trữ dữ liệu theo vị trí, không có thông tin định dạng mã hóa, thì bạn sẽ bị kết án chỉ là thừa kế duy nhất, thực sự không có gì ngoài thực hành ghép các trường bổ sung sau các trường đã thiết lập. Tôi có thể xác định trường thứ 3 là ngày tạo và vẫn tương thích với định dạng của bạn vì tôi xác định trường thứ nhất và thứ hai theo cùng một cách.

Tuy nhiên, những gì tôi không thể làm là tập hợp hai định dạng được xác định độc lập có một số trường chồng chéo, một số không, lưu trữ chúng ở một định dạng và có ích với những điều chỉ biết về một hoặc các định dạng khác.

Để làm điều đó tôi cần mã hóa thông tin định dạng từ đầu. Tôi cần nói "trường này là tên tệp". Làm điều đó cho phép nhiều thừa kế.

Bạn có thể được sử dụng để kế thừa chỉ được thể hiện trong ngữ cảnh của các đối tượng nhưng các ý tưởng tương tự hoạt động cho các định dạng dữ liệu bởi vì, tốt, các đối tượng được lưu trữ trong các định dạng dữ liệu. Đó chính xác là cùng một vấn đề.

Vì vậy, sử dụng bất cứ điều gì bạn nghĩ rằng bạn có khả năng cần nhất. Tôi đạt đến sự linh hoạt trừ khi tôi có thể chỉ ra một lý do chính đáng để không.


3
Thành thật mà nói, tôi nghi ngờ bất kỳ ai không chắc chắn giữa việc sử dụng định dạng trong băng tần hoặc ngoài băng tần có yêu cầu hiệu suất chặt chẽ đến mức họ cần phải sử dụng định dạng ngoài băng tần
Alexander - Tái lập lại

2
@Alexander rất đúng. Tôi thích dạy mọi người về điều đó để họ hiểu những gì họ đang nhìn khi đối mặt với các giải pháp ngoài ban nhạc. Các định dạng nhị phân thường làm điều này vì lý do che giấu. Không phải ai cũng muốn được xách tay. Đối với lý do hiệu suất, nếu nó thực sự quan trọng hãy xem xét nén trước khi sử dụng ngoài băng tần.
candied_orange

Hãy nhớ rằng OP đang sử dụng Python, vì vậy họ có thể không quá quan tâm đến hiệu suất. Hầu hết các mã cấp cao nên được viết với tính dễ đọc trước tiên; tối ưu hóa sớm là gốc rễ của mọi tội lỗi.
Dagroom

@Dagroom không được ghét Python. Nó thực hiện tốt trong nhiều trường hợp. Nhưng nếu không thì tôi đồng ý với mọi thứ bạn nói. Quan điểm của tôi là nói "Đây là lý do tại sao mọi người làm điều đó. Đây là lý do tại sao bạn có thể không quan tâm".
candied_orange

@CandiedOrange Tôi không ghét ngôn ngữ này, tôi sử dụng nó trong công việc hàng ngày. Tôi không thích cách mọi người sử dụng nó.
Dagroom

7

Tôi sẽ sử dụng một lớp học với hai thuộc tính. file.sizelà tốt hơn so với file[1]hoặc file["size"].

Đơn giản là tốt hơn phức tạp.


Trong trường hợp ai đó đang tự hỏi: Để tạo JSON, cả hai đều hoạt động tốt như nhau: file = Filesize(filename='stuff.txt', size=222)filetup = ("stuff.txt", 222)cả hai đều tạo cùng một JSON: json.dumps(file)json.dumps(filetup)kết quả là:'["stuff.txt", 222]'
Juha Untinen

5

Tên tập tin là duy nhất? Nếu vậy, bạn có thể loại bỏ hoàn toàn danh sách và chỉ cần sử dụng một từ điển thuần túy cho tất cả các tệp. ví dụ (một trang web giả định)

{ 
  "/index.html" : 5467,
  "/about.html" : 3425,
  "/css/main.css" : 9876
}

v.v ...

Bây giờ, bạn không nhận được "tên" và "kích thước", bạn chỉ cần sử dụng khóa và giá trị, nhưng thường thì điều này là tự nhiên hơn. YMMV.

Nếu bạn thực sự muốn có "kích thước" cho rõ ràng hoặc bạn cần nhiều hơn một giá trị cho tệp, thì:

{ 
   "/index.html" : { "size": 5467, "mime_type" : "foo" },
   "/about.html" : { "size": 3425, "mime_type" : "foo" }
   "/css/main.css" : { "size": 9876, "mime_type" : "bar" }
}

0

Trong python, từ điển là đối tượng có thể thay đổi. Mặt khác, tuple là đối tượng bất biến.

nếu bạn cần thay đổi khóa từ điển, cặp giá trị thường xuyên hoặc mọi lúc. tôi đề nghị từ điển để sử dụng.

nếu bạn có dữ liệu cố định / tĩnh, tôi đề nghị sử dụng bộ dữ liệu.

# dictionary define.
a = {}
a['test'] = 'first value'

# tuple define.
b = ()
b = b+(1,)

# here, we can change dictionary value for key 'test'
a['test'] = 'second'

Nhưng, không thể thay đổi dữ liệu bằng cách sử dụng toán tử gán.

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.