Рубрики
Без рубрики

Пространства имен Python сделаны простыми – с примерами Harry Potter

[+ Видео] Бесплатное руководство по вопросам пространства имен в Python с простым, чтобы понять примеры Гарри Поттера.

Автор оригинала: Chris.

Пространство имен являются Везде в Python (понимаешь ли вы это или нет). Однако, не зная о пространствах имен Python, является источником неприятных ошибок и неэффективного кода Python.

Во многих классах с 30 студентами два из них разделяют одно и то же имя. Причина является вариантом популярных Проблема на день рождения (Для имена, не День рождения ).

Учитель спрашивает «Алиса?» – И два алиса отвечают «да». Происхождение проблемы – это существование неоднозначных имен. Грубо говоря, реальные пространства имен не настраиваются должным образом.

Та же проблема возникает для интерпретатора Python, если вы скажете это выполнить функцию «Alice ()». Имя «Алиса», возможно, уже было определено в импортируемом модуле или в другой части вашего кода.

Цель пространства имен – это разрешение этих типов конфликтов именования, раз и для всех. В то время как учитель будет использовать более передовые методы для устранения неоднозначности (например, указывая на Алису слева), переводчик Python не может решить, какой Alice предназначен.

Пространство имен – это просто коллекция имен. Имя идентифицирует объект (например, функция или переменная). Поэтому, если вы вызываете функцию f () в вашем коде, пространство имен сообщает интерпретателю, какой функциональный объект для вызова.

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

Вы можете распечатать текущее пространство имен (I.E., Коллекция имен) с функцией dir ().

alice = 25

def birthday():
    alice += 1

print(dir())
# ['__annotations__', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'alice', 'birthday']"

Определение переменной «ALICE» и функциональный «день рождения» имеет точно такой же эффект на пространстве имен: каждый раз, когда в пространстве имен добавляется новое имя.

Обратите внимание, что пространство имен содержит некоторую разум по умолчанию (для «двойных подчеркиваний») имен. Вы узнаете о них в конце этой статьи.

Вы всегда должны использовать библиотеки вместо того, чтобы изобретать колесо. Библиотека – это коллекция модулей. Модуль – это файл, содержащий код, который вы можете повторно использовать в вашей программе. Вы загружаете код файла «Module.py» в вашу программу одним из трех следующих утверждений.

# 1. Import all the code from the file 'module.py'
import module
module.f()

# 2. Rename module in your own file
import module as m
m.f()

# 3. Import only specific functions of the module
from module import f
f()

В чем проблема? Скажем, вы определяете функцию f () в вашей программе. Но функция f () уже определена в импортируемом модуле. Это плохо. Предположим, вы сообщите переводчику Python для выполнения F (). Если это выполнить вашу функцию f () или функцию модуля f ()?

## File module.py
def f():
    print("hi")


## File main.py
from module import f

def f():
    print("hello")


f()
# What's the output??

Пока программа отлично работает (результат – «Hello»), этот способ реализации очень запутанно. Потому что вы никогда не знаете, какие функции перезаписывают, какие функции из другого модуля.

Python решает эту проблему с пространствами имен. В приведенном выше примере пространства имен разрешают проблему нескольких определений F ().

В следующем примере у нас есть главная программа «Main.PY» и модуль «OREPIFIER».

## File 'wordifier.py'
def negate(word):
    return 'de' + word


def verb(word):
    return word + 'ize'


## File 'main.py'
def add_yes(word):
    return word + ', yes!'


print(dir())
# [..., 'add_yes']

from wordifier import *

print(dir())
# [..., 'add_yes', 'negate', 'verb']

Что происходит в этой программе?

Во-первых, мы распечатаем пространство имен перед импортом модуля «Fortifier». В этом случае пространство имен содержит имя функции, определенной в нашем основном файле.

Во-вторых, мы распечатаем пространство имен после импорта всех имен из модуля «Вершина». В этом случае пространство имен содержит имя функции, определенной как в нашем основном файле, так и в модуле.

ОК, поэтому теперь вы знаете, что импортирующие модули изменит ваше пространство имен.

Используйте «из импорта B», чтобы импортировать только имя объекта «B» из пространства пространства имен на локальное пространство.

Используйте «из импорта *», чтобы импортировать все имена из пространства имен «A» в локальное пространство имен.

Тем не менее, если вы используете «Импорт A», вы не импортируете какое-либо новое имя из пространства имен «A» в ваше локальное пространство имен. Вместо этого вы называете функцию f () в модуле «A», как это: a.f ().

