Понимание словаря несколькими способами - PullRequest
0 голосов
/ 28 февраля 2020

В чем будет разница между следующими двумя утверждениями в python?

l = [1,2,3,4]
a = {item:0 for item in l}
b = dict((item,0) for item in l)
a == b
# True

Я полагаю, что первое - это правильный способ инициализации словаря через понимание из PEP , тем не менее, второй способ, по-видимому, просто создает выражение генератора, а затем создает из него диктовку (и, возможно, он делает то же самое, что и первый закулисный подход?). Какая на самом деле разница между этими двумя, и какая из них должна быть предпочтительнее другой?

1 Ответ

2 голосов
/ 28 февраля 2020
a = {item:0 for item in l}

Непосредственно создает dict, без промежуточных звеньев.

b = dict((item,0) for item in l)

Создает кортеж для каждого элемента в списке и передает его конструктору dict().

Я не сомневаюсь в том, что даже не копаясь в кишечнике полученного байтового кода Python, есть простой способ выяснить, насколько точно они отличаются. Что касается производительности, они, вероятно, также будут очень близки.

Главное, что я хотел бы рассмотреть, - это удобочитаемость и удобство обслуживания. Первый способ основан только на нужных элементах, без использования промежуточного типа данных (кортежа) и без непосредственного вызова типа, но вместо этого полагается на сам язык для правильного подключения. В качестве бонуса, он короче и проще - я не вижу никаких преимуществ в использовании второго варианта, за исключением, может быть, явного использования dict, сообщающего другим, что такое ожидаемый тип. Но если они не получат это от {} в первую очередь, я сомневаюсь, что они все равно хороши ...

Я подумал, что проверю скорость:

from timeit import timeit
from random import randint

l = [randint(0, 1000) for _ in range(1000)]


def first():
    return {item: 0 for item in l}


def second():
    return dict((item,0) for item in l)


print(timeit(first, number=10000))
print(timeit(second, number=10000))

Результат:

0.46899440000000003
1.0817516999999999

Постоянно быстрее, поэтому, кажется, нет необходимости использовать второй вариант. Если здесь есть что-то удивительное, так это то, насколько плохо оптимизирован второй пример и насколько плохо он работает.

...