Який взаємозв'язок між областю застосування та просторами імен у Python?


12

У багатьох ресурсах я виявив, що "область" та "простори імен" використовуються взаємозамінно, що здається дещо заплутаним, оскільки вони означають різні речі.

  • Область застосування визначає область коду, де є ім'я.
  • Правило LEGB визначає спосіб пошуку імен.
  • Простір імен - це місце, де ви шукаєте імена.

Потім я прочитав:

  • "імена прив'язуються до простору імен відповідно до того, куди вони присвоєні ..." (що, на мою думку, є угода з областями в лексичному обстеженні).
  • "функції додають додатковий шар простору імен у ваші програми" [ посилання. ] (не додають вони додатковий локальний обсяг?)
  • "всі імена, призначені всередині визначення функції, розміщуються в локальній області (простір імен, пов'язаний з викликом функції)."
  • "глобальна область застосування - тобто, область імен, в якій змінні, створені (призначені) на верхньому рівні файлу модуля."

* усі цитати - з вивчення пітона 5-го видання ch17

Чи є простори імен у Python способом реалізації областей застосування? Вони однакові? Хтось може мене просвітити?


1
Чи можете ви надати посилання на цитати - я міг би знайти одне, а не інше.
jonrsharpe

1
Простори імен - це лише один тип сфери застосування. Дивіться stackoverflow.com/questions/291978/…
Роберт Харві

Відповіді:


16

Імена представляють собою словник, відображення імен (як рядки) до значень. Виконуючи завдання, наприклад a = 1, ви мутуєте простір імен. Коли ви робите посилання, наприклад print(a), Python переглядає список просторів імен, щоб спробувати знайти його з ім'ям як ключовим.

А область застосування визначає , які простору імен будуть розглянуті в і в якому порядку. Область будь-якої посилання завжди починається в локальному просторі імен і переміщується назовні, поки не досягне глобального простору імен модуля, перш ніж перейти до builtins(простору імен, що посилаються на попередньо визначені функції та константи Python, як rangeі getattr), що є кінцем рядка .

Уявіть, що у вас функція з ім'ям inner, вкладена в глобальну функцію з назвою outer, і innerмістить посилання на ім'я. Спочатку Python шукає у innerпросторі імен. Якщо імені немає, Python тоді шукає у outerпросторі імен. Якщо це не вдається, Python намагається globalпростір імен модуля , а потім builtinпростір імен, врешті-решт, кидає, NameErrorякщо ім'я не знайдено.

Коли ми кажемо, що xзнаходиться в просторі імен функції, ми маємо на увазі, що він визначений там, локально в межах функції. Коли ми кажемо, що xзнаходиться в області функції, ми маємо на увазі xабо в просторі імен функції, або в будь-якому зовнішньому просторі імен, в якому вкладено всередині простору імен функції.

Щоразу, коли ви визначаєте функцію, ви створюєте нову область імен та нову область. Простір імен - це новий, локальний хеш імен. Область застосування - це мається на увазі ланцюг просторів імен, що починається з нового простору імен, потім проходить шлях через будь-які зовнішні простори імен (зовнішні області), аж до глобального простору імен (глобальної області), і до вбудованих.

Терміни можна використовувати майже взаємозамінно, але це не тому, що вони означають те саме; це тому, що вони сильно перекриваються тим, що мають на увазі.


3
"Терміни можна використовувати майже взаємозамінно, але це не тому, що вони означають одне і те ж; це тому, що вони сильно перетинаються з тим, що мають на увазі".
Нікос

2
Ця відповідь правильна по духу, але неправильна в деталях. Класи в Python не вводять нову область імен, тому атрибути класу повинні бути кваліфіковані з назвою класу, і тому атрибути екземпляра повинні бути кваліфіковані з ім'ям екземпляра. Рівні простору імен у Python від внутрішнього до зовнішнього - локальний, закритий, глобальний та вбудований. Клас може бути визначений на будь-якому з цих рівнів, але члени класу повинні бути завжди кваліфіковані.
Роб Смоллшир

Ти маєш рацію. Заняття не працюють так, як я сказав. Я думав, що вони створюють такі лексичні рамки, як функція, але цього не роблять. Будь ласка, оновіть відповідь, якщо у вас є час, інакше я це зроблю в якийсь момент. Дякую.
Карл Сміт

1
+1 Блискуча відповідь, настільки економічно уклавши таку тонкість. Я вважаю це дуже корисним, дякую!
шукач

1
«Простір імен є хешем імені, пар значень, багато , як словник Python» - я впевнений , що простору імен будуть збережені як пітон словники. Наприклад, ви можете редагувати глобальну область імен, викликаючи globals (), що дозволяє вам змінювати словник безпосередньо для прив’язки об'єктів та імен: наприклад globals () [name] = "object". Чудова відповідь інакше.
Еван Росіца

4

Існують різні форми стаття про просторах імен Python тут . Процитуйте відповідну частину, щоб відповісти на ваше запитання про посилання між діапазонами та просторами імен:

Область стосується області програми, з якої можна отримати доступ до простору імен без префікса.

Наприклад, уявіть просту програму для прокатки:

import random  # 'random' is in module namespace

def roll(sides=6):  # 'roll' is in module namespace, 'sides' is in roll's
    return random.randint(1, sides)  # both 'random' and 'sides' are in scope here

# but sides can't be accessed out here 

roll має власний простір імен , але імена в просторі імен модуля також знаходяться в області застосування .


@CarlSmith зауважимо, що рання документація Python говорить про те саме: "Область дії - це текстова область програми Python, де просто доступний простір імен." Безпосередньо доступний "" означає, що некваліфіковане посилання на ім'я намагається знайти ім'я. в просторі імен ".
jonrsharpe

@CarlSmith окрім додаткової області, яка не є локальною / додає, чи багато чого змінилося? Я думаю, ми говоримо те саме - простір імен містить імена та значення, а область вказує вам, які простори імен доступні.
jonrsharpe

Я видалив свої старі коментарі.
Карл Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.