вторник, 1 декабря 2020 г.

ЛМНты Python, 91 - 95

>>> Две или больше, the Python way

Чтобы перебрать все элементы последовательности, делается цикл по элементам последовательности:

>>> letters = ['a', 'b', 'c']
>>> for x in letters:
...     pass
...

Если нужно параллельно перебирать элементы нескольких последовательностей, то прибегают к индексированию:

>>> numbers = [1, 2, 3]
>>> for i in range(len(letters)):
...     letter = letters[i]
...     number = numbers[i]
...

Но у Python есть свое решение для параллельного перебора элементов нескольких последовательностей – функция zip:

>>> for c, n in zip(letters, numbers):
...     print(c, n)
...
a 1
b 2
c 3

См. также лмнт Две или больше.

>>> Стильные подчеркивания

Согласно PEP8, символ подчеркивания добавляется в начало или конец имени в следующих целях:

  • _single – одинарное ведущее подчеркивание указывает на то, что имя используется для внутренних нужд. См. примеры в предыдущих лмнтах.
  • single_ – одинарное конечное подчеркивание рекомендовано для избегания конфликтов с ключевыми словами языка, например: class_, lambda_. Лучше подчеркивание в конце имени, чем искажение слова.
  • __double – двойное ведущее подчеркивание изменяет ("запутывает") имя атрибута класса во избежание конфликтов имен при наследовании. Например, имя __var в исходном коде класса Hello превращается в имя _Hello__var.
  • __double__ – двойные подчеркивания в начале и в конце имени используются для "магических" методов или атрибутов, например: __init__, __all__ или __name__. Такие имена предопределены в языке.

>>> zip и zip_longest

Если два итерируемых объекта, переданных функции zip, содержат разное количество элементов, то zip работает, пока не кончатся элементы в самом коротком из них:

>>> chars = ['a', 'b', 'c', 'd']
>>> nums = [1, 2, 3]
>>> for c, n in zip(chars, nums):
...     print(c, n)
...
a 1
b 2
c 3

Получить столько пар, сколько элементов в самом длинном итерируемом объекте, поможет функция zip_longest из модуля itertools.

>>> from itertools import zip_longest
>>> for c, n in zip_longest(chars, nums):
...     print(c, n)
...
a 1
b 2
c 3
d None

Опционально, можно указать значение для заполнения недостающих элементов:

>>> pairs = zip_longest(chars, nums, fillvalue=-1)
>>> for c, n in pairs:
...     print(c, n)
...
a 1
b 2
c 3
d -1

>>> Распаковка итератора

Распаковка работает не только при передаче последовательности в функцию, когда параметрам функции присваиваются элементы последовательности:

>>> def fun(a, b, c):
...     print(a, b, c)
...
>>> names = ['Маш', 'Даш', 'Саш']
>>> fun(*names)
Маш Даш Саш

Распаковать можно также любой итератор для создания списка:

>>> pairs = [*enumerate(names)]
>>> print(pairs)
[(0, 'Маш'), (1, 'Даш'), (2, 'Саш')]
>>>
>>> names = [*map(str.upper, names)]
>>> print(names)
['МАШ', 'ДАШ', 'САШ']
>>>
>>> nums = [*range(3)]
>>> print(nums)
[0, 1, 2]

>>> Что быстрее

Создание списка распаковкой итератора оказывается несколько быстрее, чем передача итератора в list():

>>> from timeit import timeit
>>>
>>> timeit('list(range(100))')
0.7239164000000073
>>>
>>> timeit('[*range(100)]')
0.6466859000000227

А создание пустого списка при помощи литерала оказывается в разы быстрее создания списка при помощи list()`:

>>> timeit('a = []')
0.01667399999999475
>>>
>>> timeit('a = list()')
0.05548450000000571

Комментариев нет:

Отправить комментарий