почему этот вопрос?
Я пытался ответить на этот вопрос: Проверьте, существуют ли все значения в виде ключей в словаре с чем-то лучшим, чем сгенерированное понимание генераторана all
(циклы python, даже в пониманиях, замедляют выполнение по сравнению с неявными циклами, выполняемыми некоторыми функциями):
all(i in bar for i in foo)
, где bar
- словарь, а foo
- список с использованиемset.issubset
(с преобразованием в set
из foo
для возможности использования foo.issubset(bar)
), и ему не удалось превзойти времена решения all
(если оба контейнера не были преобразованы в set
s).
мой вопрос:
Из документации set
:
Примечание,неоператорные версии методов union (), intersection (), разности () иmmetric_difference (), issubset () и issperset () примут любую итерацию в качестве аргумента .Напротив, их операторные аналоги требуют, чтобы их аргументы были множествами.Это исключает подверженные ошибкам конструкции, такие как set ('abc') и 'cbs' в пользу более читабельного множества ('abc'). Intersection ('cbs').
Хорошо, но производительностьдействительно зависит от типа аргумента, даже если сложность этого не делает ( Сложность Python issubset () ):
import timeit
foo = {i for i in range(1, 10000, 2)}
bar = foo - {400}
n=10000
x = timeit.timeit(setup="foo = {str(i) for i in range(1, 10000, 2)};bar = foo - {'400'}",stmt="bar.issubset(foo)",number=n)
print("issubset(set)",x)
x = timeit.timeit(setup="foo = {str(i) for i in range(1, 10000, 2)};bar = foo - {'400'};foo=list(foo)",stmt="bar.issubset(foo)",number=n)
print("issubset(list)",x)
x = timeit.timeit(setup="foo = {str(i):i for i in range(1, 10000, 2)};bar = set(foo) - {'400'}",stmt="bar.issubset(foo)",number=n)
print("issubset(dict)",x)
x = timeit.timeit(setup="foo = {str(i):i for i in range(1, 10000, 2)}.keys();bar = set(foo) - {'400'}",stmt="bar.issubset(foo)",number=n)
print("issubset(dict_keys)",x)
мои результаты (Python 3.4):
issubset(set) 1.6141405847648826
issubset(list) 3.698748032058883
issubset(dict) 3.6300025109004244
issubset(dict_keys) 4.224299651223102
Таким образом, если в качестве аргумента передано set
, результат будет очень быстрым.
Использование list
намного медленнее.Я понял, что из-за хэша, который должен быть сделан на строках, это дорого.Поэтому я изменил свои тестовые входные данные с помощью целых чисел, таких как:
foo = {i for i in range(1, 10000, 2)}
bar = foo - {400}
, и результаты были глобально быстрее, но все еще огромная разница во времени:
issubset(set) 0.5981848205989139
issubset(list) 1.7991591232742143
issubset(dict) 1.889119736960271
issubset(dict_keys) 2.2531574114632678
Я также пытался изменить dict
в dict.keys()
, как и в Python 3, ключи называются (https://www.python.org/dev/peps/pep-3106/) «контейнерным или неупорядоченным контейнерным объектом».
Но в этом случае результат будет еще хуже, чем приdict
или list
.
Так почему же прохождение set
бьется при прохождении list
или dict
или dict_keys
объекта? Не знаюсм. что-либо упомянутое в документации об этом.