Найти - Пользователи
Полная версия: Область видимости и ссылки на аргументы
Начало » Python для экспертов » Область видимости и ссылки на аргументы
1
ArtikUA
Есть словарь и две функции: первая переворачивает значение ключа name этого словаря, а вторая - делает все буквы заглавными:
def first(town):
    town['name'] = town['name'][::-1]
    return town
def second(town):
    town['name'] = town['name'].upper()
    return town
town = {'name': 'Moscow', 'population': '10000000'}
town = first(town)
town = second(town)
print(town['name'])
Всё работает отлично, но в каждом аргументе при объявлении функции IDE ругается на “Shadows name ‘town’ from outer scope”

И в самом деле, если мы сделаем так:
def first():
    town['name'] = town['name'][::-1]
def second():
    town['name'] = town['name'].upper()
town = {'name': 'Moscow', 'population': '10000000'}
first()
second()
print(town['name'])
То результат не изменится.
Почему функции видят то, что по идее должно быть за пределами области видимости?
Я ведь не делал global town
Как сделать что бы всё было на “чистых” функциях?
JOHN_16
Потому что о реализации области видимости в Питоне вы толкьо слышали, а не изучали. Он работает ровно так как и положено. Книга Лутца “Програмируем с Python”(3 изд.) глава 16: Области видимости функции. Вырезка:
Разрешение имен: правило LEGB
Для инструкции def:
• Поиск имен ведется самое большее в четырех областях видимости:
локальной, затем в объемлющей функции (если таковая имеется),
затем в глобальной и, наконец, во встроенной.
По умолчанию операция присваивания создает локальные имена.
• Глобальные объявления отображают имена на область видимости
вмещающего модуля.
Другими словами, все имена, которым присваиваются значения
внутри инструкции def (или внутри выражения lambda, с которым мы
познакомимся позже), по умолчанию являются локальными; функции могут
использовать имена в лексически (т. е., физически) объемлющих
функциях и в глобальной области видимости, но чтобы иметь возможность
изменять их, они должны быть объявлены глобальными. Схема
разрешения имен в языке Python иногда называется правилом LEGB,
название которого состоит из первых букв названий областей видимости:
• Когда внутри функции выполняется обращение к неизвестному
имени, интерпретатор пытается отыскать его в четырех областях
видимости - в локальной (local, L), затем в локальной области
любой объемлющей инструкции def (enclosing, E) или в выражении
lambda, затем в глобальной (global, G) и, наконец, во встроенной
(built-in, Б). Поиск завершается, как только будет найдено первое
подходящее имя.
• Когда внутри функции выполняется операция присваивания (а не
обращение к имени внутри выражения), интерпретатор всегда
создает или изменяет имя в локальной области видимости, если в этой
функции оно не было объявлено глобальным.
• Когда выполняется присваивание имени за пределами функции (т.е.
на уровне модуля или в интерактивной оболочке), локальная область
видимости совпадает с глобальной - с пространством имен модуля.
Т.е. механизм поиска переменной с именем Foo и присваивание переменной имени Foo - существенно отличается.

Если брать определение чистой функции, то скорее всего так:
def first(value):
    return value[::1]
town['name'] = first(town['name'])
ArtikUA
JOHN_16
Книга Лутца “Програмируем с Python”(3 изд.) глава 16: Области видимости функции. Вырезка:
Спасибо, то что надо!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB