[] і {} vs list () та dict (), що краще?


113

Я розумію, що вони обоє по суті одне і те ж, але з точки зору стилю, який кращий (більш пітонічний) використовувати для створення порожнього списку чи дикту?

Відповіді:


197

З точки зору швидкості, це не конкуренція за порожні списки / дикти:

>>> from timeit import timeit
>>> timeit("[]")
0.040084982867934334
>>> timeit("list()")
0.17704233359267718
>>> timeit("{}")
0.033620194745424214
>>> timeit("dict()")
0.1821558326547077

а для непорожніх:

>>> timeit("[1,2,3]")
0.24316302770330367
>>> timeit("list((1,2,3))")
0.44744206316727286
>>> timeit("list(foo)", setup="foo=(1,2,3)")
0.446036018543964
>>> timeit("{'a':1, 'b':2, 'c':3}")
0.20868602015059423
>>> timeit("dict(a=1, b=2, c=3)")
0.47635635255323905
>>> timeit("dict(bar)", setup="bar=[('a', 1), ('b', 2), ('c', 3)]")
0.9028228448029267

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


4
Ознайомлення з рейтингом та списком можна здійснити і з використанням англійських імен. Приклад:list(i for i in range(10) if i % 2)
Загс

4
Чи є причина, чому {} і [] так швидше? Я думав, що вони просто псевдоніми.
Джастін Д.

Схоже, що час не дає точного часу. Відповідно до еталону, здається, це займає ~ 200 мс, що набагато повільніше, ніж звичайні http-дзвінки. Спробуйте запустити dict () зазвичай в оболонці, а потім запустіть timeit ("dict ()"), ви побачите видиму різницю у виконанні.
піюш

2
@piyush Власне, timeit()функція повідомляє про загальну кількість часу для виконання заданої кількості ітерацій, яка 1000000за замовчуванням. Отже, наведені вище приклади - це кількість секунд, щоб виконати фрагмент коду мільйон разів. Наприклад timeit('dict()', number=1) // -> 4.0531158447265625e-06(одна ітерація) у той час timeit('dict()') // -> 0.12412905693054199(мільйон ітерацій)
Грег Хаскінс

@GregHaskins, тому в цьому випадку я не бачу, що варто переживати за використання dict () або {}, якщо тільки не перегляньте мільйон записів і не використовуєте dict () у циклі.
піюш

37

На мій погляд []і{} є найбільш віщий і машиночитаних способи створення порожніх списків / dicts.

Будьте обережні set(), хоча, наприклад:

this_set = {5}
some_other_set = {}

Може заплутати. Перший створює набір з одним елементом, другий створює порожній дикт і не множину.


4
{}завжди створює порожній дикт. {1,2,3}створює набір в 2.7+, але є помилкою синтаксису у 2.6та старших версіях.
ThiefMaster

1
вибачте? це змінна назва, some_epic_setяка вказує на порожній dictоб'єкт ... це не порожній набір. Для порожнього набору потрібно використовувати set().
6502,

2
@ 6502: Дійсно, але це звичайний підводний камінь, який {5}створює набір з одним елементом, 5і {}є порожнім висловом.
orlp

1
Ого, це було заплутано. Тим не менш, це не Fraktal of Bad Design збиває з пантелику. :-)
Проф. Фолкен

4
@EnderLook: Насправді, із узагальненим розпакуванням , ви можете використовувати {*()}порожній setз буквальним синтаксисом. Я називаю це однооким оператором мавп. :-)
ShadowRanger

17

Диктує літерал може бути крихітними трохи швидше , так як його байткод коротше:

In [1]: import dis
In [2]: a = lambda: {}
In [3]: b = lambda: dict()

In [4]: dis.dis(a)
  1           0 BUILD_MAP                0
              3 RETURN_VALUE

In [5]: dis.dis(b)
  1           0 LOAD_GLOBAL              0 (dict)
              3 CALL_FUNCTION            0
              6 RETURN_VALUE

