Reputation: 143
class Test:
__x = 1
class C:
def test(self):
print(Test.__x)
c = C()
a = Test()
a.c.test()
I get Error Information like this
AttributeError: type object 'Test' has no attribute '_C__x'
So, is it inner class cannot get access to outer class? Or It can be using some other techniques?
And this questions comes from reading Learning Python, when author write about CardHolder, a inner class as a descriptor use instance.__name to reach the outer class' attribute, so what is the rule of whether can we access __X attribute?
Thank you for reading my problem.
Upvotes: 4
Views: 1161
Reputation: 6288
Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.
class Test:
__x = 1 # <= A
class C:
def test(self):
print(Test.__x) # <= B
c = C()
A
the class is Test
and therefore __x
is replaced with _Test__x
, So, Test
actually have the attribute _Test__x
B
the class is C
and therefore __x
is replaced with _C__x
, So the attribute you actually access is Test._C__x
To access 'private' __x
attribute of Test
class outside Test class definition you should use: Test._Test__x
print(Test._Test__x)
Upvotes: 2
Reputation: 3452
Adding to underscores is the proper way to declare private attributes in Python. Your code would work fine if you changed the name of __x
to _Test__x
when you call it from the other class.
class Test:
__x = 1
class C:
def test(self):
print(Test._Test__x)
c = C()
def test2(self):
print self.__x
a = Test()
a.test2() # prints 1
a.c.test() # prints 1
This tutorial goes in the details of it. The rule is: you have to be in the class to call it directly. Subclasses won't work, but methods will.
Upvotes: 1