Consider the following code, why don't I need to pass x to Y?
class X: def __init__(self):self.a = 1self.b = 2self.c = 3class Y: def A(self):print(x.a,x.b,x.c)x = X()
y = Y()
y.A()
Thank you to the top answers, they really helped me see what was the problem, namely misunderstanding regarding variable scope. I wish I could choose both as correct answer as they are enlightening in their own way.
When python compiles a def
into a function, it tries to figure out if the things you are referencing are locals - and if they're not, you must be referring to a global. For example:
def f():print(x)
Well, you haven't defined x
within the scope of f
, so you must be referring to a global.
This is all that's happening in your above code. You haven't defined x
within the scope of A
, so x
must be a global. As it happens, you define the global:
x = X()
before you call it:
y = Y()
y.A()
so everything works out okay.
In case you are going "hm, I'm not sure if I believe you, roippi" just look at the bytecode:
dis.dis(Y.A)3 0 LOAD_GLOBAL 0 (print) 3 LOAD_GLOBAL 1 (x) # aha6 LOAD_ATTR 2 (a) 9 LOAD_GLOBAL 1 (x) # aha!12 LOAD_ATTR 3 (b) 15 LOAD_GLOBAL 1 (x) # aha!!18 LOAD_ATTR 4 (c) 21 CALL_FUNCTION 3 (3 positional, 0 keyword pair) 24 POP_TOP 25 LOAD_CONST 0 (None) 28 RETURN_VALUE
aha.