Теперь вы должны быть в состоянии решить следующую головоломку.

Что такое выход этого кода фрагмент?

## File 'wordifier.py'
def negate(word):
    return 'de' + word


def verb(word):
    return word + 'ize'


## File 'main.py'
def add_yes(word):
    return word + ', yes!'


print(dir())
# [..., 'add_yes']

import wordifier

print('negate' in dir())
# True or False?

Какая вывод этого кода фрагмент? * *

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

* * Выход вышеуказанного кода головоломки «ложь».

Вы узнали о мотивации и причинах для пространств имен (неоднозначность!), Как исследовать текущее пространство имен Python (используя функцию DIR ()) и как пространство имен модифицировано при импорте модулей (есть три разных способа).

Далее вы погрузитесь глубже в пространствам имен, исследуя вопрос:

Существует два типа пространств имен: глобальные и локальные пространства имен. Глобальные пространства имен видны по всему вашему коду Python. Локальные пространства имен видны только внутри функции.

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

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

Рассмотрим следующую коду головоломки, которая показывает, как распечатать глобальные и локальные пространства имен на вашу оболочку:

wizards = ['Harry',
           'Hermione',
           'Ron']

## GLOBAL NAMESPACE
print(dir())
"""
['__annotations__', '__builtins__', '__doc__',
'__file__', '__loader__', '__name__',
'__package__', '__spec__', 'wizards']
"""

def encrypt(lst):
    secret = []
    for wiz in lst:
        secret.append(wiz[::-1])

    ## LOCAL NAMESPACE
    print(dir())
    # ['lst', 'secret', 'wiz']
    
    return secret

print(dir())
"""
['__annotations__', '__builtins__', '__doc__',
'__file__', '__loader__', '__name__',
'__package__', '__spec__', 'encrypt', 'wizards']
"""

print(encrypt(wizards))

(Кстати: вы можете решить код головоломки?)

Первый вызов функции DIR () происходит на глобальном уровне (без отступа), поэтому результат является глобальным пространством имен с значениями по умолчанию и именем «Волшебника».

Второй вызов функции DIR () происходит на локальном уровне (отступ), поэтому результат является локальным пространством имен с переменными, используемыми в функции. Как только функция завершается, пространство имен выделяется.

Третий вызов функции DIR () происходит на глобальном уровне (без отступа). Но результат изменился, поскольку вы добавили новое глобальное имя для него: «шифрование». Обратите внимание, что имена из локального пространства имен («LST», «Secree», «Wiz») больше не существуют в глобальном пространстве имен.

Скажите, что вы выполняете следующее утверждение сейчас:

print(secret)

Python будет бросать NameError, что имя «Secret» не определено, потому что локальное пространство имен больше не существует.

Это приводит нас к следующему вопросу:

В последнем примере вы видели, что вы не можете использовать имя в вашем коде, куда хотите. Если пространство имен определяет это имя не существует (или не видно), вы не можете использовать имя. Если вы попробуете, Python бросит nameeRor.

Таким образом, каждое имя имеет охват, который точно определяет местоположение в вашем коде, где вы можете использовать его. Имя «Секрет» может использоваться только в рамках функции «шифрование». Имя «шифрование» можно использовать в любом месте программы.

Интересно, что обладает иерархически структурированными:

  • Внешний (глобальный) объем Содержит все встроенные имена (с нотацией на табуку). Вы можете использовать их везде в любой программе Python.
  • Объем уровня модуля Содержит имена, определенные в вашей программе Python (функции первого уровня и переменные), а также импортируемые имена модулей или импортированные имена из этих модулей. Вы можете использовать их где угодно в вашей программе Python.
  • Иерархические локальные области : Знаете ли вы, что вы можете определить функции внутри функций? Таким образом, вы можете иметь разные ограждения пространств имен. Мы погрузимся глубже в этот конкретный пример в мгновение.
  • внутренняя область охвата Ограничено текущей функцией, в которой выполняется ваша программа. Если функция завершается, имена в этом объеме теряются.

Итак, давайте посмотрим на такой пример с иерархическими спецификациями:

def outer():
    x = 42
    def inner():
        y = 21
        print(dir())
    inner()
    print(dir())

outer()
print(dir())


'''
Output 1:
['y']

Output 2:
['inner', 'x']

Output 3:
['__annotations__', '__builtins__',
'__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__', 'outer']
'''