Те ж стосується і listvs[]


8
Це передбачає, що BUILD_MAP і LOAD_GLOBAL є постійним часом і займають однакову кількість часу. Вкрай малоймовірно. timeit дає набагато кращу оцінку.
Джеймі Пате

Швидше за все, це CALL_FUNCTIONзаймає щонайменше стільки ж часу, як BUILD_MAP(функція, яка називається по суті, є BUILD_MAP), і LOAD_GLOBALзаймає лише додаткові накладні витрати.
чепнер


3

У випадку різниці між [] та списком (), є підводний камінь, на який я ще не бачив, щоб хтось вказував. Якщо ви використовуєте словник як член списку, вони дадуть абсолютно різні результати:

In [1]: foo_dict = {"1":"foo", "2":"bar"}

In [2]: [foo_dict]
Out [2]: [{'1': 'foo', '2': 'bar'}]

In [3]: list(foo_dict)
Out [3]: ['1', '2'] 

Ви можете отримати ті ж результати, що і [foo_dict]за допомогою list((foo_dict,)). list()Метод приймає итератор , оскільки це єдиний параметр і ітерацію над ним , щоб додати елементи в список. Це спричинить подібний провал, виконуючи list(some_list)який, вирівнюватиме список.
sotrh

1

list () та [] працюють по-різному:

>>> def a(p=None):
...     print(id(p))
... 
>>> for r in range(3):
...     a([])
... 
139969725291904
139969725291904
139969725291904
>>> for r in range(3):
...     a(list())
... 
139969725367296
139969725367552
139969725367616

list () завжди створює новий об’єкт у купі, але [] може використовувати багато комірок пам'яті з багатьох причин.


0

є одна різниця в поведінці між [] та list (), як показано нижче в прикладі. нам потрібно використовувати list (), якщо ми хочемо повернути список номерів, інакше ми отримаємо об’єкт карти! Не знаю, як це пояснити.

sth = [(1,2), (3,4),(5,6)]
sth2 = map(lambda x: x[1], sth) 
print(sth2) # print returns object <map object at 0x000001AB34C1D9B0>

sth2 = [map(lambda x: x[1], sth)]
print(sth2) # print returns object <map object at 0x000001AB34C1D9B0>
type(sth2) # list 
type(sth2[0]) # map

sth2 = list(map(lambda x: x[1], sth))
print(sth2) #[2, 4, 6]
type(sth2) # list
type(sth2[0]) # int

тут, здається, пояснення поведінки на прикладі функції range () >>> print (range (10)) # range (0, 10) range () поводиться як список, але це не список. Це об'єкт, який повертає послідовні елементи з послідовності, коли ви повторюєте його, він насправді не складає список, економлячи місце. такий об'єкт є ітерабельним, тобто підходить як ціль для функцій і конструкцій, які очікують чогось, від чого вони можуть отримати послідовні елементи до вичерпання пропозиції. Список функцій () створює списки з ітерабелів: >>> список (діапазон (5)) # [0, 1, 2, 3, 4]
sebtac

1
наслідок цього полягає в тому, що [] зберігає ітерабельний об'єкт; list () створює список з того самого ітерабельного
sebtac

0

Пара дужок поля позначає один із об’єктів списку або індексний індекс, мій_ список [x].

Фігурна дужка пара позначає об’єкт словника.

a_list = ['on', 'off', 1, 2]

a_dict = {on: 1, off: 2}


-5

В основному це питання вибору більшість часу. Це питання переваги.

Однак зауважте, що якщо у вас є цифрові клавіші, наприклад, ви не можете:

mydict = dict(1="foo", 2="bar")

Ви повинні зробити:

mydict = {"1":"foo", "2":"bar"}

7
Це неправильно ... вам потрібно зробити mydict = {1:"foo", 2:"bar"}(без лапок для ключів).
6502,

8
Це не просто "неправильно". Клавіші - це рядки / вставки залежно від того, цитуєте ви їх чи ні.
ThiefMaster
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.