table of Contents
1. The composition of the class
2. Look at the concept through the code (the composition of the class)
0. What is OOP
Readers must have heard the saying "everything is an object" in Python , but may not understand its specific meaning, but when learning Python is an object-oriented programming language. Object-oriented programming is developed on the basis of process-oriented programming. It has stronger flexibility and scalability than process-oriented programming. Object-oriented programming is a watershed in the development of programmers. Many beginners will give up learning programming because they cannot understand object-oriented programming. Classes and objects are important features of Python. Compared with other object-oriented languages, Python can easily create a class and object. At the same time, Python also supports three object-oriented features: encapsulation, inheritance, and polymorphism.
Object-oriented Programming (OOP) is a method of encapsulating code. In fact, in the study of the previous chapters, we have already touched on encapsulation. For example, throwing messy data into the list is a simple encapsulation, which is a data-level encapsulation; package commonly used code blocks into a function , This is also a kind of encapsulation, it is a statement-level encapsulation.
Code encapsulation, in fact, hides the specific code that implements the function, leaving only the interface for the user to use, just like using a computer. The user only needs to use the keyboard and mouse to achieve some functions without knowing how its internals work.
In object-oriented, commonly used terms include:
- Class: Understandably is a template, through which countless specific instances can be created. For example, the tortoise written earlier represents only the species of tortoise, through which countless instances can be created to represent tortoises with different characteristics (this process is also called instantiation of classes).
- Object: The class cannot be used directly, only the instance (also known as the object) created by the class can be used. This is a bit like the relationship between car drawings and cars. The drawings themselves (classes) cannot be used by people. Only cars (objects) created through drawings can be used.
- Attributes: All variables in the class are called attributes. For example, in the tortoise class, bodyColor, footNum, weight, and hasShell are all attributes of this class.
- Methods: All functions in a class are usually called methods. However, all different from functions is that a class method must contain at least one self parameter (more on this later). For example, in the tortoise class, crawl(), eat(), sleep(), and protect() are all methods of this class. Class methods cannot be used alone, but can only be used with objects of the class.
1. The composition of the class
A class defined in Python is implemented using the class keyword, and its basic syntax format is as follows:
class Class name:
multiple (≥0) class attributes...
multiple (≥0) class methods...
Note that whether it is a class attribute or a class method, they are not necessary for the class, and they may or may not be present. In addition, the location of attributes and methods in a Python class is arbitrary, that is, there is no fixed order between them. After giving the class a good name, it should be followed by a colon (:), which means to tell the Python interpreter that the next step is to design the internal functions of the class, that is, to write class attributes and class methods. In fact, class attributes refer to the variables contained in the class; and class methods refer to the functions contained in the class. In other words, class attributes and class methods are actually nicknames for the variables and functions contained in the class. One thing to note is that all class attributes and class methods belonging to the same class must maintain a uniform indentation format, usually by 4 spaces. A Python class is composed of a class header (class name) and a class body (variables and functions that are uniformly indented). If a class does not have any class attributes and class methods, you can directly use the pass keyword as the class body. However, in practical applications, empty classes are rarely created, because empty classes have no practical meaning.
(1) Constructor
When creating a class, we can manually add an __init__() method, which is a special class instance method called a constructor (or constructor). The constructor is used when creating an object. Whenever an instance object of a class is created, the Python interpreter will automatically call it. In the Python class, the syntax format for manually adding a constructor is as follows:
def __init__(self,...):
code block
Note that in the method name of this method, there are 2 underscores at the beginning and at the end, and there can be no spaces in between. Many of these methods in Python that start with a double underscore and end with a double underscore have special meanings. In addition, the __init__() method can contain multiple parameters, but it must contain a parameter named self, which must be the first parameter. In other words, the class constructor must have at least one self parameter.
Note that even if you don't manually add any constructor to the class, Python will automatically add a constructor that only contains the self parameter to the class. The __init__() construction method that only contains the self parameter is also called the default construction method of the class. The self parameter is a special parameter, no need to manually pass the value, Python will automatically pass it the value. Python only stipulates that whether it is a construction method or an instance method, it must contain at least one parameter, and does not specify the specific name of the parameter. The reason for naming it self is just a custom among programmers. Following this convention can make the code we write more readable. The self parameter in the Python class method is equivalent to the this pointer in C++. self represents the caller of the method, that is, who calls the method, then self represents who.
(2) Properties and methods
The syntax format of using the created class object to access the instance variables in the class is as follows:
Class object name. Variable name
The grammatical format of using the class object to call methods in a class is as follows:
Object name. Method name (parameter)
Note that the dot "." is used to connect the object name, variable name, and method name.
Neither class attributes nor class methods can be used directly outside the class like ordinary variables or functions. We can regard the class as an independent space, the class attribute is actually the variable defined in the class body, and the class method is the function defined in the class body. Class variables refer to variables defined in the class but outside the methods of each class. The characteristic of the class variable is that all instantiated objects of the class share the class variable at the same time, that is to say, the class variable exists as a common resource in all the instantiated objects. There are two ways to call a class method, either directly using the class name, or using the instantiated object of the class. Instance variables refer to variables defined in the form of "self.variable name" within any class method, and are characterized by only acting on the object that calls the method. In addition, instance variables can only be accessed through object names, not through class names. In addition to instance variables, local variables can also be defined in class methods. Unlike the former, local variables are directly defined in the form of "variable name=value". Under normal circumstances, the definition of local variables is for the realization of the function of the class method. One thing to note is that local variables can only be used in the function they are in. After the function is executed, the local variables will also be destroyed.
Like class attributes, class methods can also be divided into class methods, instance methods, and static methods. Normally, the methods defined in the class are all instance methods by default. The biggest feature of an instance method is that it must contain at least one self parameter, which is used to bind the instance object that calls this method (Python will automatically complete the binding). Instance methods are usually called directly with class objects. The Python class method is similar to the instance method. It must contain at least one parameter, except that it is usually named cls in the class method, and Python will automatically bind the class itself to the cls parameter (note that the binding is not a class object). In other words, when we call the class method, we don't need to explicitly pass the cls parameter. Like self, the naming of the cls parameter is not prescribed (you can name it arbitrarily), it is just a convention used by Python programmers. The biggest difference with instance methods is that class methods need to @classmethod
be modified with modifiers. Static methods are actually the functions we have learned. The only difference from functions is that static methods are defined in the class space (class namespace), and Functions are defined in the space (global namespace) where the program is located. Static methods do not have special parameters like self and cls, so the Python interpreter will not bind any class or object to the parameters it contains. Because of this, no class attributes and class methods can be called in the static methods of the class. Static methods need to use @staticmethod
decorations.
2. Look at the concept through the code (the composition of the class)
Indeed, when I saw these for the first time, I had only one thought in my mind: What the hell are these things TMD... It doesn't feel very easy to understand. For this reason, Caiji wrote a piece of code for learning...
(1) Code demonstration
Next, use python to write a complex number class:
# coding=gbk
class complex:##定义一个复数类
imag = 0j
real = 0
def __init__(complex,imag,real):##构造函数,实例方法
complex.imag = imag
complex.real = real
@classmethod ##类方法
def Math1(complex):
complex.step = 1j##实例变量
sacle = 2##局部变量
return complex.imag+complex.step+complex.real*sacle
def Math2(complex):##实例方法
complex.step = 1j##实例变量
sacle = 2##局部变量
return complex.imag+complex.step+complex.real*sacle
@staticmethod
def Math3():
complex.step = 1j##实例变量
sacle = 2##局部变量
return complex.imag+complex.step+complex.real*sacle
@staticmethod
def Math4(complex):
complex.step = 1j##实例变量
sacle = 2##局部变量
return complex.imag+complex.step+complex.real*sacle
def Printf(self):
print("这是一个python自定义的复数类")
test = complex(3j,4)
test.Printf()
ans1 = test.Math1()
print(ans1)
ans2 = test.Math2()
print(ans2)
ans3 = test.Math3()
print(ans3)
ans4 = test.Math4(test)
print(ans4)
The output of the code is as follows:
(2) Code interpretation
First, a complex class called test is instantiated through the constructor, the real part is 4, the imaginary part is 3, and math1 is the class method. The imag and real called are class attributes, that is, 0+0j, so the return value is 1j; and math2 is an instance method, the imag and real that are called are the assignment of the constructor when instantiating, so the return value is 8+4j. In other words, math2 cannot take values for the class attributes imag and real.
and. Every time a class method is called, @classmethod needs to be added before the function, that is, the keyword is only the scope of the next function.
For static functions, the caller can be a class or an object, and there is no automatic parameter passing effect. When there are no internal parameters, the class attribute is called; when the function parameter is an instantiated custom class, the instantiated parameter is called. The method of binding to the class is specifically for the class, but in fact, the object can also be called, but the first parameter automatically passed in is still the class, which means that this kind of call is meaningless and easy to cause confusion.
(3) Additional expansion
Caiji's schoolboy had learned python before Caiji, so Caiji went to my schoolboy to discuss this issue. And my younger brother’s reply led me to a new concept "binding method" . For this reason, Caiji went to take a look at this thing, and the reference link for Caiji's reference is given below:
https://www.cnblogs.com/liunaixu/p/12879302.html (Do not spray me, spray him...)
In other words, static methods without binding methods in python3, that is, static methods are functions.
3.property() function
(1) Descriptor
In Python , through the use of descriptors, programmers can customize the work to be done when referencing an object attribute. Essentially, a descriptor is a class, but it defines how to access properties in another class. In other words, a class can delegate property management to the descriptor class. Descriptor is the basis of complex property access in Python. It is used internally to implement property, method, class method, static method and super type.
The descriptor class is based on the following 3 special methods, in other words, these 3 methods form the descriptor protocol:
- __set__(self, obj, type=None): This method will be called when setting attributes
- __get__(self, obj, value): This method will be called when the attribute is read
- __delete__(self, obj): This method will be called when del is called on the attribute.
Among them, the descriptor class that implements the set and get methods is called a data descriptor; conversely, if only the get method is implemented, it is called a non-data descriptor.
In fact, every time an attribute is searched, the method in the descriptor protocol is called by the special method __getattribute__() of the class object (be careful not to confuse it with __get__()). That is to say, every time the calling method of class object.attribute (or getattr(class object, attribute value)) is used, __getattribute__() will be called implicitly, and it will look for the attribute in the following order:
- Verify whether the attribute is the data descriptor of the class instance object;
- If not, check whether the attribute can be found in the __dict__ of the class instance object;
Finally, check whether the attribute is a non-data descriptor of the class instance object.
(2) property() function
We have been using the "class object. attribute" method to access the attributes defined in the class. In fact, this approach is improper, because it breaks the encapsulation principle of the class. Under normal circumstances, the attributes contained in a class should be hidden, and only indirect access and manipulation of class attributes are allowed through the methods provided by the class. Therefore, on the basis of not destroying the principle of class encapsulation, in order to be able to effectively manipulate the properties in the class, the class should contain multiple getter (or setter) methods for reading (or writing) the class properties, so that the "class object." Method (parameter)" to manipulate attributes. Fortunately, Python provides the property() function, which allows developers to still use the "class object. attribute" method to manipulate the properties in the class without breaking the principle of class encapsulation.
The basic usage format of the property() function is as follows:
属性名=property(fget=None, fset=None, fdel=None, doc=None)
Among them, the fget parameter is used to specify the class method to obtain the attribute value, the fset parameter is used to specify the method to set the attribute value, the fdel parameter is used to specify the method to delete the attribute value, and the last doc is a document string for Explain the role of this function.
PS: As a C++-based programmer, I am not used to this thing!
4. Encapsulation mechanism
Simple understanding of encapsulation (Encapsulation), that is, when designing a class, some properties and methods are deliberately hidden inside the class, so that when using this class, you cannot directly use "class object. property name" (or "class object These attributes (or methods) are called in the form of "method name (parameters)"), and these hidden attributes and methods can only be manipulated indirectly by unhidden class methods. First of all, the encapsulation mechanism ensures the integrity of the internal data structure of the class , because users who use the class cannot directly see the data structure in the class, and can only use the data that the class allows to expose, which avoids external influence on internal data. Improve the maintainability of the program. In addition, to achieve a good encapsulation of a class, users can only access data with the help of exposed class methods, we only need to add appropriate control logic to these exposed methods, and then users can easily realize the attributes in the class. Or the unreasonable operation of the method. Moreover, good encapsulation of classes can also improve code reusability.
Unlike other object-oriented programming languages (such as C++, Java), variables and functions in Python classes are either public (similar to public attributes) or private (similar to private). The difference between these two attributes is as follows:
- public: The class variables and class functions of public attributes can be accessed normally in the outside of the class, inside the class, and in the subclasses (the inheritance feature will be described in detail later);
- private: Class variables and class functions of private attributes can only be used inside the class, and cannot be used outside the class and subclasses.
However, Python does not provide public and private modifiers. In order to achieve class encapsulation, Python has adopted the following methods:
- By default, variables and methods in Python classes are all public (public), and there is no underscore (_) before their names;
- If the names of variables and functions in the class begin with a double underscore "__", the variable (function) is a private variable (private function), and its attributes are equivalent to private.
In addition, you can also define class attributes or class methods starting with a single underscore "_" (such as _name, _display(self)). Such class attributes and class methods are usually regarded as private attributes and private methods, although they It can also be accessed normally through the class object, but this is a common usage of conventions, and beginners must abide by it. Note that there are also class methods starting and ending with a double underscore in the Python class (such as the class constructor __init__(self)). These are defined internally by Python and used for internal calls in Python. When we define class attributes or class methods ourselves, do not use this format.