Существует три уровня иерархического пространства имен в примере кода:

  • Глобальное пространство имен Содержащие названия разум по умолчанию и имя «внешнего» функции,
  • Локальное пространство имен «внешней» функции Содержание имена переменной «X» и имя функции «Внутреннее» и
  • Локальное пространство имен «Внутренняя» функция содержащий имя переменной ‘y’.

Таким образом, существует несколько уровней пространств имен, определяющих объем имен, то есть конкретная часть кода, в которой ваши имена могут использоваться без питона, бросая ошибку.

[Короткое уведомление] Эта статья основана на теме электронной почты в моем серии электронной почты «Coffee Break Python», где я публикую ежедневные учебные пособия Python для постоянного улучшения в Python во время ваших перерывов на кофе. Присоединяйтесь к нам, это весело!

Осталось два важных вопроса:

Начнем с удивительного кода головоломки:

magic_wiz = 'Harry'

def change_wiz():
    magic_wiz = 'Hermione'

change_wiz()
print(magic_wiz)

Какой вывод этого кода?

Обязать ответ перед чтением.

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

При входе в функцию «Comment_Wiz ()», новое локальное пространство имен содержит только имя «Magic_Wiz». Это имя не имеет ничего общего с глобальным именем «Magic_Wiz» – это временно перезаписывает глобальное имя.

Грубо говоря, при обращении к названию «Magic_Wiz» в функции «Change_Wiz», вы не можете напрямую получить доступ к глобальному имени «Magic_Wiz». Правильный компьютер на науке для этого явления – «маскировка имени», потому что имя внутренней области временно маскирует название внешнего объема [ Вики .

Следовательно, результат вышеуказанного кода головоломка – «Гарри». Удивительно, не так ли?

Глобальная переменная «Magic_Wiz» никогда не была изменена функцией – имя «Magic_Wiz» во внутреннем пространстве имен функции замаскировала глобальное имя «Magic_Wiz».

Как мы можем решить эту проблему? Просто, используя ключевое слово «Global», чтобы указать, что мы имеем в виду глобальное имя в рамках функции:

magic_wiz = 'Harry'

def change_wiz():
    global magic_wiz
    magic_wiz = 'Hermione'

change_wiz()
print(magic_wiz)

Теперь вывод «Гермиона», поскольку имя «Magic_Wiz» явно определяется как ссылка на глобальное пространство имен.

Прежде чем мы завершите пространствами имен, я хочу быстро ответить на последний вопрос:

Каковы имена по умолчанию в пространстве имен с двойным подчерком («разум») обозначения?

Посмотрите на этот простой пример:

magic_wiz = "Harry"

print(dir())
"""
['__annotations__', '__builtins__',
'__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__',
'magic_wiz']
"""

Мы определили только фамилию в пространстве имен. Остальные имена включены в пространство имен по умолчанию. Все эти имена по умолчанию прилагаются в двойные подчеркивания («Dunders»).

Давайте распечатаем их один за другим:

print(__annotations__)
# {}

print(__builtins__)
# 

print(__doc__)
# None

print(__file__)
# C:\Users\xcent\Desktop\Finxter\Blog\PythonNamespaces\global_vs_local.py

print(__loader__)
# 

print(__name__)
# __main__

print(__package__)
# None

print(__spec__)
# None

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

В этой статье рассматриваются важная тема в Python: пространства имен. Это актуально, особенно для отладки. Вы можете найти некоторые ошибки только с правильным пониманием пространств имен Python. Рассмотрим это сделано.

Статья основана на моих писаниях для ежедневного «Coffe Break Python» серии электронной почты. Я регулярно делаю новые мини-курсы по разнообразным и важным темам в области информатики. Проверьте академию Finxter, чтобы узнать о новых мини-курсах, таких как этот:

[Мини-курс] «Насущная инструментария кодера: Как все работает вместе в Python »

Работая в качестве исследователя в распределенных системах, доктор Кристиан Майер нашел свою любовь к учению студентов компьютерных наук.

Чтобы помочь студентам достичь более высоких уровней успеха Python, он основал сайт программирования образования Finxter.com Отказ Он автор популярной книги программирования Python одноклассники (Nostarch 2020), Coauthor of Кофе-брейк Python Серия самооставленных книг, энтузиаста компьютерных наук, Фрилансера и владелец одного из лучших 10 крупнейших Питон блоги по всему миру.

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

Оригинал: “https://blog.finxter.com/python-namespaces-made-simple/”