3

I understand that variables in python are always (?) available in subfunctions.

That is why this works:

def abc():
    print(a)

def main():
    abc()
    pass

if __name__=='__main__':
    a = 'a'
    main()

However, why does it not work if the definition of ais moved to main()?

def abc():
    print(a)

def main():
    a = 'a'
    abc()
    pass

if __name__=='__main__':
    main()

It is still defined before it is used and should be available in abc(), right?

mrCarnivore
  • 4,638
  • 2
  • 12
  • 29

3 Answers3

3

No, variables defined in a function are scoped to the function by default. To make it available in abc() you would need to make it global:

def main():
    global a
    a = 'a'
    abc()

As for the 'shadowing' warning, you get it when you redefine names at inner scopes. For example, this code creates a global variable a:

if __name__ == '__main__':
    a = 'a'
    main()

Now if you do a = 'b' inside main() you are effectively 'shadowing' a from the outer scope by creating a local variable with the same name.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 1
    But why do I ge a `shadows name from outer scope` warning in pyCharm every time I use the same variable name in a sub function? – mrCarnivore Aug 19 '19 at 15:42
  • 1
    You can get such warning when you redefine a global variable (i.e. defined at the module level, like `a` in your first example) inside a function. – Eugene Yarmash Aug 19 '19 at 15:48
2

In the first code sample, 'a' is defined as a global variable. Meaning that it can be accessed by any function called after it is instantiated.

In the second code sample, 'a' is defined as a local variable. Meaning that it only exists within the "main" function. If you wanted to pass it into the "abc" function, you would have to explicitly pass that variable. That would look like:

def abc(a):
   print(a)

def main():
   a = 'a'
   abc(a)
   pass

if __name__=='__main__':
   main()
Casen
  • 21
  • 1
1

Variables at the module level of your function are available to read anywhere else in the module. When you do

if __name__=='__main__':
    a = 'a'

you are defining a as a module-level variable, hence why you can read it inside abc(). This is similar to why you can see your imports within other functions.

When you define a inside abc(), it's no longer at the module-level and no longer is implicitly readable elsewhere in the module.

As an aside, global variables are usually a bad idea, it's better to pass them around explicitly. See http://wiki.c2.com/?GlobalVariablesAreBad for a good summary of why.

Tom Dalton
  • 6,122
  • 24
  • 35