Перейти к содержимому

Shadows name from outer scope python что это

  • автор:

Python-сообщество

[RSS Feed]

  • Начало
  • » Python для экспертов
  • » Область видимости и ссылки на аргументы

#1 Авг. 3, 2015 21:52:58

ArtikUA Зарегистрирован: 2015-05-14 Сообщения: 8 Репутация: 0 Профиль Отправить e-mail

Область видимости и ссылки на аргументы

Есть словарь и две функции: первая переворачивает значение ключа 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
Как сделать что бы всё было на “чистых” функциях?

Отредактировано ArtikUA (Авг. 3, 2015 21:54:17)

#2 Авг. 3, 2015 23:43:36

JOHN_16 От: Россия, Петропавловск-Камчатск Зарегистрирован: 2010-03-22 Сообщения: 3292 Репутация: 221 Профиль Отправить e-mail

Область видимости и ссылки на аргументы

Потому что о реализации области видимости в Питоне вы толкьо слышали, а не изучали. Он работает ровно так как и положено. Книга Лутца “Програмируем с 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']) 

_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

How to fix “Shadows name from outer scope” in PyCharm

Pycharm Shadows Names

PyCharm is a hugely popular Python IDE developed by JetBrains. PyCharm supports pretty much anything you can think of when you mention a modern IDE, such as debugging, syntax highlighting, project management, smart prompt, automatic completion, unit testing, version control… In addition to that, PyCharm also provides advanced web development for Django, doing data science with Anaconda and even IronPython.

While working with PyCharm, you might encounter some warning, a few of them are not Python error messages. “Shadows name from outer scope” is one of the most common error message that spread confusion among new users. This article will explain why it happens and what you can do to avoid it.

Why does “Shadows name from outer scope” happens?

Let’s take the code snippets below as our example :

the_list = [1, 2, 3] def data_log(the_list): # Warning: "Shadows 'the_list' from outer scope print(the_list) data_log(the_list)

You can clearly see that in the first line we define the_list in the global scope, and inside the function data_log , we reused that name. Reusing names in and out of functions will be referred as “shadowing names” in PyCharm, therefore causes “Shadows name from outer scope”. This is just a warning and doesn’t make your code unable to run.

While there’s nothing wrong with the example and it runs just fine, it can be the beginning of strange behaviour if you continue to ignore the error message.

Imagine data_log takes in not one but a few more arguments, and the inner logic of it gets more complex. You decide to manually rename the_list to array_object , but leaves a few miss here and there.

If you run the code again, it might just work, but the results will certainly be strange. That is because now the_list refers to the global object, array_object refers to the local one, they are different and you mixed them back and forth inside your function.

Avoid “Shadows name from outer scope”

Now that we know the reason behind the warning, the solution is quite simple : You need to avoid reusing names in your code.

Doing so will not only reduce weird behaviour in your code, but also make debugging easier, since you would end up with NameError if Python cannot find a global name or local name.

One more thing to remember is that you should not “shadow” modules, classes and functions the same way you shadow names, too.

This is how our example will look like if it doesn’t shadow names :

the_list = [1, 2, 3] def data_log(a_list): # Warning: "Shadows 'the_list' from outer scope print(a_list) data_log(the_list)

Or you can just move the global variables to another function like so :

def data_log(a_list): print(a_list) def main(): the_list = [1, 2, 3] data_log(the_list)

We’ve also covered how to fix locale.Error: unsupported locale setting once and for all, which might be a good read for new Python developers. We hope this article will help you solve your problem and write better, cleaner, error-free code.

Leave a Comment Cancel reply

Hey! I’m Daan. I work as a SysAdmin in the Netherlands. Whenever I find free time, I write about IT, Linux, Open Source and hardware on this site.

Recommended Readings

  • cURL: “failed to verify the legitimacy of the server” error
  • Git: Accept all current/incoming changes
  • Git: fatal: Not possible to fast-forward, aborting
  • requests: Max retries exceeded with URL
  • Python: Object of type is not JSON serializable
  • Chrome: Access to XMLHttpRequest has been blocked by CORS policy
  • Auto indent in VSCode
  • Save SSH passwords
  • Quickly Format JSON in VSCode
  • Go to definition
  • Fix ESLint problems in VSCode
  • Fix Unresolved imports in VSCode

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

Проблема следующая, и думаю известная многим. При использовании в именах аргументов функций переменных с названиями, которые использовались во внешнем окружении IDE выводим соответствующее предупреждение — Shadow name «proxy» from outer scope. И правильно делает, так как это может привести к ошибкам(обсуждается вот тут)

proxy = 'somepr.ox' def func(proxy): # do somethings return proxy 

