Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the pythonic way to avoid shadowing variables?

I often have the following code which either leads to variable shadowing or to a multiplication of local variables

def whenadult(age):     return 18 - age  age = 5 needtowait = whenadult(age) 

age has the same logical role both when passed to the function as in the main code so I would like to avoid creating something like l_age in whenadult.

What is the pythonic way to solve the "shadowing vs. variable multiplication" dilemma?

UPDATE: following up on some comments I want to make it clear that I was looking for a Python best practice (as opposed to local vs. global variables scope)

like image 317
WoJ Avatar asked Nov 11 '13 08:11

WoJ


People also ask

How do you avoid variable shadowing?

Variable shadowing could be avoided by simply renaming variables with unambiguous names. We could rewrite the previous examples: The inner scope has access to variables defined in the outer scope.

What is shadowing a variable?

In computer programming, variable shadowing occurs when a variable declared within a certain scope (decision block, method, or inner class) has the same name as a variable declared in an outer scope.

Are global variables Pythonic?

In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function's body, it's assumed to be a local unless explicitly declared as global.

What is variable shadowing Python?

Variable shadowing occurs when a variable defined in the inner scope has the same name as a variable in the outer scope. Consider the example below, here the variable inside the function has the same name as a global variable.


2 Answers

The fact that the local variable (and function parameter) age happens to have the same name as a variable somewhere else in your program is irrelevant. The whole point of local variables is that they only live within the local scope of the function they're defined in.

The fact that the local variable has the same name as the variable used elsewhere as an argument is especially not a problem. In fact, it's very common in real-life code. For example, picking a random stdlib module, the 3.3 version of cmd, the Cmd.onecmd method has a variable named line, and it passes it as an argument to the self.default method, which binds it to a parameter that's also named line.

The fact that the variable used for the argument happens to be a global variable that you could have accessed, if you didn't have a local variable of the same name, is not a problem unless you actually wanted to access that global variable. Which you didn't want to in your existing code, and almost never should want to. In this case, and in most real-world cases, it's simply a coincidence that means nothing and affects nothing, not a problem you have to solve.


The problem you're having is that PyCharm can't guess whether you wanted the global age to be accessible in whenadult. Is it possible (if not in this trivial case, maybe in more complex cases) that a human might be similarly confused, slowing down his comprehension of your code? Or that you'll one day have to write code in some environment where your code reviewers or teacher or whatever will reject your code because it doesn't pass some linter with no warnings? Maybe.

But really, in any such environment, they'd probably complain about you using global variables in the first place. And you really don't need to here. The only reason age is a global is that it has to be accessible to the top-level code. If you move that code into a function, age can become a local in that function. For example:

def whenadult(age):     return 18 - age  def main():     age = 5     needtowait = whenadult(age)  main() # possibly with an if __name__ == '__main__' guard 

This will make PyCharm happy, and any linter tools, and any easily-confused or rigidly-minded human readers. It'll even make your code a tiny bit faster. On the other hand, it's more code to read—only three lines and one indent, but then the whole program is only eight lines long. So, it's a tradeoff that you can make on a case-by-case basis.

like image 92
abarnert Avatar answered Oct 05 '22 04:10

abarnert


Whenever I got the warning of shadowing variable in PyCharm. I would try to rename the local variable to use the underscore prefix as the convention. That's another way to consider in addition to wrap global variables into a main() function.

    def whenadult(_age):         return 18 - _age      age = 5     needtowait = whenadult(age) 
like image 43
Devy Avatar answered Oct 05 '22 03:10

Devy