Понимание списков может быть полезно в определенных ситуациях, но также может быть довольно ужасным для чтения .. В качестве слегка преувеличенного примера, как бы вы сделали отступ в следующем?
allUuids = [x.id for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) if x.type == "post" and x.deleted is not False]






Как насчет:
allUuids = [x.id for x in self.db.query(schema.allPostsUuid).execute(timeout = 20)
if (x.type == "post" and x.deleted is not False)]
Как правило, длинных строк можно избежать, предварительно вычислив подвыражения в переменных, что может привести к незначительным потерям производительности:
query_ids = self.db.query(schema.allPostsUuid).execute(timeout = 20)
allUuids = [x.id for x in query_ids
if (x.type == "post" and x.deleted is not False)]
Кстати, разве is not False не лишний? Вы беспокоитесь о различии между None и False? Потому что в противном случае достаточно оставить только условие: if (x.type == "post" and x.deleted)
Согласен, но правила синтаксиса Python часто поощряют / заставляют строки становиться длиннее. Его обработка пробелов в целом - это моя единственная жалоба на язык.
Благодаря тщательно подобранным переменным и разделению строк скобками или скобками мне никогда не приходилось прибегать к слишком длинным строкам (чаще проблема заключается в том, чтобы избежать self.long_foo.very_long_bar.baz (....) с использованием временных библиотек)
Насчет «Между прочим», это не совсем лишнее, например, случай x.deleted = None.
Для меня это уже слишком. Возможно, это просто ужасный пример, поскольку «тип» и «удаленный» явно будут частью запроса к базе данных.
Я склонен думать, что если понимание списка занимает несколько строк, оно, вероятно, не должно быть пониманием списка. Сказав это, я обычно просто разделяю это на «если», как и другие люди, и отвечу здесь.
Это зависит от того, сколько они длинны. Я стараюсь структурировать их так:
[x.id for x
in self.db.query(schema.allPostsUuid).execute(timeout=20)
if x.type == 'post'
and x.deleted is not False
and ...
and ...]
Таким образом, у каждого выражения будет своя линия.
Если какая-либо строка становится слишком большой, мне нравится извлекать ее с помощью лямбда или выражения:
transform = lambda x: x.id
results = self.db.query(schema.allPostsUuid).execute(timeout=20)
condition = lambda x: x.deleted is not False and ... and ...
[transform(x) for x in results if condition(x)]
А затем, если лямбда становится слишком длинной, она превращается в функцию.
они НЕ эквивалентны - понимание списка происходит во много раз быстрее, так как не требуется выполнять поиск функций. соответствующий перевод будет использовать для циклов.
За исключением падения производительности, это очень читаемый пример!
Как циклы for предотвратят поиск функции? Также обратите внимание, что цикл в понимании списков реализован в C и, следовательно, быстрее, чем простой.
Просто примечание - вы можете использовать несколько операторов if вместо многократного использования «и». Этакая забавная синтаксическая правда.
Не все, кто использует Python, являются специалистами по данным или занимаются машинным обучением, поэтому для обычных людей, которые просто работают с ответами от API, в которых содержится всего несколько 100 элементов, вторая версия подойдет. Однако я все же предпочитаю первый.
Там, где я работаю, наши правила кодирования требуют от нас сделать что-то вроде этого:
all_posts_uuid_query = self.db.query(schema.allPostsUuid)
all_posts_uuid_list = all_posts_uuid_query.execute(timeout=20)
all_uuid_list = [
x.id
for x in all_posts_uuid_list
if (
x.type == "post"
and
not x.deleted # <-- if you don't care about NULLs / None
)
]
allUuids = [x.id
for x in self.db.query(schema.allPostsUuid).execute(timeout = 20)
if x.type == "post" and x.deleted is not False]
Вы не должны использовать для этого понимание списка.
Понимание списков - отличная функция, но они предназначены для использования в качестве ярлыков, а не обычного кода.
Для такого длинного сниппета следует использовать обычные блоки:
allUuids = []
for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) :
if x.type == "post" and x.deleted is not False :
allUuids.append(x.id)
Точно такое же поведение, гораздо более читабельное. Гвидо гордился бы тобой :-)
это немного медленнее, так как вам нужно строить массив шаг за шагом
Я думаю, что понимание списка делает то же самое под капотом. Это одноразовая операция не потому, что это однострочное выражение ...
e-statis: функция та же, но понимание списков может быть значительно быстрее
Хм, у меня нет времени тестировать его, так что придется поверить тебе на слово :-) Но в любом случае удобочитаемость имеет большее значение, чем скорость в Python ...
В культуре Python вы обычно предпочитаете удобочитаемость скорости. В любом случае Python - не быстрый язык ...
Таким образом используется изменчивый нефункциональный стиль. Неизменяемость позволяет мыслить в терминах отображения и фильтрации. В этом коде список изменен, и читатель должен иметь в виду, что он может быть изменен впоследствии. Лучше заставить генератор работать с yield, чем это, или ввести новые переменные и функции.
Если вы настроены на понимание, ответ Орестиса - это хорошо.
Для более сложных представлений я бы предложил использовать генератор с yield:
allUuids = list(self.get_all_uuids())
def get_all_uuids(self):
for x in self.db.query(schema.allPostsUuid).execute(timeout = 20):
if x.type == "post" and x.deleted is not False:
yield x.id
Я поддерживаю это. Как правило, на всех языках следует избегать строк, содержащих более 80 символов.