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

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

  • автор:

Как правильно именовать переменную, чтобы избежать предупреждения типа «Имя тени из внешней области видимости» в Python

Я использую PyCharm для своей программы на Python, и я написал коды ниже:

Поэтому я получаю текст предупреждения типа «Shadows name ‘ds’ from external scope». Я знаю влияние области действия, но я все еще хочу использовать тот же формат кода, что и «для root, ds, fs in . » во внутренней или внешней области видимости.

Я искал PEP8, однако до сих пор не знаю, как назвать переменную в функции нормативно.

Не могли бы вы дать мне предложение?

3 ответа

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

Однако я бы не стал вызывать os.walk() вызов в глобальной области видимости в любом случае . Я бы предпочел поместить это и в функцию, которая имеет счастливый побочный эффект от имен, которые вы использовали, больше не глобальные.

Например, вы можете использовать функцию main() :

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

Если ваши имена повторяются, используйте «_», чтобы избежать таких предупреждений. Это обычная практика.

Это предупреждение shadows name XX from outer scope — это не проблема PEP8, а реальное предупреждение от Pycharm о том, что повторное использование имен переменных таким образом — плохая идея. Другими словами, это не проблема стиля кода, а то, что может привести к проблемам в более поздних программах.

Мое предложение было бы, ну, во всяком случае, избегать повторного использования имен переменных, когда это возможно. Набрав это:

for root_path, directory_name, file_name in os.walk(root_dir):

Не займет много времени и позволит избежать нежелательных побочных эффектов в будущем.

Тем не менее, если по какой-либо причине вам абсолютно необходимо повторно использовать имена переменных и вы хотите избавиться от предупреждающего сообщения, вы можете отключить его в Pycharm («Настройки» -> «Редактор» -> «Стиль кода» -> «Проверки» -> скрытие имен из внешних областей). Но обычно это плохая идея.

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

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 :

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.

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

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.

Solution 2

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.

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

Solution 3

A good workaround in some cases may be to move the variables and code to another function:

Solution 4

I like to see a green tick in the top right corner in PyCharm. I append the variable names with an underscore just to clear this warning so I can focus on the important warnings.

Solution 5

It depends how long the function is. The longer the function, the greater the chance that someone modifying it in future will write data thinking that it means the global. In fact, it means the local, but because the function is so long, it’s not obvious to them that there exists a local with that name.

For your example function, I think that shadowing the global is not bad at all.

Shadows name xyz from outer scope

I am using pycharm and it lists out all the errors/warnings associated with the code. While I understand most of them I am not sure of this one «Shadows name xyz from outer scope». There are a few SO posts regarding this: How bad is shadowing names defined in outer scopes? but then they seem to be accessing a global variable.

In my case, my __main__ function has a few variable names and then it is calling another function sample_func which uses those variable names again (primarily the loop variable names). I am assuming because I am in a different function, the scope for these variables will be local, however the warning seem to suggest otherwise.

Any thoughts? For your reference here is some code:

The Wanderer's user avatar

5 Answers 5

The warning is about the potential danger you are introducing by re-using these names at inner scopes. It can cause you to miss a bug. For example, consider this

Because you used the same name, your misspelling inside the function does not cause an error.

When your code is very simple, you will get away with this type of thing with no consequences. But it’s good to use these «best practices» in order to avoid mistakes on more complex code.

The code inside of your if branch of your main function is actually in scope when you’re inside of sample_func. You can read from the variable x (try it out). This is okay as you don’t really care about it so you have a few options to move forward.

1) Disable shadowing warnings in pycharm. Honestly this is the most straightforward and depending on how experienced of a coder you are it probably makes the most sense (if you’re relatively new I would not do this though.)

2) Put your main code into a main function. This is probably the best solution for any production level code. Python is very good at doing things the way you want to do them so you should be careful not to fall into traps. If you are building a module, having lots of logic at the module level can get you into sticky situations. Instead, something like the following could be helpful:

3) Don’t use the same variable names that you’re using in broader scopes. This is pretty hard to enforce and is kinda the opposite of #1.

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

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