Ни использовать решение которое вытекает из PEP8(синонимы или proxy_ ) мне не очень нравится так все равно иногда можно допустить ошибку, да и код выглядит убого(имхо): def func(proxy_, server_, user_): . return proxy_ Один знакомый(Megabit, привет) дал совет который я использовал в C++ — в начале каждого аргумента ставится буква А(Аргумент), но в Python используется другой стиль и такой «финт» наверное испортит читабельность кода.

int BrootSearch(byte* Abuff, int ALength)

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

def func(proxy): return proxy def main(): proxy = 'somepr.ox' main() 

Shadows name from outer scope python что это

Last updated: Jun 29, 2023
Reading time · 3 min

banner

# Warning: Shadows name X from outer scope in PyCharm

The PyCharm warning «Shadows name ‘X’ from outer scope» is shown when you have a parameter of a function or a variable defined in a function that shadows a variable defined in the outer scope.

To resolve the issue, rename the variable or parameter so it doesn’t clash with the one from the outer scope.

Here is an example of when the warning is shown.

Copied!
site = 'bobbyhadz.com' # ⛔️ Shadows name 'site' from outer scope def print_site(site): print(site) # bobbyhadz.com print_site(site)

shadows name from outer scope

We have a variable named site that is defined in the global scope.

The print_site function takes a parameter named site and prints it.

The warning is shown because the name of the parameter ( site ) is the same as the name of the variable ( site ) in the outer scope.

This causes the two variables to clash.

One way to resolve the issue is to rename the function parameter (or the site variable from the outer scope).

Here is an example that renames the function parameter.

Copied!
site = 'bobbyhadz.com' def print_site(website): print(website) # bobbyhadz.com print_site(site)

rename function parameter

I renamed the function parameter from site to website to resolve the issue.

The name of the parameter no longer shadows the variable from the outer scope so the issue is resolved.

You can also rename the global variable to resolve the warning.

Copied!
website = 'bobbyhadz.com' def print_site(site): print(site) # bobbyhadz.com print_site(website)

rename outer scope variable to resolve warning

I renamed the outer scope variable to website and the function’s parameter is named site , so they no longer clash.

# Function parameter/variable sharing the same name as an outer scope variable

When the function’s parameter shares the same name as the outer scope variable, the outer scope variable becomes inaccessible (directly) inside the function.

Here is a code sample that better illustrates this.

Copied!
site = 'bobbyhadz.com' def print_site(): # ⛔️ Shadows name 'site' from outer scope site = 'google.com' print(site) # google.com print_site()

We declared a site variable in the outer scope and then declared a variable with the same name inside the function.

When we pass the site variable to the print() function, the variable from the local scope gets printed.

You cannot access the `site` variable from the outer scope inside the print_site function because the local variable with the same name shadows it.

To resolve the issue, you either have to rename the global variable or the local variable.

Copied!
site = 'bobbyhadz.com' def print_site(): website = 'google.com' print(website) # google.com print_site()

Now the names of the outer scope and local variables no longer clash, so the issue is resolved.

# Disabling the «Shadowing names from outer scopes» warning in PyCharm

If you want to disable the «Shadowing names from outer scopes» warning in PyCharm:

  1. Press Ctrl + Alt + S or click on File in the top menu and then select Settings.
  2. Click on Editor, then Inspections and search for shadowing names.
  3. Uncheck the Shadowing names from outer scopes checkbox and click on Apply and OK.

disable shadowing names from outer scope in pycharm

# Wrapping the outer scope variable in a function

An alternative way to resolve the warning is to wrap your outer scope variable in a function.

Copied!
def main(): site = 'bobbyhadz.com' print_site(site) def print_site(site): print(site) main()

The site variable is no longer defined in the global scope so it doesn’t shadow the parameter of the print_site function.

# Using a trailing underscore to differentiate between the two variables

A commonly used convention that you can use to solve the error is to add a trailing underscore after the name of the variable (or the name of the function parameter).

Copied!
site = 'bobbyhadz.com' def print_site(site_): print(site_) # bobbyhadz.com print_site(site)

The function parameter is named site_ instead of site .

Now the two names don’t clash so the warning is no longer shown.

I’ve also written a detailed guide on how to use global variables in Python.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

  • Delete or Change a Global Variable in a Function in Python
  • How to clear the Terminal and Console in PyCharm
  • Pycharm does not show a Matplotlib Plot issue [Solved]

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.

Python-сообщество

[RSS Feed]

  • Начало
  • » Python для экспертов
  • » Область видимости и ссылки на аргументы

#1 Авг. 3, 2015 21:52:58

ArtikUA Зарегистрирован: 2015-05-14 Сообщения: 8 Репутация: 0 Профиль Отправить e-mail

Область видимости и ссылки на аргументы

Есть словарь и две функции: первая переворачивает значение ключа 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
Как сделать что бы всё было на “чистых” функциях?

Отредактировано ArtikUA (Авг. 3, 2015 21:54:17)

