Python is an object-oriented language, and the classes in Python provide all of the object-oriented features: polymorphism, encapsulation, and inheritance.
1) polymorphic: The same action can be used on different objects, which behaves differently depending on the type of object (or Class);
2) Encapsulation: The work details of hidden objects in the external world;
3) Inheritance: Establish a specific class object based on a common class.
For more object-oriented concepts, refer to specialized object-oriented books, which describe how classes are defined and used in Python.
Defining classes
Here is the simplest form of defining a class:
Class ClassName: <statement-1> ... <statement-N>
A class is like a function, which must be defined before it can be used (support for placing the definition of a class in a branch of an if statement, or inside a function).
In practice, a class is usually a function definition, but other statements are allowed, which is useful at some point, which is detailed later. A function definition in a class usually has a specific form of parameter list, which is also detailed later.
The inside of the class has its own scope and namespace, and all local variables enter the namespace of the class. In particular, a function definition binds a new function name.
After the class definition has ended normally, a class object is created, which is basically the encapsulation of the contents of the namespace created by the class definition, which we will describe in detail below.
Property references and instantiation of a class
The class object supports two operations: Property Reference and instantiation.
The attribute reference uses that standard syntax: Obj.name. When a class is created, all names in the namespace of the class are valid property names. For example, if the class is defined as follows:
Class MyClass: "" " A Simple Example Class" "" i = 12345 def f (self): return ' Hello World '
Then myclass.i and MYCLASS.F are valid property references, returning an integer and a function object, respectively. Class properties can also be assigned, so you can modify the value of the assigned myclass.i. __DOC__ is also a valid property that returns the class's document string, that is: "A Simple Example Class".
Class instantiation uses that function symbol, just as a class object is a parameterless function that returns a new instance of the class. For example:
x = MyClass ()
This creates a new instance of the class and assigns the object to the local variable x.
Instantiating an operation (called a class object) creates an empty object, and some classes may want to set the initial state of the object when the object is created, and you can define a specific method of the class __init__ (), for example:
def __init__ (self): self.data = []
When the class defines the __init__ () method, the class instantiation automatically calls __init__ (). In this example, the new instance can be obtained in the following way and has a data property:
x = MyClass ()
__init__ () can also pass in parameters, and arguments are passed to __init__ () through the instantiation of the class, for example:
>>> class Complex: def __init__ (self, Realpart, Imagpart): SELF.R = realpart self.i = Imagpart >>> x = Complex (3.0, -4.5) >>> X.R, x.i (3.0,-4.5)
Properties and methods for instance objects
What can we do with the instance object next? The instance object supports only property references, and there are two valid property names: Data properties and methods.
The data properties correspond to "instance variables" in Smalltalk and "data members" in C + +. Data attributes do not need to be defined, with local variables, which are automatically defined when used for the first time. For example, assuming that X is an instance of the MyClass defined above, the following code will print 16:
X.counter = 1while X.counter <: X.counter = X.counter * 2print (x.counter) del X.counter
Another property reference to an instance object is a method, and a method is a function that belongs to an object.
The valid method name of the instance object depends on its definition in the class, in the example above, the X.F value is a valid method reference, because MYCLASS.F is a function, but x.i is not. But note that unlike X.F and MYCLASS.F, X.f is a method object, and MYCLASS.F is not.
Method invocation
Typically, a method is called using the following method:
X.F ()
In the case of MyClass, this call will return ' Hello World '. You can also pay the method to another variable, which is called later:
XF = x.fwhile True: print (XF ())
What happens when a method is called? You may have noticed that although F () specifies a parameter when it is defined, it does not need to pass in the parameter when it is called, what is the reason? When a function requires a parameter, and the call is not passed in, Python throws an exception, which is OK. As you may have guessed, the first parameter of the method is the object itself, in our case, calling X.F () is equivalent to calling MYCLASS.F (x), and generally, invoking an n parameter is equivalent to calling a function with the same n parameters and inserting the object to which the method belongs before the first argument.
If you do not understand how the method works, then this is the concrete implementation of the method invocation: When an instance property is referenced (not a data attribute), its class will be found; If the property name is a valid class property and is a function object, a method object is created and points to the instance object When this method object is called with a parameter list, a new argument list with the instance object and invocation is constructed and used to invoke the function object.
Class and instance variables
Typically, instance variables correspond to each specific instance, and class variables correspond to instances of all classes:
Class Dog: kind = ' Canine ' # class variable shared by all instances def __init__ (self, name): self.name = Name # instance variable unique to each instance>>> D = Dog (' Fido ') >>> e = Dog (' Buddy ') >>> D.kind # shared by all dogs ' canine ' >>> e.kind # Gkfx by all dogs ' canine ' >>> d.name # Uniq UE to d ' Fido ' >>> e.name # unique to E ' Buddy '
Here dog.kind are class variables, and name is an instance variable, and class variables can be shared among different instances of the class, while instance variables correspond to each instance of the class.
It is important to note that shared data can cause some surprising behavior, for example, a list in the following code is shared between different objects:
Class Dog: tricks = [] # Mistaken use of a class variable def __init__ (self, name): self.name = name D EF Add_trick (self, trick): self.tricks.append (trick) >>> d = Dog (' Fido ') >>> e = Dog (' Buddy ') > >> D.add_trick (' Roll over ') >>> E.add_trick (' Play Dead ') >>> d.tricks # unexpectedly shared By all dogs[' roll over ', ' play dead '
Because the class variable tricks can be shared by all instances of the class, the data in the list will be unpredictable and may cause some strange behavior, and the correct approach should be to provide a tricks variable for each instance object:
Class Dog: def __init__ (self, name): self.name = name self.tricks = [] # Creates a new empty list for each Dog def add_trick (self, trick): self.tricks.append (trick) >>> d = Dog (' Fido ') >>> e = Dog (' Buddy ') >>> d.add_trick (' Roll over ') >>> E.add_trick (' Play Dead ') >>> d.tricks[' roll over '] >>> e.tricks[' play dead ']
class's data properties and Method properties
If the data and method properties of a class have the same name, some bugs that are difficult to find can be raised in large programs. Therefore, in order to avoid name collisions, it is necessary to use some naming conventions to minimize conflicts. Possible conventions include uppercase method names, using a small, unique string (perhaps just an underscore) as a prefix for data property names, or using verb nouns for data properties and methods.
Data properties can be referenced by the object's consumer or by a method. In other words, a class cannot implement purely abstract data types, and in fact Python cannot implement data hiding, all based on conventions.
Use of the data attribute should be very careful, if you modify the value of the variable, it may affect the execution of methods dependent on this variable. Users can also add their own data properties to instance objects, but they need to avoid name collisions, so naming conventions can reduce a lot of headaches.
Using methods to reference data properties tends to increase readability, and users are less likely to confuse local variables and instance variables.
The first parameter of the method is usually self, but this is only a convention, but adherence to this Convention tends to make it easier for other Python programmers to read your code and be automatically generated by the editor.
A function object is not necessarily defined in a class definition, it is possible to define a function first, and then assign it to a local variable of the class, for example:
Def f1 (self, x, y): return min (x, X+y) class C: f = F1 def g (self): return ' Hello world ' h = g
Now F, G, and H are all properties of Class C, execute a Function object, and all will become instances of C (H and G are exactly equivalent). However, this in practice leads to poor readability of the code and does not bring real benefits.
Method can invoke other methods through the self parameter, for example:
Class Bag: def __init__ (self): self.data = [] def add (self, x): self.data.append (x) def addtwice ( Self, x): self.add (x) Self.add (x)
Method can also refer to a global name (variable or function), you need to introduce a module that contains the name definition before the reference.
Each value has an object, so there is a class (also called a type) that is stored in the object.__class__:
>>> a = 1>>> a.__class__<class ' int ' >>>> a = 1.1>>> a.__class__<class ' Float ' >>>> class Bag: def __init__ (self): self.data = [] def add (self, x): Self.data.append (x) def addtwice (self, x): self.add (x) self.add (x) >>> Bag.__class__<class ' Type ' >
Inherited
The definition syntax for derived classes in Python is as follows:
Class Derivedclassname (baseclassname): <statement-1> ... <statement-N>
Aseclassname is the name of the base class, and it also supports adding a module prefix to the name of the base class, for example:
Class Derivedclassname (ModName. Baseclassname):
The execution processing of a derived class definition is the same as the base class, when the class object is constructed and the base class is saved. When the requested attribute in the class is not found, search in the base class until it reaches the topmost base class.
The instantiation of a derived class is also the same as the base class: Derivedclassname () Creates a new instance of a class. The method reference takes the following principle: First, search for the class attribute, searching the base class until the final base class.
A derived class can overload a method of a base class, and if a method of a base class is overloaded, if another method in the base class calls the method, the method that is overloaded in the subclass is actually called.
If you want to call a method of a base class in a derived class, there is a direct way: Call Baseclassname.methodname (self, arguments).
There are two methods in Python that you can use to investigate an inheritance relationship:
1) isinstance ()
Check the type of an instance: if Isinstance (obj, int) returns TRUE, then obj.__class__ must be a subclass of int or int.
2) Issubclass ()
Used to check the inheritance relationship of a class: Issubclass (bool, int) returns TRUE because BOOL is a subclass of Int. However, Issubclass (float, int) returns false because float is not a subclass of Int.
In addition, the class has a property __bases__ can see all the base classes of the class, you may notice that here bases is a complex number, that is, it implies that the base class may have more than one.
Multiple inheritance
Python supports multiple inheritance, and a class can define multiple base classes:
Class Derivedclassname (Base1, Base2, Base3): <statement-1> ... <statement-N>
Simply put, under multiple inheritance, the search for the properties of a class takes a deep traversal, left to right order. Therefore, if an attribute is not in Derivedclassname, the Base1 is searched, the base class of Base1 is searched, and if no discovery is found, the Base2 is searched, and so on.
Therefore, when a method inherits from more than one superclass, you must pay attention to the order of the superclass: The method in the class that inherits first overrides the method in the inherited class. If the superclass shares a superclass, the order in which the superclass is accessed in the search for a given method or attribute becomes the MRO (method Resolution order).
In the complexity of multiple inheritance, it is recommended that you avoid it as much as possible, because sometimes unforeseen problems arise.
Private variables
There is no private variable in Python, but there is a convention that is followed by most Python code: a name prefixed with ' _ ' should be used as a non-public part of the API (whether it is a function, method, or data member) and it should be modified without notice.
Python provides a preliminary form of the private nature of a class element, a property that starts with a double underscore (which is actually at least two underscores, with an underscore ending) that is confused at run time and cannot be accessed directly, for example:
>>> Class Test:__a_ = "This is a Test." >>> t = Test () >>> T.__a_traceback (most recent call last): File "<pyshell#71>", line 1, in < ;module> t.__a_attributeerror: ' Test ' object has no attribute ' __a_ '
The ambiguous name is preceded by an underscore and a class name, which is _classname__. Therefore, the variable __a_ in class Test becomes _test__a_ when it is confused:
>>> T._test__a_ ' This is a Test. '
This provides some level of privatization, and another purpose of name obfuscation is to protect the __XXX variable from the parent namespace, and the parent class's __xxx variable is not overwritten by the quilt class. For example:
>>> class Test:def Test (self):p rint ("It is base.") __test = Testdef dotest (self): Self.__test () >>> class Testsubclass (test):d the EF test (self):p rint Subclass. ") >>> a = Test () >>> B = Testsubclass () >>> a.test () This is base.>>> a.dotest () the IS BAS E.>>> B.test () This is subclass.>>> b.dotest () the IS base.
Python13: Class