python global operator emulation

Viewed 69

in Lutz's book I read how to emulate global operator in a function body. I created p.py file in documents folder:

var = 0
def func():
    import p #import itself
    p.var = 15
func()
print(var)

output:

15
0

I thought is is supposed to simply print 15, but by some reason it also added 0 to output. So I'm wandering why has it happened.

for example, when i do the same thing in terminal, but in the main module, it works as I want:

var = 0
def func():
    import __main__ #import itself
    __main__.var = 15
func()
print(var)

and output is

15

I have python 3.7.7

2 Answers

Files are not modules: files are used to define modules. If you run p.py as a script that contains import p, there are two modules, __main__ and p, both created from the same file, but each with its own global namespace.

Okay, let's break this into few steps.

  • First of all:

self-importing of a module is not a good thing to do - one example why is because of the things you noticed in your question.

import p #
var = 0
def func():
    p.var = 15
func()
print(var)
print(p.var)

Running this, you will notice that var and p.var are actually 2 separate variables, even though logically they are the same thing, just in a different namespace. You've also got func and p.func, which again do the same but are 2 separate things.

  • Second problem:

Global keyword should be used only when absolutely necessary. When you have a global variable, it is much harder to track when it changes and control the flow of your program - Global Variables Are Bad (not everything applies to Python, but most points still stand).

  • Finally, why you are actually seeing the behaviour you see:

In Python when the module is imported, all of it is executed just like the main script you are running. Let's say you have pr.py file containing only this:

print("text")

Importing such a module with import pr would be enough to see text on console, because it gets executed on import. That's why you see 15 printed (in import p, print(var) happens - and because we are in module p, p.var and var are the same here). Then import p finishes and we get to print(var) - but because we are now in __main__ module, var is not the same as p.var, and it still has the original value of 0.

Why does import __main__ work different? It's because it is handled specially by Python, as can be read here. In short, __main__ is initialised from the start of the program, so import __main__ does not cause the code to run again, just like importing some module more only causes it to be executed once.

Related