Автостопом по Python | страница 45
Используйте оператор списка Python * для того, чтобы создать список, состоящий из одинаковых неизменяемых элементов:
>>>> four_nones = [None] * 4
>>>> print(four_nones)
>[None, None, None, None]
Одинаковые объекты должны иметь одинаковые значения хэша. В документации к Python содержится более подробная информация.
Однако будьте осторожны при работе с изменяемыми объектами: поскольку списки изменяемы, оператор * создаст список, состоящий из N ссылок на него самого, и это вряд ли вас устроит. Поэтому используйте списковое включение:
Плохой код | Хороший код |
---|---|
>>>> four_lists = [[]] * 4 | >>>> four_lists = [[] for __ in range(4)] |
>>>> four_lists[0].append("Ni") | >>>> four_lists[0].append("Ni") |
>>>> print(four_lists) | >>>> print(four_lists) |
>[['Ni'], ['Ni'], ['Ni'], ['Ni']] | >[['Ni'], [], [], []] |
Распространенная идиома для создания строк состоит в том, чтобы использовать функцию str.join() для пустой строки. Данная идиома может быть применена к спискам и кортежам:
>>>> letters = ['s', 'p', 'a', 'm']
>>>> word = ''.join(letters)
>>>> print(word)
>spam
Иногда требуется выполнить поиск по коллекции элементов. Изучим два варианта: списки и множества.
Для примера рассмотрим следующий код:
>>>> x = list(('foo', 'foo', 'bar', 'baz'))
>>>> y = set(('foo', 'foo', 'bar', 'baz'))
>>>>
>>>> print(x)
>['foo', 'foo', 'bar', 'baz']
>>>> print(y)
>{'foo', 'bar', 'baz'}
>>>>
>>>> 'foo' in x True
>>>> 'foo' in y True
Даже несмотря на то что обе булевых проверки на наличие в списке и множестве выглядят идентично, а foo in y учитывает тот факт, что множества (и словари) в Python являются хэш-таблицами[40], производительность для этих двух примеров будет различной. Python должен пройти по каждому элементу списка в поисках совпадения, на что уходит много времени (это заметно при увеличении размера коллекций). Но поиск ключей во множестве может быть выполнен быстро с помощью поиска по хэшу. Кроме того, множества и словари не могут содержать повторяющихся записей и идентичных ключей. Для получения более подробной информации поинтересуйтесь семинаром на эту тему на ресурсе Stack Overflow (http://stackoverflow.com/questions/513882).
Зачастую блоки try/finally используются для управления ресурсами вроде файлов или блокировок потоков в случае генерации исключений. В PEP 343 (https://www.python.org/dev/peps/pep-0343/) представлены оператор with и протокол управления контекстом (в версиях 2.5 и выше) — идиома, позволяющая заменить блоки try/finally на более читаемый код. Протокол состоит из двух методов, __enter__() и __exit__(), которые при реализации для объекта позволяют использовать этот объект в операторе with, например так: