Python class: class creation, data method attributes and access control details, python Access Control
In Python, you can use the class keyword to define your own class, and then create an instance object through the custom class Object class.
Create a class in python
Create a Student class and implement the class's initialization function "_ init __":
Class Student (object ):
Count = 0
Books = []
Def _ init _ (self, name ):
Self. name = name
Next, let's take a look at the class-related content in Python through the Student class above.
Class Construction and initialization
Connections and differences between "_ init _" and "_ new _"
The following code shows the call sequence of the two methods:
class A(object): def __init__(self,*args, **kwargs): print "init %s" %self.__class__ def __new__(cls,*args, **kwargs): print "new %s" %cls return object.__new__(cls, *args, **kwargs) a = A()
The code output shows that when an object is instantiated through a class, the "_ new _" method is called first and then the "_ init _" method.
In general, the "_ init _" and "_ new _" functions have the following forms:
def__init__(self,*args,**kwargs): # func_suite def__new__(cls,*args,**kwargs): # func_suitereturnobj
"_ New _" and "_ init _" can be summarized as follows:
• The "_ new _" method is a real Constructor (create and return an instance) in Python. Through this method, an instance object corresponding to "cls" can be generated, therefore, the "_ new _" method must have a return value.
• The "_ init _" method is an initialization method. "self" indicates the instance object generated by the class, "_ init _" Will initialize the object accordingly.
_ New _ features
"_ New _" is a new method in the new class. It has the following behavior characteristics:
• The "_ new _" method is the first method called when the class instantiates an object. It returns the instance object.
• The "_ new _" method is always a static method of the class (that is, the first parameter is cls), even if the static method modifier is not added
• The first cls parameter is the currently instantiated class. To obtain the instance of the current class, the _ new _ method of the parent class of the current class should be called in the "_ new _" method statement of the current class.
For the third point above, if the current class is directly inherited from the object, the object returned by the "_ new _" method of the current class should be:
def __new__(cls, *args, **kwargs): # func_suitereturn object.__new__(cls, *args, **kwargs)
Rewrite _ new __
If the (new) class does not overwrite the "_ new _" method, by default, Python calls the "_ new _" method of the direct parent class of this class to construct the instance of this class. If the parent class of this class is not overwritten __", the "_ new _" method of the object will be traced back to the same rule, because the object is the base class of all new classes.
If the "_ new _" method is rewritten in the new class, you can select any other new class (it must be a new class, only new classes have "_ new _", because all new classes are derived from objects.) The "_ new _" method is used to create instances, including all the previous and descendant classes of this new class, as long as they do not cause recursive endless loops.
Let's take a look at the example code:
ClassFoo (object): def _ new _ (cls, * args, ** kwargs): obj = object. _ new _ (cls, * args, ** kwargs) # The object here. _ new _ (cls, * args, ** kwargs) is equivalent to # super (Foo, cls ). _ new _ (cls, * args, ** kwargs) # object. _ new _ (Foo, * args, ** kwargs) # Bar. _ new _ (cls, * args, ** kwargs) # Student. _ new _ (cls, * args, ** kwargs). It is allowed even if Student has no relationship with Foo, because Student is a new class derived from an object # in any new class, you cannot call your own "_ new _" to create an instance, because this will cause an endless loop # Avoid return Foo. _ new _ (cls, * args, ** kwargs) or return cls. _ new _ (cls, * args, ** kwargs) print "Call _ new _ for % s" % obj. _ class _ returnobj classBar (Foo): def _ new _ (cls, * args, ** kwargs): obj = object. _ new _ (cls, * args, ** kwargs) print "Call _ new _ for % s" % obj. _ class _ returnobj classStudent (object): # Student does not have the "_ new _" method, the "_ new _" method of its parent class is automatically called to create an instance. _ new _ (cls) pass classCar (object): def _ new _ (cls, * args, ** kwargs ): # You can use Bar to create an instance obj = object. _ new _ (Bar, * args, ** kwargs) print "Call _ new _ for % s" % obj. _ class _ returnobj foo = Foo () bar = Bar () car = Car ()
The code output is:
_ Init _ call
"_ New _" determines whether to use the "_ init _" method of the class, because "_ new _" can call the constructor of other classes or directly return the objects created by other classes as instances of this class.
Generally, when a new class starts to be instantiated, the "_ new _" method returns the instance of cls (cls refers to the current class, then, the "_ init _" method of the class is called as the initialization method. This method receives this instance (that is, self) as its first parameter, input the location parameters and name parameters received in the "_ new _" method in sequence.
However, if "_ new _" does not return the cls (current class) instance, the "_ init _" method of the current class will not be called.
Example:
class A(object): def __init__(self, *args, **kwargs): print "Call __init__ from %s" %self.__class__ def __new__(cls, *args, **kwargs): obj = object.__new__(cls, *args, **kwargs) print "Call __new__ for %s" %obj.__class__ return obj class B(object): def __init__(self, *args, **kwargs): print "Call __init__ from %s" %self.__class__ def __new__(cls, *args, **kwargs): obj = object.__new__(A, *args, **kwargs) print "Call __new__ for %s" %obj.__class__ return obj b = B()print type(b)
In the Code, in the "_ new _" method of B, use "obj = object. _ new _ (A, * args, ** kwargs) "creates an instance of A. In this case, the "_ init _" function of B will not be called.
Derived immutable type
Another important purpose of the "_ new _" method is to derive an unchangeable type.
For example, in Python, float is of an unchangeable type. If you want to derive a subclass from float, you must implement the "_ new _" method:
classRound2Float(float): def__new__(cls,num): num=round(num,2) #return super(Round2Float, cls).__new__(cls, num) returnfloat.__new__(Round2Float,num) f=Round2Float(4.14159)printf
In the code, a Round2Float class is derived from float. the instance of this class is a floating point number that retains the last two digits of the decimal point.
You can use the built-in function dir () or the dictionary attribute _ dict __of the category class to view the attributes of the class.
Data attributes
Class data attributes and instance data attributes
In the Student class above, "count" "books" "name" and "age" are both called class data attributes, but they are classified into class data attributes and instance data attributes.
Class variables are defined immediately after the class name, which is equivalent to static variables of java and c ++.
Instance variables are defined in _ init _, which is equivalent to common variables in java and c ++.
>>> Class test:
Count = 0; Class variable
Def _ init _ (self, c ):
Self. count = c; instance variable
Self. _ class _. count = self. _ class _. count + 1;
>>> A = test (3)
>>> A. count
3
>>> Test. count
1
For the class data attributes and instance data attributes, We can summarize them as follows:
1. The class data attribute belongs to the class itself and can be accessed/modified by the class name
2. The class data attribute can also be accessed/modified by all instances of the class.
3. After the class is defined, You can dynamically add class data attributes using the class name. The newly added class attributes are also shared by the class and all instances.
4. instance data attributes can only be accessed through instances
5. After an instance is generated, You can dynamically add instance data attributes. However, these instance data attributes only belong to this instance.
Special class attributes
All classes have a special set of attributes:
Class attributes |
Description |
_ Name __ |
Class Name (string) |
_ Doc __ |
Class document string |
_ Bases __ |
Tuples composed of all the parent classes of the class |
_ Dict __ |
Dictionary composed of class attributes |
_ Module __ |
Module to which the class belongs |
_ Class __ |
Class Object Type |
Note: The document string is unique for classes, functions, methods, and modules. In other words, the _ doc _ attribute cannot be inherited from the parent class.
Hide attributes
As mentioned above, the class data attribute belongs to the class itself and is shared by all instances of the class. In addition, you can access/modify the class attribute through the instance.
However, you must be cautious when using the category attribute in the instance, because the property may be "hidden.
Continue to use the Student class above to see if the property is hidden:
Wilber = Student ("Wilber", 28)
Print "Student. count is wilber. count:", Student. count is wilber. count
Wilber. count = 1
Print "Student. count is wilber. count:", Student. count is wilber. count
Print Student. _ dict __
Print wilber. _ dict __
Del wilber. count
Print "Student. count is wilber. count:", Student. count is wilber. count
Print
Wilber. count + = 3
Print "Student. count is wilber. count:", Student. count is wilber. count
Print Student. _ dict __
Print wilber. _ dict __
Del wilber. count
Print
Print "Student. books is wilber. books:", Student. books is wilber. books
Wilber. books = ["C #", "Python"]
Print "Student. books is wilber. books:", Student. books is wilber. books
Print Student. _ dict __
Print wilber. _ dict __
Del wilber. books
Print "Student. books is wilber. books:", Student. books is wilber. books
Print
Wilber. books. append ("CSS ")
Print "Student. books is wilber. books:", Student. books is wilber. books
Print Student. _ dict __
Print wilber. _ dict __
The code output is:
Analyze the output of the above Code:
• Student. count can be accessed through the instance wilber and "Student. count is wilber. count"
• When you assign values or modify the count attribute through an instance, a new count instance attribute is created for the instance wilber. At this time, "Student. count is not wilber. count"
• When the "del wilber. count" statement is used to delete the instance's count attribute, it becomes "Student. count is wilber. count" again"
• Student. books can also be accessed through the wilber instance for variable type class attributes, and "Student. books is wilber. books"
• When the books attribute is assigned to an instance, a new book instance attribute is created for the wilber instance. In this case, "Student. books is not wilber. Books"
• When the "del wilber. books" statement is used to delete the books attribute of an instance, it becomes "Student. books is wilber. books" again"
• When modifying the books attribute through an instance, modify the memory address (Student. books) pointed to by wilber. books. At this time, "Student. Books is wilber. books"
Note: although you can use the instance to configure class attributes, it is not recommended that you do so. It is best to use the class name to configure class attributes, so as to avoid unnecessary trouble caused by property hiding.
Method
In a class, there may be three methods: instance method, static method, and class method. Let's take a look at the differences between the three methods.
Instance method
The first parameter of the instance method must be "self", and "self" is similar to "this" in C ++ ".
The instance method can only be called through a class instance. "self" indicates the class instance itself. You can directly access the attributes of an instance through "self.
Class Method
The class method uses cls as the first parameter. cls indicates the class itself and uses @ classmethod for definition. You can use cls to define the relevant attributes of a class.
Class Student (object ):
'''
This is a Student class
'''
Count = 0
Books = []
Def _ init _ (self, name, age ):
Self. name = name
Self. age = age
@ Classmethod
Def printClassInfo (cls ):
Print cls. _ name __
Print dir (cls)
Pass
Student. printClassInfo ()
Wilber = Student ("Wilber", 28)
Wilber. printClassInfo ()
The code output shows that class methods can be accessed by class names or instances.
Static Method
Unlike the instance method and class method, the static method has no parameter restrictions, neither instance parameters nor class parameters are required, and the @ staticmethod modifier is used for definition.
Similar methods are the same. Static methods can be accessed by class names or instances.
class Student(object): ''' this is a Student class ''' count = 0 books = [] def __init__(self, name, age): self.name = name self.age = age @staticmethod def printClassAttr(): print Student.count print Student.books pass Student.printClassAttr() wilber = Student("Wilber", 28)wilber.printClassAttr()
The main difference between the three methods is that the instance method is bound to an instance and can only be called through the instance. However, for static and class methods, you can call a service by using the class name and instance.
Access Control
There are no access control keywords in Python, such as private and protected.
However, there are some conventions in Python encoding for access control.
The use of "_" and "_" is more of a specification/Convention, and does not really achieve the purpose of restrictions:
"_": A variable starting with a single underline represents a protected type, that is, it can only be accessed with its own subclass; it also indicates weak internal variable identifier, such, when "from moduleNmae import *" is used, objects starting with an underscore are not introduced.
"_": Double underscores indicate private variables. This class can only be accessed by itself, and even the subclass is not allowed. This type of attribute name will be added with a single underline and class name at runtime.
Single underline "_"
In Python, the module-level privatization is achieved through a single underscore (_). Generally, the variables and functions starting with a single underscore (_) are private to the module, that is to say, "from moduleName import *" will not introduce variables and functions starting.
There is a module lib. py with the following content. A variable name and a function name in the module start with "_" respectively:
numA = 10_numA = 100 def printNum(): print "numA is:", numA print "_numA is:", _numA def _printNum(): print "numA is:", numAprint "_numA is:", _numA
After using the following code to introduce the lib. py module, all variables and functions starting with "_" are not introduced. If you access the module, an exception is thrown:
from lib import *print numAprintNum() print _numA#print _printNum()
Double underline "__"
For class attributes in Python, double underscores (_) can be used to privatize them to a certain extent, because attributes starting with double underscores (_) are "mangling" at runtime ).
In the Student class, a "_ address" attribute is added:
class Student(object): def __init__(self, name, age): self.name = name self.age = age self.__address = "Shanghai" pass wilber = Student("Wilber", 28)print wilber.__address
When you access this attribute through the wilber instance, an exception is displayed, indicating that the attribute "_ address" does not exist.
In fact, you can see some of the reasons through the built-in function dir (). When the "_ address" attribute is running, attribute name changed to "_ Student _ address" (single underline and class name added before attribute name)
>>> wilber = Student("Wilber", 28)>>> dir(wilber)['_Student__address', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name']>>>
In this case, even double underscores (_ address) do not privatize attributes, because the following method can still directly access the "_ address" attribute:
>>> wilber = Student("Wilber", 28)>>> print wilber._Student__addressShanghai>>>
Another important purpose of double-underline
Avoid subclass conflicts with attributes with the same name of the parent class.
Let's look at the following example:
class A(object): def __init__(self): self.__private() self.public() def __private(self): print 'A.__private()' def public(self): print 'A.public()' class B(A): def __private(self): print 'B.__private()' def public(self): print 'B.public()' b = B()
When B is instantiated, because the _ init _ function is not defined, the _ init __of the parent class will be called. However, due to the double-Underline "obfuscation" effect, "self. _ private () "will be changed to" self. _ A _ private ()".
The following figure shows the output:
A. _ private ()
B. public ()
The above python class: class creation, data method attributes, and access control details are all the content that I have shared with you. I hope you can give us a reference and support for more.