Shadows name from outer scope python что это
for root_path, directory_name, file_name in os.walk(root_dir):
This inspection detects shadowing names defined in outer scopes.
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:
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.
Python language basics 33: variable shadowing and the ‘global’ keyword
In the previous post we looked at positional and keyword arguments in a function. We saw how positional arguments were matched up with the arguments in the function signature. We also discussed how keyword arguments could make your code cleaner by explicitly providing the argument names in a function call.
In this post we’ll look at how a variable declared within a function can overshadow another variable declared outside of it.
Variable scope
Variable scope means the bounded location in the code where a variable can be used and has a meaningful value. The most prevalent scope type is local. Locally scoped variables are used within a function. We’ve seen examples of that before:
The variables “prompt_text” and “user_input” are both local variables that can be accessed within the get_integer_input method. They cannot be accessed outside this function:
The above code won’t compile as user_input is not defined at that level.
Variables can of course be declared on a higher level called global scope:
The user_input variable in the first line has global scope and the print statement will print “10”. The local user_input variable within get_integer_input has nothing to do with user_input declared globally just before. To prove this we’ll extend the code slightly:
If you run the above code and enter e.g. 40 as the input on line…
…then the print statements will give 40 and 10. The global user_input variable has been unaffected by the local user_input variable declaration and assignment.
If you use PyCharm then you’ll see a gray squiggly line underneath user_input in the get_integer_input function. If you hover over the variable you’ll see the reason: shadows name ‘user_input’ from outer scope. So user_input in get_integer_input shadows the globally declared user_input variable.
Note that there’s nothing wrong with this in a programmatic sense. The code compiles and runs and it may well have been your intention to introduce a local variable with the same name as that of a global variable. The message in PyCharm is just a safety check: did you really mean to shadow another variable or are you referring to the the global variable? In case you meant to reference the globally declared variable and change its value within the get_integer_input then the “global” keyword comes to the rescue:
Running the code with 40 as the user input will also change the value of the globally declared user_input variable to 40. The print statements will print 40 and 40 accordingly.
Name already in use
book-python / basics / function / scope.rst
- Go to file T
- Go to line L
- Copy path
- Copy permalink
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
- Values defined in function does not leak out
- Functions has access to global values
- Shadowing is when you define variable with name identical to the one from outer scope
- Shadowing in a function is valid only in a function
- After function return, the original value of a shadowed variable is restored
- global keyword allows modification of global variable
- Using global keyword is considered as a bad practice
- Values defined in function does not leak out
- Functions has access to global values
- When variable in function has the same name as in outer scope
- Shadowing in a function is valid only in a function
- Shadowed variable will be deleted upon function return
- After function return, the original value of a shadowed variable is restored
- global keyword allows modification of global variable
- Using global keyword is considered as a bad practice
- Variables defined inside function
- Variables are not available from outside
- If outside the function, will return the same as globals()
If outside the function, will return the same as globals() :
Shadowing Global Scope
- Defining variable with the same name as in outer scope
- Shadowed variable will be deleted upon function return
Shadowing of a global scope is used frequently in Mocks and Stubs. This way, we can simulate user input. Note that Mocks and Stubs will stay until the end of a program.
A Python Tutorial To Understanding Scopes and Closures.
Most documentations about programming scopes and closures almost always seem to bend towards front-end development with JavaScript. I try to provide a more general information as much as possible on the subject whilst sticking to the eccentricities of python.
Scope has to do with the access of variables. As defined here, it is the set of rules that determines where and how a variable (identifier) can be looked-up. This look-up may be for the purposes of assigning to the variable or it may be for the purposes of retrieving its value.
To understand what scopes really are, let’s examine what happens when you write a program.
LEXING / TOKENIZING.
Before a program is parsed and executed, the string of characters that make up the program — code, is broken up into meaningful (programming language-specific) chunks, called tokens. considering this python code for instance:
Before this code is executed, it is tokenized into meaningful python semantics before being parsed, generated into bytecodes and executed by the CPython compiler. Below is the disassembled byte-code representation of the python function f1 above.
The idea/concept of lexing provides the foundation to understand what lexical scope is and where the name comes from. consider this code that defines a function inside f1.
now examine the disassembled bytecodes.
The function f1 has one variable, a and f2 also has one variable, c . Considering each function as a block on it’s own, during lexing, every variable within each block is persisted to that very block. Now, the block created by each function is called a scope. This gives the idea of lexical scope.
Lexical scoping (sometimes known as static scoping ) is a convention used with many programming languages that sets the scope (range of functionality) of a variable so that it may only be called (referenced) from within the block of code in which it is defined.
Functions are the most common unit of scope, each function you declare creates a scope for itself. Whilst functions might be the basic unit of scope declaration, there are other blocks of code that define scopes. An example of such others are control flow and loop blocks.
You can think of scopes as containers. Containers that are defined by where the blocks of the container is written. There is an outer container where all containers/blocks of code are written, ie: where the b variable and f1() are declared. This container is called the global scope.
It is possible for a container to be nested within another container, with the outer one being the parent of the inner one as illustrated above with the f2() being written inside the f1() .
Variables and functions that are declared inside another function are essentially “hidden” from any of the parent “scopes” whilst variables within a parent scope is accessible within the inner scope, just as b is accessible from within f1() and a is accessible from within f2() . In compliance to the above, variable c inside f2() is “hidden” from f1() and the global scope as is a and f2() inside f1() .
VARIABLE LOOK-UPS.
when a variable is referenced, as b was in f2() , the compiler first starts it’s lookup within the innermost scope, the scope of the f2() . It won't find b there, so it goes one level up, out to the next nearest scope, the scope of f1() . It won’t find b there, so it goes one more level up to the next scope, which is the global scope, where it finds b and retrieves the value assigned to b.
Scope look-up stops once it finds the first match. The same identifier name can be specified at multiple layers of nested scope, which is called “shadowing” (the inner identifier “shadows” the outer identifier). Regardless of shadowing, scope look-up always starts at the innermost scope being executed at the time, and works its way outward/upward until the first match, and stops.
EXPLAINING SECOND DISASSEMBLED CODE AND CLOSURES.
In f2() , there is the presence of the variable a that was originally defined in f1(). That is the major idea behind closures: accessing variables that are defined outside the current scope. To fully understand closure, examine this refactored version of the second example.
In the example illustrated above, f2() was executed well outside the lexical scope of f1() but it still had access to the variable a that was defined in f1(). Considering the fact that memory is automatically garbage-collected in python, one would think that after f1() was executed, the variable a would be automatically garbage-collected. But surprisingly it wasn’t. why is that?
This is because, the inner scope of f1() was still in use by f2() . By virtue of where it was declared, f2() has a lexical scope closure over the inner scope of f1() , which keeps that scope alive for f2() to reference at any later time.
f2() still has a reference to that scope, and that reference is called closure.
So, a few microseconds later, when the variable f2 is invoked (invoking the inner function also labeled f2 ), it duly has access to author-time lexical scope, so it can access the variable a just as we'd expect.
The function is being invoked well outside of its author-time lexical scope. Closure lets the function continue to access the lexical scope it was defined in at author-time.
Whatever facility we use to transport an inner function outside of its lexical scope, it will maintain a scope reference to where it was originally declared, and wherever we execute it, that closure will be exercised. Essentially whenever and wherever you treat functions (which access their own respective lexical scopes) as first-class values and pass them around, you are likely to see those functions exercising closure.
… python is very different in a way:
When accessing a variable outside it’s scope, you cannot reference that variable and then later reassign it in the same function — variables are not hoisted. It throws an error.
When Python compiles the body of the function, it decides that a is a local variable because it is assigned within the function. The generated bytecode reflects this decision and will try to fetch a from the local environment. Later, when the call function() is made, the body of function tries to fetch the value of local variable b it discovers that b is unbound.
To bypass this, you have to explicitly state that you are referring to the global variable.
The same thing happens in closures. you cannot define use a variable from an outside scope and define the same variable in the current scope
To bypass this error, you have to explicitly state you’re not referring to this local variable.
Other languages have different implementations scopes and variable access. For instance, with JavaScript, the two examples above will not raise an error because variables are hoisted. To read more about variable hoisting, please visit this site.
Although, this tutorial is strictly based on python, most of the information provided about scopes and closures is true for most programming languages.
Please feel free to leave any comments below, in case of any misrepresentation and misunderstanding of the subject matter.