>>> Генератор
Объект-генератор можно создать не только с помощью генераторного выражения, но и с помощью функции с предложением 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 ищет имя, встретившееся в коде, в такой последовательности:
- текущее локальное пространство имен,
- объемлющее локальное постранство имен (таких может быть несколько, в зависимости от вложенности определения функции),
- глобальное пространство имен,
- и, наконец, встроенное пространство имен.
>>> Глобальное имя
Имя 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
Комментариев нет:
Отправить комментарий