суббота, 1 февраля 2020 г.

ЛМНты Python, 41 - 45

>>> Генератор

Объект-генератор можно создать не только с помощью генераторного выражения, но и с помощью функции с предложением yield внутри:

>>> def down5():
...     n = 5
...     while n:
...         yield n
...         n -= 1
...
>>> type(down5)
<class 'function'>
>>> d5 = down5()
>>> type(d5)
<class 'generator'>

Получим итератор из объекта-генератора и последовательно выберем все его значения:

>>> it = iter(d5)
>>> next(it)
5
>>> next(it)
4
>>> next(it)
3
>>> next(it)
2
>>> next(it)
1
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Генератор "израсходовал" свои значения, и повторно полученный итератор оказывается пуст:

>>> it = iter(d5)
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

>>> Ещё включения

Списковое включение оказалось настолько удобной конструкцией, что со временем спровоцировало появление в Python множественного включения (set comprehension) и словарного включения (dictionary comprehension). Множественное включение порождает множество из итерируемого объекта:

>>> {x for x in range(5)}
{0, 1, 2, 3, 4}
>>> {x**2 for x in range(5) if x%2}
{1, 9}
>>> {(x, y) for x in [0, 1] for y in [7, 8]}
{(1, 8), (0, 8), (0, 7), (1, 7)}
>>> {x for x in (1, 2, 3, 2, 1)}
{1, 2, 3}

Словарное включение порождает словарь:

>>> alp = ('a', 'b')
>>> num = (1, 2, 3)
>>> {k: v for k in alp for v in num}
{'a': 3, 'b': 3}
>>> {k: v for k, v in enumerate(alp)}
{0: 'a', 1: 'b'}

>>> Пространства имен

Python работает с тремя видами пространств имен: встроенным (builtin), глобальным (global) и локальным (local). Встроенное связано с модулем builtins, глобальное – с текущим модулем, код которого выполняется в настоящий момент, и локальное – с текущей выполняемой функцией.

В интерактивном сеансе работы с Python текущим модулем является __main__, а модуль builtins неявно автоматически импортирован под именем __builtins__. При работе на уровне модуля (а не внутри функции), глобальное и локальное пространства имен совпадают:

>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>
, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>
, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
>>> locals() is globals()
True

>>> Python ищет

Функции locals() и globals() возвращают словари с именами, определенными в соответствующем пространстве имен. Эти функции, как и другие встроенные функции Python, определены в модуле builtins:

>>> locals is __builtins__.locals
True
>>> globals is __builtins__.globals
True
>>> print is __builtins__.print
True
>>> len is __builtins__.len
True

Python ищет имя, встретившееся в коде, в такой последовательности:

  1. текущее локальное пространство имен,
  2. объемлющее локальное постранство имен (таких может быть несколько, в зависимости от вложенности определения функции),
  3. глобальное пространство имен,
  4. и, наконец, встроенное пространство имен.

>>> Глобальное имя

Имя x из глобального пространства имен доступно изнутри функции:

>>> x = 'global x'
>>>
>>> def fun():
...     print(locals())
...     print(x)
...
>>> fun()
{}
global x
>>> print(x)
global x

Операция присваивания внутри функции создает в локальном пространстве имен новое имя x, которое экранирует глобальное x:

>>> x = 'global x'
>>>
>>> def fun():
...     x = 'local x'
...     print(locals())
...     print(x)
...
>>> fun()
{'x': 'local x'}
local x
>>> print(x)
global x

Чтобы предотвратить создание нового имени x операцией присваивания, нужно внутри функции объявить имя x глобальным:

>>> x = 'global x'
>>>
>>> def fun():
...     global x
...     x = 'still global x'
...     print(locals())
...     print(x)
...
>>> fun()
{}
still global x
>>> print(x)
still global x

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

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