#2 Авг. 3, 2015 23:43:36

JOHN_16 От: Россия, Петропавловск-Камчатск Зарегистрирован: 2010-03-22 Сообщения: 3292 Репутация: 221 Профиль Отправить e-mail

Область видимости и ссылки на аргументы

Потому что о реализации области видимости в Питоне вы толкьо слышали, а не изучали. Он работает ровно так как и положено. Книга Лутца “Програмируем с 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']) 

_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Shadows name from outer scope python что это

Last updated: Jun 29, 2023
Reading time · 3 min

banner

# Warning: Shadows name X from outer scope in PyCharm

The PyCharm warning «Shadows name ‘X’ from outer scope» is shown when you have a parameter of a function or a variable defined in a function that shadows a variable defined in the outer scope.

To resolve the issue, rename the variable or parameter so it doesn’t clash with the one from the outer scope.

Here is an example of when the warning is shown.

Copied!
site = 'bobbyhadz.com' # ⛔️ Shadows name 'site' from outer scope def print_site(site): print(site) # bobbyhadz.com print_site(site)

shadows name from outer scope

We have a variable named site that is defined in the global scope.

The print_site function takes a parameter named site and prints it.

The warning is shown because the name of the parameter ( site ) is the same as the name of the variable ( site ) in the outer scope.

This causes the two variables to clash.

One way to resolve the issue is to rename the function parameter (or the site variable from the outer scope).

Here is an example that renames the function parameter.

Copied!
site = 'bobbyhadz.com' def print_site(website): print(website) # bobbyhadz.com print_site(site)

rename function parameter

I renamed the function parameter from site to website to resolve the issue.

The name of the parameter no longer shadows the variable from the outer scope so the issue is resolved.

You can also rename the global variable to resolve the warning.

Copied!
website = 'bobbyhadz.com' def print_site(site): print(site) # bobbyhadz.com print_site(website)

rename outer scope variable to resolve warning

I renamed the outer scope variable to website and the function’s parameter is named site , so they no longer clash.

# Function parameter/variable sharing the same name as an outer scope variable

When the function’s parameter shares the same name as the outer scope variable, the outer scope variable becomes inaccessible (directly) inside the function.

Here is a code sample that better illustrates this.

Copied!
site = 'bobbyhadz.com' def print_site(): # ⛔️ Shadows name 'site' from outer scope site = 'google.com' print(site) # google.com print_site()

We declared a site variable in the outer scope and then declared a variable with the same name inside the function.

When we pass the site variable to the print() function, the variable from the local scope gets printed.

You cannot access the `site` variable from the outer scope inside the print_site function because the local variable with the same name shadows it.

To resolve the issue, you either have to rename the global variable or the local variable.

Copied!
site = 'bobbyhadz.com' def print_site(): website = 'google.com' print(website) # google.com print_site()

Now the names of the outer scope and local variables no longer clash, so the issue is resolved.

# Disabling the «Shadowing names from outer scopes» warning in PyCharm

If you want to disable the «Shadowing names from outer scopes» warning in PyCharm:

  1. Press Ctrl + Alt + S or click on File in the top menu and then select Settings.
  2. Click on Editor, then Inspections and search for shadowing names.
  3. Uncheck the Shadowing names from outer scopes checkbox and click on Apply and OK.

disable shadowing names from outer scope in pycharm

# Wrapping the outer scope variable in a function

An alternative way to resolve the warning is to wrap your outer scope variable in a function.

Copied!
def main(): site = 'bobbyhadz.com' print_site(site) def print_site(site): print(site) main()

The site variable is no longer defined in the global scope so it doesn’t shadow the parameter of the print_site function.

# Using a trailing underscore to differentiate between the two variables

A commonly used convention that you can use to solve the error is to add a trailing underscore after the name of the variable (or the name of the function parameter).

Copied!
site = 'bobbyhadz.com' def print_site(site_): print(site_) # bobbyhadz.com print_site(site)

The function parameter is named site_ instead of site .

Now the two names don’t clash so the warning is no longer shown.

I’ve also written a detailed guide on how to use global variables in Python.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

  • Delete or Change a Global Variable in a Function in Python
  • How to clear the Terminal and Console in PyCharm
  • Pycharm does not show a Matplotlib Plot issue [Solved]

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.

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

Проблема следующая, и думаю известная многим. При использовании в именах аргументов функций переменных с названиями, которые использовались во внешнем окружении IDE выводим соответствующее предупреждение — Shadow name «proxy» from outer scope. И правильно делает, так как это может привести к ошибкам(обсуждается вот тут)

proxy = 'somepr.ox' def func(proxy): # do somethings return proxy 

