This article was originally published in love butterfly blog (http://blog.csdn.net/lanphaday), welcome to reprint, but must retain this statement and not for commercial purposes. Thank you.
Introduction
I warmly invite you to guess the output of the following program:
Class A (object ):
Def _ init _ (Self ):
Self. _ private ()
Self. Public ()
Def _ private (self ):
Print 'a. _ private ()'
Def public (Self ):
Print 'a. Public ()'
Class B ():
Def _ private (self ):
Print 'B. _ private ()'
Def public (Self ):
Print 'B. Public ()'
B = B ()
Preliminary Exploration
The correct answer is:
A. _ private ()
B. Public ()
If you have guessed it, you can skip this blog. If you haven't guessed it or have some questions, I have prepared this blog for you.
The reason for the output is "A. _ private. But to clarify why, we need to understand the python naming mechanism.
According to Python manual, the variable name (identifier) is an atomic element of Python. When a variable name is bound to an object, the variable name refers to this object, just like in human society, isn't it? When the variable name appears in the code block, it is the local variable; when the variable name appears in the module, it is the global variable. I believe everyone has a good understanding of the module, but the code block may be confusing. Here we will explain:
A code block is a piece of Python program text that can be used as an executable unit. modules, function bodies, and class definitions are all code blocks. In addition, each interactive script command is also a code block, a script file is also a code block, and a command line script is also a code block.
Next we will talk about the visibility of variables. We will introduce the concept of a range. The range is the visibility of variable names in the code block. If a code block defines local variables, the range includes this code block. If a variable is defined in a function code block, the range is extended to any code block in the function block unless another variable with the same name is defined. But the scope of variables defined in the class is limited to the class code block, instead of being extended to the method code block.
Lost
According to the theory above, we can divide the code into three code blocks: Class A, Class B, and variable B. According to the class definition, we know that the Code defines three member variables for Class A (Python functions are also objects, so the Member methods can also be called member variables .); Class B defines two member variables. This can be verified by the following code:
>>> Print '\ n'. Join (Dir ())
_ A _ private
_ Init __
Public
>>> Print '\ n'. Join (Dir (B ))
_ A _ private
_ B _ private
_ Init __
Public
Why does Class A have an attribute named _ A _ private? And _ private disappears! Now let's talk about the rolling of Python's private variables.
Exploration
Anyone familiar with Python knows that python treats a variable that starts with two or more underscores and does not end with two or more underscores as a private variable. Private variables are converted to long format (public) before code generation ). The conversion mechanism is as follows: insert the class name at the front end of the variable, and add an underline character at the front end. This is the so-called private name mangling ). For example, the _ private identifier in Class A will be converted to _ A _ private, which is why _ A _ private and _ private disappear in the previous section.
Let's talk about two more things:
First, the identifier is longer due to rolling. When it exceeds 255, python will cut off. Note the naming conflict caused by this.
Second, when all the class names are named below, python will not execute rolling. For example:
>>> Class ____ (object ):
Def _ init _ (Self ):
Self. _ method ()
Def _ method (Self ):
Print '____. _ method ()'
>>> Print '\ n'. Join (Dir (____))
_ Class __
_ Delattr __
_ Dict __
_ Doc __
_ Getattribute __
_ Hash __
_ Init __
_ Method # not rolled
_ Module __
_ New __
_ Reduce __
_ Performance_ex __
_ Repr __
_ Setattr __
_ STR __
_ Weakref __
>>> OBJ = ____()
____. _ Method ()
>>> Obj. _ method () # can be called externally
____. _ Method ()
Now let's look at why "A. _ private ()" is output!
Truth
I believe that smart readers have already guessed the answer? If you haven't thought of it, I will give you a prompt: The truth is similar to macro preprocessing in C language.
Because Class A defines a private member function (variable), execute the private variable rolling before the code is generated (note that the line marked with red in the previous section does not exist ?). After the rolling, the code of Class A becomes like this:
Class A (object ):
Def _ init _ (Self ):
Self. _ A _ private () # This line has changed
Self. Public ()
Def _ A _ private (self): # This line has also changed
Print 'a. _ private ()'
Def public (Self ):
Print 'a. Public ()'
Is it a bit like the macro development in C language?
Because the _ init _ method is not overwritten when class B is defined, the call is still. _ init __, that is, self. _ A _ private (), which naturally outputs ". _ private.
The following two sections of code increase persuasiveness and increase understanding:
>>> Class C ():
Def _ init _ (Self): # rewrite _ init __and no longer call self. _ A _ private
Self. _ private () # _ c_private is bound here.
Self. Public ()
Def _ private (self ):
Print 'C. _ private ()'
Def public (Self ):
Print 'C. Public ()'
>>> C = C ()
C. _ private ()
C. Public ()
############################
>>> Class A (object ):
Def _ init _ (Self ):
Self. _ A _ private () # Call an undefined function. python will give it to my handler _^ ~
Self. Public ()
Def _ private (self ):
Print 'a. _ private ()'
Def public (Self ):
Print 'a. Public ()'
>>> A = ()
A. _ private ()
A. Public ()