Исследует пространства имен и то, как Python использует их для улучшения кода.

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

Как и во многих языках программирования, Python изолирует код с помощью концепции пространств имен. Во время работы программа отслеживает все известные пространства имен и информацию, доступную в этих пространствах имен.

Пространства имен полезны несколькими способами:

  • По мере роста программного обеспечения нескольким концепциям требуются одинаковые или идентичные имена.
  • Пространства имен помогают минимизировать коллизии, давая понять, к какой концепции относится каждое имя.
  • По мере роста программного обеспечения становится экспоненциально сложнее узнать, какой код уже находится в кодовой базе. Пространства имен помогают вам делать обоснованные предположения о том, где может находиться код, если он существует.
  • При добавлении нового кода в большую базу кода существующие пространства имен могут указывать, где должен располагаться новый код. Если очевидного выбора нет, может быть подходящим новое пространство имен.

Пространства имен настолько важны, что они включены в качестве последнего утверждения в Zen of Python (если вы не знакомы с Zen of Python, попробуйте запустить интерпретатор Python и ввести import this).

"Пространства имен - отличная идея, давайте сделаем еще их!" - Дзен Python

Все переменные, функции и классы, которые вы когда-либо использовали в Python, имели имена в том или ином пространстве имен. Имена - это такие вещи, как x, total или EssentialBusinessDomainObject, которые относятся к чему-то.

Когда в вашем коде Python указано x = 3, это означает «присвоить значение 3 имени x», после чего вы можете ссылаться на x в своем коде.

Слово «переменная» используется взаимозаменяемо с именами, которые относятся к значениям, хотя имена могут относиться к функциям, классам и многому другому в Python.

Пространства имен и I mport Заявление

Когда вы впервые открываете интерпретатор Python, встроенное пространство имен заполняется всем, что встроено в Python. Встроенное пространство имен Python содержит встроенные функции, такие как print() и open().

У этих встроенных модулей нет префикса, и вам не нужно делать ничего особенного для их использования. Python делает их доступными в любом месте вашего кода. Вот почему известная простота print('Hello world!') Just Works ™ на Python.

В отличие от некоторых языков, вы не можете явно создавать пространства имен в своем коде Python, но ваша структура кода влияет на то, какие пространства имен создаются и как они взаимодействуют.

Например, при создании модуля Python автоматически создается дополнительное пространство имен для этого модуля. В простейшем случае модуль Python представляет собой .py файл, содержащий некоторый код.

Например, файл с именем sales_tax.py - это «модуль sales_tax»:

# sales_tax.py
  
 def add_sales_tax(total, tax_rate):
     return total * tax_rate

Каждый модуль имеет глобальное пространство имен, к которому код в модуле имеет свободный доступ. Функции, классы и переменные, которые ни во что не вложены, находятся в глобальном пространстве имен модуля:

TAX_RATES_BY_STATE находится в глобальном пространстве имен модуля.

❷ Код в модуле может без проблем использовать TAX_RATES_BY_STATE.

Функции и классы в модуле также имеют локальное пространство имен, доступ к которому имеют только они:

tax_rate находится только в локальной области для add_sales_tax().

❷ Код в add_sales_tax() можно без проблем использовать tax_rate.

Модуль, который хочет использовать переменную, функцию или класс из другого модуля, должен импортировать их в свое глобальное пространство имен. Импорт - это способ перенести имя из другого места в желаемое пространство имен.

❶ Функция add_sales_tax добавлена ​​в глобальное пространство имен receipt.

add_sales_tax все еще знает о TAX_RATES_BY_STATE и tax_rate из своего собственного пространства имен.

Чтобы ссылаться на переменную, функцию или класс в Python, должно выполняться одно из следующих условий:

  1. Имя находится во встроенном пространстве имен Python.
  2. Имя - это глобальное пространство имен текущего модуля.
  3. Имя находится в текущей строке локального пространства имен кода.

Приоритет конфликтующих имен работает в обратном порядке; локальное имя переопределяет глобальное имя, которое переопределяет встроенное имя.

Вы можете запомнить это, потому что обычно используется определение, наиболее специфичное для текущего кода. Это показано на рисунке 1.

Возможно, вы когда-нибудь видели NameError: name 'my_var' is not defined в своих приключениях с Python. Это означает, что имя my_var не было найдено ни в одном из пространств имен, известных этому коду.

Обычно это означает, что вы никогда не присваивали my_var значение или вы назначали его где-то еще и вам необходимо его импортировать.

Модули - отличный способ начать разбиение кода; если у вас есть один длинный script.py с кучей несвязанных функций, подумайте о том, чтобы разбить эти функции на модули.

Множество масок импорта

Синтаксис для импорта в Python сначала кажется простым, но есть несколько способов сделать это, и каждый из них приводит к незначительным различиям в информации, вводимой в пространство имен.

Ранее вы импортировали функцию add_sales_tax() из модуля sales_tax в модуль receipt:

# receipt.py
  
 from sales_tax import add_sales_tax

Это добавляет функцию add_sales_tax() в глобальное пространство имен модуля receipt.

Это все хорошо, но предположим, что вы добавили еще десять функций в sales_tax и хотите использовать их все в receipt. Если вы продолжите идти по тому же пути, вы получите что-то вроде этого:

# receipt.py
  
 from sales_tax import add_sales_tax, add_state_tax, add_city_tax, add_local_millage_tax, ...

Это альтернативный синтаксис, который немного улучшает это:

Это все еще не очень хорошо. Если вам нужен набор функций из другого модуля, вы можете вместо этого полностью импортировать этот модуль:

# receipt.py
  
 import sales_tax

Это добавляет весь модуль sales_tax к текущему пространству имен, и на его функции можно ссылаться с префиксом sales_tax.:

Это позволяет избежать длинных операторов import, а префикс помогает избежать конфликтов пространства имен.

Импорт подстановочных знаков

Python позволяет вам импортировать все имена из модуля в сокращенном виде, используя from themodule import *. Заманчиво использовать это вместо того, чтобы добавлять к именам префикс themodule. во всем коде, но не надо!

Импорт с подстановочными знаками может привести к большему количеству конфликтов имен, поскольку вы не можете видеть импортируемые явные имена, и это затрудняет отладку. Придерживайтесь явного импорта!

Это все для этой статьи. Если вы хотите узнать больше о книге, загляните в liveBook и посмотрите эту колоду слайдов.

Из Практики Python Pro Дэйна Хилларда.