Ни использовать решение которое вытекает из PEP8(синонимы или proxy_ ) мне не очень нравится так все равно иногда можно допустить ошибку, да и код выглядит убого(имхо): def func(proxy_, server_, user_): . return proxy_ Один знакомый(Megabit, привет) дал совет который я использовал в C++ — в начале каждого аргумента ставится буква А(Аргумент), но в Python используется другой стиль и такой «финт» наверное испортит читабельность кода.

int BrootSearch(byte* Abuff, int ALength)

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

def func(proxy): return proxy def main(): proxy = 'somepr.ox' main() 

What is the problem with shadowing names defined in outer scopes?

I just switched to PyCharm and I am very happy about all the warnings and hints it provides me to improve my code. Except for this one which I don’t understand:

This inspection detects shadowing names defined in outer scopes.

I know it is bad practice to access variable from the outer scope, but what is the problem with shadowing the outer scope? Here is one example, where PyCharm gives me the warning message:

data = [4, 5, 6] def print_data(data): #  

20.9k 69 69 gold badges 77 77 silver badges 102 102 bronze badges
asked Nov 21, 2013 at 15:35
34k 52 52 gold badges 131 131 silver badges 193 193 bronze badges

Also I searched for the string "This inspection detects. " but found nothing in the pycharm online help: jetbrains.com/pycharm/webhelp/getting-help.html

Nov 21, 2013 at 15:39

To turn off this message in PyCharm: ++s (settings), Editor, Inspections, "Shadowing names from outer scopes". Uncheck.

Jan 23, 2019 at 17:33

I got the same warning and see nothing wrong with the code. The function is using the local parameter "data", not the global "data". Of course if you rename the parameter, you'll have to rename its occurrences in the function scope. Not sure what the author of the plugin thinks. It's like he's never used IDE's Code Refactoring.

Jan 12, 2023 at 7:28

As of PyCharm 2023, the path to turn of the Shadows warning is File -> Settings -> Editor -> Inspections -> Shadowing names from outer scopes

Aug 3, 2023 at 17:42

11 Answers 11

There isn't any big deal in your above snippet, but imagine a function with a few more arguments and quite a few more lines of code. Then you decide to rename your data argument as yadda , but miss one of the places it is used in the function's body. Now data refers to the global, and you start having weird behaviour - where you would have a much more obvious NameError if you didn't have a global name data .

Also remember that in Python everything is an object (including modules, classes and functions), so there's no distinct namespaces for functions, modules or classes. Another scenario is that you import function foo at the top of your module, and use it somewhere in your function body. Then you add a new argument to your function and named it - bad luck - foo .

Finally, built-in functions and types also live in the same namespace and can be shadowed the same way.

None of this is much of a problem if you have short functions, good naming and a decent unit test coverage, but well, sometimes you have to maintain less than perfect code and being warned about such possible issues might help.

30.8k 22 22 gold badges 106 106 silver badges 131 131 bronze badges
answered Nov 21, 2013 at 15:56
bruno desthuilliers bruno desthuilliers
76.4k 6 6 gold badges 92 92 silver badges 120 120 bronze badges

Fortunately PyCharm (as used by the OP) has a very nice rename operation that renames the variable everywhere it is used in the same scope, which makes renaming errors less likely.

Apr 6, 2017 at 0:29

In addition to PyCharm's renaming operation I would love to have special syntax highlights for variables that refer to outer scope. These two should render this time consuming shadow resolution game irrelevant.

Jul 25, 2019 at 13:46

Side note: You can use the nonlocal keyword to make outer score referring (like in closures) explicit. Note that this is different from shadowing, as it explicitly does not shadow variables from outside.

Oct 7, 2019 at 8:21

I believe this is not the right answer and does not propose a solution. I believe this should be the answer: stackoverflow.com/a/40008745/2424587

Jan 25, 2022 at 15:50

@HananShteingart I already commented on why what you believe should be the answer is not, and it's also part of my own answer.

Jan 27, 2022 at 17:59

It doesn't matter how long your function is, or how you name your variable descriptively (to hopefully minimize the chance of potential name collision).

The fact that your function's local variable or its parameter happens to share a name in the global scope is completely irrelevant. And in fact, no matter how carefully you choose you local variable name, your function can never foresee "whether my cool name yadda will also be used as a global variable in future?". The solution? Simply don't worry about that! The correct mindset is to design your function to consume input from and only from its parameters in signature. That way you don't need to care what is (or will be) in global scope, and then shadowing becomes not an issue at all.

In other words, the shadowing problem only matters when your function need to use the same name local variable and the global variable. But you should avoid such design in the first place. The OP's code does not really have such design problem. It is just that PyCharm is not smart enough and it gives out a warning just in case. So, just to make PyCharm happy, and also make our code clean, see this solution quoting from silyevsk's answer to remove the global variable completely.

def print_data(data): print data def main(): data = [4, 5, 6] print_data(data) main() 

This is the proper way to "solve" this problem, by fixing/removing your global thing, not adjusting your current local function.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *