Alala
Окт. 20, 2011 15:40:18
Возник с коллегой спор, какой вариант работает быстрее:
1)
a = {'a':[0, 1], 'b':[1, 1], c:[1, 0]}
for x in a:
megafunction(x, a[x][0], a[x][1])2)
a = {'a':[0, 1], 'b':[1, 1], c:[1, 0]}
for x,y in a.iteritems():
megafunction(x, y[0], y[1])есть какие-то преимущества одного варианта над другим?
truporez
Окт. 20, 2011 16:16:09
Вот на таком тесте итератор работает чуть быстрее
#!/usr/bin/env python
#-*- coding: UTF-8 -*-
import cProfile
a = dict( (i, [i&1, i&2]) for i in xrange(5000000) )
megafunction = lambda a, b, c: a+b-c
def test1():
for x in a:
megafunction(x, a[x][0], a[x][1])
def test2():
for x,y in a.iteritems():
megafunction(x, y[0], y[1])
cProfile.run("test1()")
cProfile.run("test2()")
Fibio
Окт. 20, 2011 23:13:08
на самом деле тестила несколько раз простые циклы, map и генераторы списков, простые циклы всегда чуть медленнее, а вот map и генераторы дают неоднозначные результаты, даже при выполнении одного и того же выражения (ф-ции), хотя Лутц утверждает что генераторы быстрее. В Вашем варианте преимуществ имхо нет.
Alala
Окт. 24, 2011 10:09:22
truporez
Ок, спасибо!
я как-то не догадалась тупо протестить это)))
Вообще, конечно, хотелось бы понять разницу в устройстве
Enchantner
Окт. 24, 2011 10:40:01
Alala
их имеет смысл сравнивать только на больших объемах данных. Попробуй сгенерировать словарь на пару тысяч значений и отпрофилируй.
Я так понимаю, что в случае iteritems() всё должно быть эффективнее, потому что с помощью for'а ты как бы приделываешь итератор снаружи к объекту и при этом хранишь его в памяти. Во втором же случае объект сам предоставляет тебе свой интерфейс итератора, который может быть оптимизирован изнутри и который хранит в памяти по умолчанию только один объект одновременно.
o7412369815963
Окт. 24, 2011 18:56:43
1-ый вариант медленнее из за того что там на каждой итерации дваждый идет выборка из словаря по ключу x
Enchantner
Окт. 25, 2011 00:30:03
o7412369815963
Не аргумент. Во втором выборка дважды идёт из списка, и то и то выполняется за O(1).
o7412369815963
Окт. 25, 2011 10:09:13
Enchantner
o7412369815963
Не аргумент. Во втором выборка дважды идёт из списка, и то и то выполняется за O(1).
1) Сравните поиск по ключу в словаре из 5М элементов, и выборка из листа в 2 элемента.
2) В 1 варианте выборки из списка что-ли нет?
bw
Окт. 25, 2011 14:06:16
Второй, очевидно, должен быть быстрее; и можно пойти дальше:
>>> for x, (y0, y1) in a.iteritems():
…
Хотя вряд ли это даст хоть сколько либо ощутимый прирост, даже не исключено падение производительности (создаются новые имена в локальном пространстве).
..bw
Enchantner
Окт. 25, 2011 18:32:40
o7412369815963
1) Сравните поиск по ключу в словаре из 5М элементов, и выборка из листа в 2 элемента.
Товарищ, вы знаете, что такое O(1)? Это значит, что выборка из контейнера в общем случае не зависит от количества элементов в нём. В основе списка лежит массив, выборка по индексу (указателю). В основе словаря - хэш-таблица, в которой выборка может затормаживаться коллизиями, которые вряд ли присутствуют в наборе из нескольких элементов.
Но да, согласен, в первом случае идёт двойная выборка.