Основные понятия Python3x - пространство имён

Jazz

Опубликован:  2023-09-12T06:19:25.053697Z
Отредактирован:  2023-09-12T06:19:25.053697Z
Статус:  публичный
14
0
0

Во втором эпизоде встречи с современным языком программирования Python3x я попытаюсь раскрыть один из основополагающих терминов теории программирования на Питоне - namespace (пространство имён), расскажу, что это такое, как его создать, как создавать в нём объекты, покажу некоторые ключевые процедуры, с помощью которых в Python3x можно такое действие осуществить. Кроме этого, я сосредоточу пристальное внимание на сущности объектов в Python3x, их отличительных особенностях и некоторых характерных для Питона способах и приёмах взаимодействия с ними. Будет интересно... Поиграем?

О пространстве имён

Пространство имён - это основополагающее понятие в теории программирования, и в частности, программирования на Питоне. Разрабатывая ту или иную программу, мы создаём пространства имён, наполняем их объектами, определяем возможности взаимодействия с этими объектами, в том числе возможности взаимодействия объектов друг с другом, в результате чего и получается готовая программа.

Существуют три основных типа пространств имён, из которых и состоит программа, написанная на Питоне, следует их перечислить:

  1. Модуль;

  2. Класс;

  3. Функция;

В рамках этой демонстрации я подробно остановлюсь на перовом типе пространств имён - модуле.

В теории программирования на Python3 у любого пространства имён есть две ипостаси. Применительно к модулю, первая ипостась пространства имён - это текст модуля, его исходный код. Да, именно создаваемый программистом в процессе разработки программы текстовый файл, с расширением .py, и есть то самое пространство имён типа модуль. Вторая ипостась пространства имён проявляется в момент, когда компьютер исполняет программу. Программу на Питоне исполняет интерпретатор Python3x. И в момент исполнения программы интерпретатор читает текст исполняемого модуля и адекватно этому тексту создаёт в оперативной памяти компьютера обособленную область, а уже в этой области создаёт определённые в коде этого модуля объекты.

Делаем вывод, пространство имён типа модуль - это код исполняемого модуля и соответствующая этому коду обособленная область оперативной памяти компьютера, в которой в процессе исполнения программы хранятся определённые в коде исполненного модуля объекты. Код пишет программист, область оперативной памяти создаёт интерпретатор в момент исполнения написанного программистом кода, и вместе это называется пространством имён.

Создаём пространство имён

В рамках этой демонстрации я буду говорить о пространстве имён типа модуль. Создать такое пространство имён можно двумя способами:

  1. Созданием текстового файла с расширением .py и редактированием кода в рамках этого файла, детально процесс описан на примере программирования простой игры в кости в одном из предыдущих выпусков этого блога, ссылку я давал чуть выше;

  2. Запуском интерактивной сессии интерпретатора 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.

FfZ5qk8GYt.png

Природа объектов 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 в моём терминале.

frGE7I3Eik.png

На что здесь следует обратить внимание... Когда я обратился по имени к объекту player в самом начале сессии, этот объект ещё не существовал в пространстве имён, интерпретатор откликнулся исключением. Но на вызовы функций dir, type и isinstance он реагировал иначе, хотя я в текущем пространстве имён никаких объектов с этими именами не создавал. Откуда они взялись?

Давайте ещё раз посмотрим на вызов функции dir.

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'player']
>>>

6jTxq2DeeF.png

В возвращаемом этим вызовом списке имён, хранящихся в текущем пространстве имён объектов, есть имя __builtins__. То есть, можно сказать, что __builtins__ это объект, а это значит, что мы можем увидеть его тип.

>>> type(__builtins__)
<class 'module'>
>>>

Модуль. При помощи всё той же функции dir можно увидеть список хранящихся в этом модуле объектов. Весь выхлоп интерпретатора на этот вызов показывать не буду, он слишком длинный, покажу только форму вызова функции dir. При желании, каждый может воспроизвести этот вызов самостоятельно.

>>> dir(__builtins__)

В возвращаемом этим вызовом списке имён можно найти использованные в этой демонстрации функции dir, type и isinstance - это определённые в модуле __builtins__ объекты. Ларчик открылся...

Builtins - это основополагающий модуль стандартной библиотеки Питона, в котором определены все базовые типы, исключения, функции и константы. Изучение языка программирования на начальных этапах сводится именно к изучению определённых в этом модуле объектов. Исчерпывающую документацию по стандартной библиотеке Питона можно получить на соответствующей странице официального сайта сообщества разработчиков Python. Можно сказать, что знание языка программирования Python3 сводится к знанию его синтаксиса и стандартной библиотеки. Объём стандартной библиотеки Питона впечатляет. И я не знаю... Можно ли вообще знать Python3x? Но точно знаю, что им можно очень великолепно пользоваться и решать с его помощью разные полезные, простые и сложные пользовательские компьютерные задачи, каждый раз при этом обращаясь к документации, и именно так и только так этот язык программирования можно и, наверное, нужно изучать.

Заключение

В рамках небольшой статьи Интернет блога невозможно объять необъятное. Будем считать, что цель этой демонстрации достигнута, я разобрал основополагающее для Питона понятие пространства имён, показал некоторые приёмы работы в интерактивном режиме интерпретатора и форму некоторых ключевых процедур Python3x. В ближайших выпусках этого блога я планирую более детально описать больше процедур этого языка программирования и поделиться собственным опытом его изучения. Кому интересно, оставайтесь с нами, подписывайтесь, ставьте лайки, дизлайки, как без них, задавайте вопросы. Будем приручать Питона вместе...

Выводы и умозаключения

  1. Namespace (пространство имён) - основополагающее понятие в теории программирования на Python3x, различаются три типа пространств имён: модуль, класс и функция. Пространство имён - это с одной стороны исходный код написанный программистом, с другой - это обособленная область оперативной памяти компьютера, в которой создаются описанные в исходном коде объекты.

  2. Python3x является объектно ориентированным языком программирования, это значит, что любая сущность определённая в пространстве имён является объектом, то есть экземпляром базового класса object.

  3. У каждого объекта в пространстве имён есть имя и возвращаемое значение. Значение объекта можно получить, обратившись к объекту по имени. Не все объекты в пространстве имён равнозначны, в этом смысле объекты различают по категориям: константы, переменные, функции, классы, модули. Тип объекта можно определить с помощью встроенной функции type, типом объекта определяется и то, к какой категории этот объект относится.

  4. Python3x имеет динамическую типизацию, это значит, что определённые в пространстве имён объекты в рамках одной программы могут менять свой тип в зависимости от присвоенного им значения.