Коли використовувати словник проти кортежу в Python


31

Конкретним прикладом на увазі є список імен та їх розміри. Я не можу вирішити, чи має кожен елемент у списку бути такою формою {"filename": "blabla", "size": 123}, чи просто ("blabla", 123). Словник здається мені більш логічним, оскільки, наприклад, доступ до розміру file["size"]є більш пояснювальним, ніж file[1]... але я насправді не знаю точно. Думки?


Як додаток, розгляньте розпакування кортежу , якщо ви турбуєтесь про читабельність кортежів - fname, file_size = fileтам, де дані є вашими вище кортежами , це усуне file[1]і замінить його file_size. Звичайно, це спирається на хорошу документацію.
nlsdfnbch

2
Це залежить від того, яку структуру даних ви будуєте, і як ви маєте намір отримати доступ до неї? (за назвою файлу? за індексом? обидва?) Це просто переменная змінна структура / структура даних, чи можливо ви будете додавати інші елементи (/ атрибути), а також розмір? Чи потрібно структурі запам'ятати замовлення; Ви хочете сортувати список розмірів або отримати доступ до нього за позицією (наприклад, "Найбільші n найменші / найменші файли")? Залежно від них, найкращою відповіддю може бути dict, OrdersDict, nametuple, звичайний старий список або власний власний клас. Вам потрібно більше контексту.
smci

Відповіді:


78

Я б використав namedtuple:

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

Тепер ви можете використовувати file.sizeі file.filenameу своїй програмі, яка є IMHO найбільш читаною формою. Примітка namedtupleстворює незмінні об'єкти, як кортежі, і вони легші, ніж словники, як описано тут .


1
Дякую, гарна ідея, ніколи раніше про них не чула (я досить пікантна на Python). Питання: що трапиться, якщо хтось десь у коді також визначає той самий "клас", можливо дещо інакше. наприклад, в якомусь іншому вихідному файлі співробітник Боб мавFilesize = namedtuple('Filesize', 'filepath kilobytes')
user949300

Ви також можете використовувати дуже приємний attrsмодуль (можна знайти його через pipабо просто знайти), який дозволяє вам мати дуже схожі синтаксичні зручності з назвою кортеж, але може надати вам незмінність (але також можна зробити незмінною). Основна функціональна відмінність полягає в тому, що attrs-виготовлені класи не порівнюють рівних простих кортежів, як namedtupleце робиться.
mtraceur

3
@DocBrown Python не має поняття декларацій. class, defі =всі лише перезаписати будь-які попередні використання. repl.it
Challenger5

@ Challenger5: ти маєш рацію, моя помилка, тому правильна відповідь така: останнє визначення має значення, відсутність помилок під час виконання Python, але все ж схожа поведінка, як і у будь-якої іншої змінної.
Док Браун

8
Зауважте, що namedtupleпо суті це коротка заява для нового типу з незмінними атрибутами. Це означає, що відповідь ефективно: "Ні tupleані а dict, а є object". +1
jpmc26

18

{"filename": "blabla", "size": 123} або просто ("blabla", 123)

Це вікове питання про те, чи кодувати ваш формат / схему в діапазоні чи поза діапазоном.

Ви торгуєте деякою пам’яттю, щоб отримати читабельність і портативність, що випливає з вираження формату даних прямо в даних. Якщо цього не зробити, то знання, що перше поле - це ім'я файлу, а друге - розмір, має зберігатися в іншому місці. Це економить пам'ять, але при цьому коштує читабельності та портативності. Що обійдеться вашій компанії більше грошей?

Що стосується непорушного питання, пам’ятайте, що незмінне не означає марного в умовах змін. Це означає, що нам потрібно захопити більше пам’яті, внести зміни в копію та використати нову копію. Це не безкоштовно, але це часто не є зловмисником угод. Ми використовуємо незмінні рядки для того, щоб постійно змінювати речі.

