Приручаем Питона, эпизод второй
Jazz
Опубликован: | 2023-09-12T06:19:25.053697Z |
Отредактирован: | 2023-09-12T06:19:25.053697Z |
Статус: | публичный |
Во втором эпизоде встречи с современным языком программирования Python3x я попытаюсь раскрыть один из основополагающих терминов теории программирования на Питоне - namespace (пространство имён), расскажу, что это такое, как его создать, как создавать в нём объекты, покажу некоторые ключевые процедуры, с помощью которых в Python3x можно такое действие осуществить. Кроме этого, я сосредоточу пристальное внимание на сущности объектов в Python3x, их отличительных особенностях и некоторых характерных для Питона способах и приёмах взаимодействия с ними. Будет интересно... Поиграем?
О пространстве имён
Пространство имён - это основополагающее понятие в теории программирования, и в частности, программирования на Питоне. Разрабатывая ту или иную программу, мы создаём пространства имён, наполняем их объектами, определяем возможности взаимодействия с этими объектами, в том числе возможности взаимодействия объектов друг с другом, в результате чего и получается готовая программа.
Существуют три основных типа пространств имён, из которых и состоит программа, написанная на Питоне, следует их перечислить:
-
Модуль;
-
Класс;
-
Функция;
В рамках этой демонстрации я подробно остановлюсь на перовом типе пространств имён - модуле.
В теории программирования на Python3 у любого пространства имён есть две ипостаси. Применительно к модулю, первая ипостась пространства имён - это текст модуля, его исходный код. Да, именно создаваемый программистом в процессе разработки программы текстовый файл, с расширением .py
, и есть то самое пространство имён типа модуль. Вторая ипостась пространства имён проявляется в момент, когда компьютер исполняет программу. Программу на Питоне исполняет интерпретатор Python3x. И в момент исполнения программы интерпретатор читает текст исполняемого модуля и адекватно этому тексту создаёт в оперативной памяти компьютера обособленную область, а уже в этой области создаёт определённые в коде этого модуля объекты.
Делаем вывод, пространство имён типа модуль - это код исполняемого модуля и соответствующая этому коду обособленная область оперативной памяти компьютера, в которой в процессе исполнения программы хранятся определённые в коде исполненного модуля объекты. Код пишет программист, область оперативной памяти создаёт интерпретатор в момент исполнения написанного программистом кода, и вместе это называется пространством имён.
Создаём пространство имён
В рамках этой демонстрации я буду говорить о пространстве имён типа модуль. Создать такое пространство имён можно двумя способами:
-
Созданием текстового файла с расширением
.py
и редактированием кода в рамках этого файла, детально процесс описан на примере программирования простой игры в кости в одном из предыдущих выпусков этого блога, ссылку я давал чуть выше; -
Запуском интерактивной сессии интерпретатора Python3x.
Второй способ интересно рассмотреть в деталях. Для этого запускаю терминал и в нём выполняю такую команду.
$ python3
Терминал отзовётся следующим выхлопом:
Python 3.11.5 (main, Aug 29 2023, 15:31:31) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
В последней строке выхлопа располагаются три угловые скобки, и следом за ними курсор ввода - это приглашение интерпретатора, пользователь может ввести любую процедуру Python3x, нажать enter
и получить отклик, интерактивный отклик интерпретатора. Что происходит с той стороны экрана? В момент запуска интерактивной сессии Python3x создаёт в оперативной памяти обособленную область - эту область мы и называем пространством имён, подгружает в эту область некоторые обязательные для модуля Python объекты и ожидает пользовательского ввода, чтобы в соответствии с введёнными пользователем процедурами создать в этом пространстве имён новые объекты или получить доступ к уже созданным объектам, их свойствам и методам.
На первый поверхностный взгляд неискушенного пользователя созданное пространство имён не содержит ничего, я же не ввёл пока ни одной процедуры и не создал ни одного объекта. На самом деле это не так, и в только что созданном пространстве имён уже кое-что есть. Содержимое пространства имён можно достаточно просто посмотреть, для этого существует библиотечная функция dir
, и чтобы ей воспользоваться, нужно ввести в приглашении интерактивной сессии следующую процедуру.
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
Процедура эта называется вызовом функции. В результате такой процедуры исполняется код, хранящийся в теле вызываемой функции, и интерпретатор выводит полученное в результате исполнения этого кода значение, это значение называют возвращаемым функцией значением.
Как видно из выхлопа, интерпретатор в результате вызова функции dir
вывел на экран список имён хранящихся в текущем пространстве имён, для этого модуля оно является глобальным, объектов. К каждому объекту в пространстве имён можно обратиться по его имени. Как мы видим, в полученном списке отсутствует объект с именем player
- нет такого объекта в текущем пространстве имён. Давайте посмотрим, как отреагирует интерпретатор, если обратиться по имени к несуществующему объекту.
>>> player
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'player' is not defined
>>>
Как видно, в ответ на ввод пользователем этой процедуры интерпретатор попытался найти в текущем пространстве имён объект с именем player
, не нашёл и ответил нам таким великолепным выхлопом. Такой выхлоп принято называть исключением, или причиной ошибки, в последней строчке выхлопа указано имя ошибки и причина ошибки: имя player
не определено. Коммуникация состоялась. Не сложно догадаться, что если бы мы исполнили модуль, содержащий такую процедуру, не в интерактивном режиме интерпретатора, то на этой процедуре исполнение программы и завершилось бы ошибкой.
Создаём объекты в пространстве имён
Создавать объекты в пространстве имён Python3x можно с помощью различных процедур. В рамках этой демонстрации я покажу только одну, она называется инициализацией переменной. Для инициализации переменной мне нужно задать имя переменной и присвоить этой переменной какое-то значение. Давайте создадим переменную с именем player
.
>>> player = 'Jazz'
>>>
Как видно, интерпретатор принял и распарсил введённую в приглашении процедуру, о чём свидетельствует появившееся в выхлопе интерпретатора новое приглашение. Что произошло с той стороны экрана? В текущем пространстве имён создан новый объект с именем player
и значением 'Jazz'
, то есть, в обособленной области оперативной памяти создан новый объект. Если повторно вызвать функцию dir
, мы увидим, что в возвращаемом ей списке имён появилось новое имя - player
.
Природа объектов Python3x
Язык программирования Python3x является объектно ориентированным, это значит, что всё, что создаёт программист во всех пространствах имён, является объектом. Давайте раскроем понятие объекта.
В Питоне объект имеет две ипостаси. Первая - это хранящийся в оперативной памяти физический объект, представленный в форме бинарных данных. Вторая - это экземпляр библиотечного базового класса object
. Имя объекта - это привязка к физическому объекту в области оперативной памяти компьютера, которую мы называем пространством имён. К каждому объекту в пространстве имён можно обратиться по имени. Давайте обратимся к только что созданному объекту player
посмотрим, как на это отреагирует интерпретатор.
>>> player
'Jazz'
>>>
Как видно, интерпретатор вернул нам хранящееся в объекте в области оперативной памяти значение, к которому привязано имя player
. Мы обратились к объекту по имени. Делаю вывод, у каждого объекта в пространстве имён есть имя и значение. Кроме этого у каждого объекта в пространстве имён есть ещё и тип. Тип объекта можно увидеть вводом процедуры вызова библиотечной функции type
, вот такую форму эта процедура будет иметь для объекта player
в текущем пространстве имён.
>>> type(player)
<class 'str'>
>>>
Как видно из выхлопа, интерпретатор вывел на экран тип переменной player
, в данном случае это класс str
. А действительно ли, что player
является объектом? Давайте убедимся, для этого нам потребуется ещё одна библиотечная функция - isinstance
.
>>> isinstance(player, object)
True
>>>
Интерпретатор вернул по запросу True
, действительно, только что созданная переменная player
является объектом.
О динамической типизации
Тип только что созданной переменной player
не является статическим и может изменяться в зависимости от типа присвоенной этой переменной значения. Вот как это можно воспроизвести в интерактивной сессии.
>>> player = ['Jazz']
>>>
Как видно из выхлопа, интерпретатор принял эту процедуру и присвоил переменной player
новое значение. По сравнению со старым значением, я изменил только форму записи, добавил прямоугольные скобки в начало и конец значения. И в итоге, тип переменной player
изменился. Давайте убедимся.
>>> type(player)
<class 'list'>
>>>
Вот так всё просто, был класс str
, стал класс list
, а изменилась только форма записи значения. Это свойство объектов Python3x называется динамической типизацией, тип объекта в рамках одного модуля программы может изменяться и зависит от типа присвоенного этому объекту значения. Если сравнивать с другими языками программирования, такими как C, C++, Java, Rust, в них объекты в рамках одной программы не могут менять свой тип, эти языки называют языками со статической типизацией.
О библиотечных функциях
Вот как на текущий момент выглядит интерактивный сеанс интерпретатора Python в моём терминале.
На что здесь следует обратить внимание... Когда я обратился по имени к объекту player
в самом начале сессии, этот объект ещё не существовал в пространстве имён, интерпретатор откликнулся исключением. Но на вызовы функций dir
, type
и isinstance
он реагировал иначе, хотя я в текущем пространстве имён никаких объектов с этими именами не создавал. Откуда они взялись?
Давайте ещё раз посмотрим на вызов функции dir
.
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'player']
>>>
В возвращаемом этим вызовом списке имён, хранящихся в текущем пространстве имён объектов, есть имя __builtins__
. То есть, можно сказать, что __builtins__
это объект, а это значит, что мы можем увидеть его тип.
>>> type(__builtins__)
<class 'module'>
>>>
Модуль. При помощи всё той же функции dir
можно увидеть список хранящихся в этом модуле объектов. Весь выхлоп интерпретатора на этот вызов показывать не буду, он слишком длинный, покажу только форму вызова функции dir
. При желании, каждый может воспроизвести этот вызов самостоятельно.
>>> dir(__builtins__)
В возвращаемом этим вызовом списке имён можно найти использованные в этой демонстрации функции dir
, type
и isinstance
- это определённые в модуле __builtins__
объекты. Ларчик открылся...
Builtins - это основополагающий модуль стандартной библиотеки Питона, в котором определены все базовые типы, исключения, функции и константы. Изучение языка программирования на начальных этапах сводится именно к изучению определённых в этом модуле объектов. Исчерпывающую документацию по стандартной библиотеке Питона можно получить на соответствующей странице официального сайта сообщества разработчиков Python. Можно сказать, что знание языка программирования Python3 сводится к знанию его синтаксиса и стандартной библиотеки. Объём стандартной библиотеки Питона впечатляет. И я не знаю... Можно ли вообще знать Python3x? Но точно знаю, что им можно очень великолепно пользоваться и решать с его помощью разные полезные, простые и сложные пользовательские компьютерные задачи, каждый раз при этом обращаясь к документации, и именно так и только так этот язык программирования можно и, наверное, нужно изучать.
Заключение
В рамках небольшой статьи Интернет блога невозможно объять необъятное. Будем считать, что цель этой демонстрации достигнута, я разобрал основополагающее для Питона понятие пространства имён, показал некоторые приёмы работы в интерактивном режиме интерпретатора и форму некоторых ключевых процедур Python3x. В ближайших выпусках этого блога я планирую более детально описать больше процедур этого языка программирования и поделиться собственным опытом его изучения. Кому интересно, оставайтесь с нами, подписывайтесь, ставьте лайки, дизлайки, как без них, задавайте вопросы. Будем приручать Питона вместе...
Выводы и умозаключения
-
Namespace (пространство имён) - основополагающее понятие в теории программирования на Python3x, различаются три типа пространств имён: модуль, класс и функция. Пространство имён - это с одной стороны исходный код написанный программистом, с другой - это обособленная область оперативной памяти компьютера, в которой создаются описанные в исходном коде объекты.
-
Python3x является объектно ориентированным языком программирования, это значит, что любая сущность определённая в пространстве имён является объектом, то есть экземпляром базового класса
object
. -
У каждого объекта в пространстве имён есть имя и возвращаемое значение. Значение объекта можно получить, обратившись к объекту по имени. Не все объекты в пространстве имён равнозначны, в этом смысле объекты различают по категориям: константы, переменные, функции, классы, модули. Тип объекта можно определить с помощью встроенной функции
type
, типом объекта определяется и то, к какой категории этот объект относится. -
Python3x имеет динамическую типизацию, это значит, что определённые в пространстве имён объекты в рамках одной программы могут менять свой тип в зависимости от присвоенного им значения.