Насколько эффективен (в) эффективный список, если вы его не назначили?
В этом вопросе у меня есть аргумент с комментатором, который утверждает, что
for t in threads:
t.join()
будет лучше, чем
[t.join() for t in threads]
Оставляя в стороне вопрос о "злоупотреблении пониманием" - я склонен согласиться, но я хотел бы сделать однострочный для этого: насколько эффективна моя версия (вторая)? Является ли Python материализовыванием списков всегда/в моем случае или он использует внутренний генератор?
Будет ли map(lambda t: t.join(), threads)
более эффективным? Или есть другой способ применить функцию к каждому элементу в списке threads
?
Ответы
Ответ 1
Понимание списка всегда будет создавать объект списка, в этом случае с возвращаемыми значениями всех вызовов t.join()
. Таким образом, Python создает для вас список с None
значениями длины len(threads)
. Python никогда не попытается оптимизировать создание объекта списка.
Использование map()
также не является более эффективным, поскольку вы добавляете дополнительные стоп-сигналы с помощью lambda
. Просто придерживайтесь явного цикла for
.
Действительно, для серии соединений нитей нет точки при попытке микро-оптимизации здесь.
У вас болит читаемость для некритического кода.
Другими словами, я полностью согласен с комментатором. Не используйте понимание списка или map()
только для побочных эффектов и сохраняйте себя, чтобы попасть в ENTER и создать две строки кода.
Цитирование Zen of Python:
- Показатели удобочитаемости.
Ответ 2
Если вы хотите использовать один слой для этого, напишите функцию выхлопа и используйте его в сочетании с выражением генератора:
def exhaust(iterator):
for _ in iterator:
pass
exhaust(t.join() for t in threads)
Затем вы не оплачиваете стоимость всего хранилища списка.
Невозможно переименовать exhaust
что-то более быстрое или релевантное для вашего использования.
Я часто видел это злоупотребление списком, даже в интервью, где мы явно давали указания кандидатам избегать неограниченного роста памяти при решении проблемы.
Ответ 3
Вы можете сделать foreach, который работает так, как вы хотите. Я бы рекомендовал против этого, так как это не обычный способ python делать вещи. Непроверенный, но по строкам:
class foreach:
def __init__(self, object_list):
self.__object_list = object_list
def __getattr__(self, name):
def f(*args, **kwargs):
for obj in self.__object_list:
getattr(obj, name)(*args, **kwargs)
return f
foreach(thread_list).join()
Он в значительной степени создает своего рода прокси-объект, который пересылает любой вызов с любыми параметрами ко всем объектам.
(Скорее всего, у меня будет хороший чат, если вы это сделаете в моей команде разработчиков, но это служит примером того, что возможно в python)
Ответ 4
Если вам нужен однострочный шрифт, почему бы просто не сделать for t in threads: t.join()
?
Похоже, это самое простое решение для меня и, вероятно, будет самым быстрым (хотя на самом деле накладные расходы на объединение потоков, скорее всего, будут затмевать что-нибудь еще IMO)