Ще один розгляд - розширюваність. Якщо ви зберігаєте дані лише позиційно, не кодуючи інформацію про формат, ви засуджуєтесь лише до одного успадкування, що насправді є не що інше, як практика об'єднання додаткових полів після встановлених полів. Я можу визначити 3-е поле як дату створення і все ще бути сумісним з вашим форматом, оскільки я визначаю перше і друге так само.

Однак те, що я не можу зробити, - це об'єднати два незалежно визначених формату, які мають деякі поля, що перекриваються, а деякі - ні, зберігати їх в одному форматі, і це буде корисно для речей, які знають лише про той чи інший формат.

Для цього мені потрібно кодувати інформацію про формат з самого початку. Мені потрібно сказати "це поле - ім'я файлу". Це робить можливим багаторазове успадкування.

Ви, ймовірно, звикли успадковуватися лише в контексті об'єктів, але ті самі ідеї працюють і для форматів даних, оскільки, ну, об'єкти зберігаються у форматах даних. Це точно та сама проблема.

Тому використовуйте те, що, на вашу думку, вам найбільше потрібно. Я прагну до гнучкості, якщо не можу вказати на вагому причину цього не робити.


3
Якщо чесно, я сумніваюсь у тих, хто не впевнений у використанні формату в діапазоні чи поза діапазоном, є такі жорсткі вимоги до продуктивності, що їм потрібно буде використовувати формат поза діапазоном
Олександр - Відновити Моніку

2
@ Олександр дуже правда. Я вважаю за краще навчати людей про це, щоб вони розуміли, на що вони дивляться, стикаючись із позабійними рішеннями. Бінарні формати часто роблять це з причин обфускування. Не всі хочуть бути портативними. Що стосується причин продуктивності, якщо це дійсно важливо, врахуйте стиснення, перш ніж вдаватися до позадіапазону.
candied_orange

Пам'ятайте, що OP використовує Python, тому вони, мабуть, не надто стурбовані продуктивністю. Більшість кодів високого рівня слід писати спочатку з читальністю; передчасна оптимізація - корінь усього зла.
Dagrooms

@Dagrooms не ненавидять Python. Він спрацьовує добре у багатьох випадках. Але в іншому випадку я згоден з усім, що ви сказали. Моя думка полягала в тому, щоб сказати: "Ось чому люди так роблять. Ось чому вам, ймовірно, все одно"
candied_orange

@CandiedOrange Я не ненавиджу мову, використовую її у своїй щоденній роботі. Мені не подобається те, як люди його використовують.
Dagrooms

7

Я б використав клас з двома властивостями. file.sizeприємніше, ніж будь-який file[1]або file["size"].

Простий - краще, ніж складний.


Якщо хтось задається питанням: Для генерації JSON обидва працюють однаково добре: file = Filesize(filename='stuff.txt', size=222)і filetup = ("stuff.txt", 222)обидва генерують один і той же JSON: json.dumps(file)і json.dumps(filetup)призводять до:'["stuff.txt", 222]'
Juha Untinen

5

Чи унікальні файли файлів? Якщо це так, ви можете повністю видалити список і просто використати чистий словник для всіх файлів. наприклад (гіпотетичний веб-сайт)

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

тощо ...

Тепер ви не отримуєте "ім'я" та "розмір", ви просто використовуєте ключ та значення, але часто це більш природно. YMMV.

Якщо ви дійсно хочете "розмір" для ясності або вам потрібно більше одного значення для файлу, то:

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

0

У python словник є об'єктом, що змінюється. Інша сторона, кортеж - незмінний предмет.

якщо вам потрібно змінити ключ словника, пара значень часто або кожен раз. Я пропоную словник використовувати.

якщо у вас є фіксовані / статичні дані, я пропоную використовувати кортеж.

# 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'

Але, не в змозі змінити кортеж даних за допомогою оператора призначення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.