#python #list-comprehension
#python #понимание списка
Вопрос:
У меня есть небольшой вопрос относительно лучших практик для Python. Я видел, где функции lambda filter использовались вместо понимания списка, но я хотел знать, есть ли более простой способ поиска определенного элемента в списке без необходимости генерировать и повторять по всему списку.
Используя библиотеку AWS boto3, я запрашиваю различные функции get_x (), используя понимание списка:
[i['domainName'] for i in domain_names['items'] if re.search(r'b' domain_name, i['domainName'])].pop()
[i['id'] for i in usage_plans['items'] if i['name']==f'{self.service}Usage'].pop()
Если элемент не найден, ошибка IndexError будет зафиксирована и передана обратно пользователю. Поскольку это в функции AWS Lambda, я беспокоюсь о масштабируемости и выставлении счетов во время выполнения функции.
Должен ли я продолжать использовать понимание списка так, как я собираюсь это сделать, или есть способ получше?
Комментарии:
1. Вы всегда можете пойти императивным путем и просто записать функцию.
2. Определенно, но я просто не знал, есть ли быстрый и одноразовый способ сделать это.
Ответ №1:
Если вы хотите избежать перебора всего списка, вы можете использовать понимание генератора вместо понимания списка. Например:
next(i for i in range(0, 2**1000) if i % 2 == 1)
Перебор всего этого диапазона займет некоторое время, но при использовании понимания генератора это происходит мгновенно.
Обратите внимание, что если он не находит элемент, вы получаете StopIteration
исключение вместо IndexError
. Вы действительно должны перехватить это и включить в другое исключение, потому что ошибка, StopIteration
распространяющаяся по стеку, может вызвать странное поведение.
Перенос StopIteration
выглядит следующим образом:
>>> try:
... next(i for i in range(0, 100) if i % 2 == 3 )
... except StopIteration:
... raise IndexError("Couldn't find item")
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
StopIteration
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
IndexError: Couldn't find item
Обратите внимание, что вы можете указать next
значение по умолчанию для возврата вместо увеличения StopIteration
:
>>> print(next((i for i in range(0, 100) if i % 2 == 3), None))
None
Комментарии:
1. Этот последний комментарий заслуживает 10 голосов «за», время, которое я однажды потратил на отладку цикла, который таинственным образом завершился раньше, потому что какая-то совершенно не связанная функция next() глубоко в стеке вызовов не перехватила его…
2. Честно говоря, именно поэтому я люблю stackoverflow. Спасибо cha0site, я, скорее всего, приму это как ответ, но я собираюсь оставить его открытым еще немного. Я определенно ценю ответ!
3. Быстрый вопрос по этому поводу, хотя, как бы вы обернули
StopIteration
исключение?4. @ThomasTaylor: Я добавил некоторую информацию об этом.
5. Я принял ваш ответ. Большое спасибо за ваше время @cha0site