Python full stack development 9, object-oriented, meta-class and Singleton, python meta-class
The previous series of blog posts are all about process-oriented programming. Now it's time for a wave of object-oriented explanations.
I. Introduction
Object-Oriented Programming is implemented using classes and objects. Therefore, object-oriented programming is actually the use of classes and objects. A class is a template. A template can contain multiple methods (functions) and implement various functions in the method. The object is an instance created based on the template, objects can execute methods in the class. Each object has the same method, but their data may be different.
Ii. Classes, objects, and methods
In Python, the class is defined throughclass
Keyword,class
The class name is followed by the class name. The class name is usually a word starting with uppercase, followed('Name of the class to be inherited ')
Indicates the class from which the class is inherited. Normally, if there is no suitable inheritance classobject
Class. This is the class that all classes will ultimately inherit.
Class MyClass (): # create a class def func (self): # define the method passobj1 = MyClass () # create an object based on MyClass
When defining a method in a class, like previously defining a function, it is used to implement a certain function. However, when defining a method, at least one parameter (self) must be passed to represent the created object, the function is not required. Let's take a look at what self actually refers.
Class MyClass (): def func (self, str): print (self, str) def func1 (self, str): passobj1 = MyClass () # Which object is called by self, self is the object obi <===> selfprint (obj1) # <__ main __. myClass object at 0x000002C2119AD4A8> obj1.func ('jason ') # <__ main __. myClass object at 0x000002C2119AD4A8>
From the data printed above, we can see that the address value of the created obj1 object is the same as the address value of self in the func method. The two are the same, indicating that self refers to the created object, here, you must understand what self refers.
3. Three major object-oriented features: encapsulation, inheritance, and polymorphism. 1. Encapsulation
Object-oriented has three major features. First, we should consider the first feature: encapsulation. encapsulation is generally achieved by encapsulating data in the class and obtaining data through the object or self. Similar to other object-oriented languages, constructor is also used to encapsulate data. Let's take a look at the code below.
Class A: def _ init _ (self, name): # constructor, initialization data, self. name = name # encapsulate data def f1 (self): print (self. name) # obtain the encapsulated data through self a = A ('jason '). f1 () # obtain encapsulated data through an object
Another encapsulation method is to use private attributes to encapsulate data. Let's take a look at the specific usage,
Class A: name = 'jason '_ age = 18 # Private Static Field, def _ init _ (self): self. _ like = 'soccer' # private common field self. holobby = 'kkkk 'def f1 (self): print (self. _ age) # private static field. A private common field can only be called by the method in the class. print (self. _ like) #. _ age # private static fields cannot be obtained externally, and data is encapsulated as a = A () # soccera. f1 () #18 print (. holobby)
2. Inheritance
The Inheritance in Python can be inherited. through inheritance, you can obtain the features of the parent class. When inheriting, if there are repeated methods in the parent class, you should first find yourself. If there is a relationship below, D inherits B, E inherits C, F inherits D, E, then search for the order, D-> B-> E-> C. If there is A following relationship, B inherits, C inherits A, D inherits B, E inherits C, F inherits D, E, then find the order, D-> B-> E-> C-A, Next let's look at the usage
Class A: def f (self): print ('A') class B: def f (self): print ('B') def f1 (self ): print ('bbbbb') class C (A, B): def f1 (self): print ('C') cc = c () cc. f () # acc. f1 () # c # The following are difficult points: class A: def bar (self): print ('bar') self. f1 () class B (A): def f1 (self): print ('B') class C (): def f1 (self): print ('C ') class D (B): def f1 (self): print ('D') class E (C, d): passd = D () D. bar () # d. bar (). where can I find f1?
In addition to the Inheritance Method, you can also inherit the constructor of the parent class.
# Inheritance constructor class A: def _ init _ (self): self. name = 'jason 'class B (A): def _ init _ (self): self. age = '16' super (B, self ). _ init _ () #. _ init _ (self) # Another method that inherits constructor d = B ()
3. Polymorphism
Python itself supports polymorphism, so it doesn't make sense to discuss polymorphism in Python object-oriented, so I will not talk about it here
Iv. Class Members
The class members can be divided into three categories: fields, methods, and attributes. The following code shows the usage
Class A: country = 'China' # static field, saved in the class to save the memory def _ init _ (self, name): self. name = name # common field, saved in object def show (self): # common method, saved in class, the object uses print ('common method') Through Class Object Pointer ') return self. name @ staticmethod # static method, saved in the class def f1 (): # No self parameter print ('static method ') @ classmethod # The class method is equivalent to a static method with a class name parameter def f2 (cls): # pass the current class name as a parameter to print ('class method ') @ property # A property or a feature that disguise a common method as a field, but cannot pass in the second parameter def f3 (self): print ('properties') return self. name @ f3.setter # Set the attribute def f3 (self, value): print (value) self. name = valuea = A ('jason ') print (hasattr (A, 'name') # Falseprint (hasattr (a, 'name') # Trueprint (hasattr (, 'show') # Trueprint (hasattr (A, 'country') # Trueprint (hasattr (a, 'country') # True # priority, access your own members first in addition to the methods in the class # use the following method to operate # access through the class: static fields, static methods, class Method (adding A class name parameter to the static method) # common fields and common methods are accessed through objects # self, object call # No self, class call. f1 () # static method. show () # normal method. f2 () # class method. f3 # Attribute. Do not add parentheses when obtaining the attribute values. It is similar to. f3 = 'kobe' # Set the attribute value, print (. country) print (. name) # private class A can only be called in the class. class A cannot be called externally: name = 'jason '_ age = 18 # Private Static Field def _ init _ (self): self. _ like = 'soccer' # private common field self. holobby = 'kkkk 'def f1 (self): print (self. _ age) # private static field. A private common field can only be called by the method in the class. print (self. _ like) #. _ age # Private Static Field a = A () # soccera. f1 ()
Special members, not much to mention, directly go to the code
Class A: def _ init _ (self): print ('init ') self. name = 'jason 'def _ str _ (self): return '........ 'def _ call _ (self, * args, ** kwargs): print ('call') return 1 def _ getitem _ (self, item ): print (item, type (item) def _ setitem _ (self, key, value): print (key, value) def _ delitem _ (self, key): print (key) def _ iter _ (self): yield 1 yield 2a = A () # execute _ init _ a () in parentheses after the init class () # execute _ call _ print (a) # execute _ str _ Method k = ()() # init call k = 1a ['ddddd'] # Run _ getitem _ <class 'str'> a ['name'] = 'jason '# Run _ setitem _ _ del a ['name'] # Run _ delitem _ a [] # py2 _ getslice __, py3 execution _ getitem _ <class 'slice '> a [] = [1, 2] # py2 _ setslice __, py3 execute _ setitem _ del a [] # py2 _ detslice __, py3 execute _ delitem _ print (. _ dict _) # {'name': 'jason '} field print (. _ dict _) # for I in a: # execute _ iter _ print (I)
V. Metadata
In Python, everything is an object and a class is also an object. The question is, how to create a class, the class definition is dynamically created at runtime, and the method to create a class is to usetype()
Function, throughtype()
The class created by the function is exactly the same as writing the class directly, because when the Python interpreter encounters the class definition, it only scans the class definition syntax and then callstype()
Function to create a class. Type can take the description of a class as a parameter, and then return a class that can be used like this: type (Class Name, parent class tuples (for inheritance, it can be blank ), dictionary containing attributes (name and value ))
# Def f1 (self): print (self. name) MyClass = type ('myclass', (), {'name': 'jason ', 'f1': f1}) print (MyClass, type (MyClass )) # <class '_ main __. myclass'>, <class 'type'> print (MyClass. name) # jasonmy = MyClass () print (my. _ class _) # <class '_ main __. myclass'> print (my) # <__ main __. myClass object at 0x000001F3013751D0> my. f1 () # jason
After the type is finished, what is the relationship between the type and the meta-class? The type is actually a meta-class. Type is the metadata used by Python to create all classes.type()
In addition to the dynamic creation class, metaclass (metaclass) is used to control the creation behavior of the class. To create a class, create a Class Based on metaclass. Therefore, define metaclass first, then create a class. To connect, You can first define metaclass to create a class and then create an instance. The role of a metadatabase is to intercept the creation of a class, modify the class, and return the modified class. The following describes how to use the code.
# Using functions # def upper_attr (future_class_name, future_class_parents, future_class_attrs): # attrs = (name, value) for name, value in future_class_attrs.items () if not name. startswith ('_') # uppercase_attr = dict (name. upper (), value) for name, value in attrs) # return type (future_class_name, future_class_parents, uppercase_attr () # class (): # _ metaclass _ = upper_attr # country = "China" # def _ init _ (self ): # Self. name = 'jason '# print (hasattr (A, 'country') # print (hasattr (A, 'country') ''' _ new __() the parameters received by the method are: the object of the class to be created; the name of the class; the parent class set inherited by the class; and the method set of the class. _ New _ is the special method called before _ init _ is used to create an object and return the method. _ init _ is only used you seldom use _ new __, unless you want to control the creation of the object here, the created object is a class, and we want to customize it, so here we rewrite _ new _ if you want, you can also do some things in _ init _. Some advanced usage involves the special _ call _ method, but we do not need '''class UppMetaclass (type) here): def _ new _ (cls, name, base, attrs): uppattrs = dict (k. upper (), v) for k, v in attrs. items () if not k. startswith ('_') # return type. _ new _ (cls, name, base, uppattrs) return super (UppMetaclass, cls ). _ new _ (cls, name, base, uppattrs) class A (metaclass = UppMetaclass ): # _ metaclass _ = UppMetaclass country = "China" def _ init _ (self): self. name = 'jason 'print (hasattr (A, 'country') print (hasattr (A, 'country') print (. COUNTRY)
Vi. Singleton Mode
Singleton, as the name implies, is a single instance. The purpose of the singleton mode is to ensure that only one instance exists in the current memory to avoid Memory waste. The following describes how to implement Singleton.
Class Instance: # method 1 _ instance = None # Private Static Field def _ init _ (self): self. name = 'jason 'self. passwd = 'kkkkk '@ staticmethod def get_instance (): if not Instance. _ instance: # If the private static field is empty, create an Instance instance. _ instance = Instance () return Instance. _ instance # if it is not null, an Instance obj1 = instance is directly returned. get_instance () # execute the static method. Create an Instance and assign the value to obj1obj2 = Instance. get_instance () # execute the static method and assign the object stored in the Private Static Field to obj2print (obj1) # <__ main __. instance object at 0x0000021AEDF56048> print (obj2) # <__ main __. instance object at 0x0000021AEDF56048> class Singleton (): # method 2 def _ new _ (cls, * args, ** kwargs): if not hasattr (cls, '_ instance'): cls. _ instance = super (Singleton, cls ). _ new _ (cls, * args, ** kwargs) return cls. _ instanceclass A (Singleton): passa = A () B = A () print (a is B) class Singleton (type ): # method 3 def _ call _ (cls, * args, ** kwargs): if not hasattr (cls, '_ instance'): cls. _ instance = super (Singleton, cls ). _ call _ (* args, ** kwargs) return cls. _ instanceclass A (metaclass = Singleton): # _ metaclass _ = Singleton passa = A () B = A () print (a is B)
VII. Supplement
Another way of expressing attributes:
class A: def __init__(self): self.mylist = [1, 2, 3, 4] def getmylist(self): print(self.mylist) def setmylist(self, value): self.mylist.append(value) print(self.mylist) def delmylist(self): if len(self.mylist) > 0: self.mylist.pop() print(self.mylist) my_pro_list = property(getmylist, setmylist, delmylist, 'Property')a = A()a.my_pro_lista.my_pro_list = 7del a.my_pro_list''' [1, 2, 3, 4] [1, 2, 3, 4, 7] [1, 2, 3, 4]'''
Dan Li added:
Class SingMetaclass (type): def _ call _ (self, * args, ** kwargs): if not hasattr (self, 'instance'): # self. instance = super (SingMetaclass, cls ). _ new _ (cls, name, base, attrs) # self. instance = self. _ new _ (self, * args, ** kwargs) # This method can also be used below, but it is easy to understand self without comments. instance = super (). _ call _ (* args, ** kwargs) return self. instanceclass A (metaclass = SingMetaclass): pass
The inheritance sequence of py27 is different from that of py3. For example, bar does not inherit object (Classic class) and depth first. In other cases, bar prevails in width first.
# py27class bar(): def f1(self): print('bar')class A(bar): def f(self): print('a')class C(A): def f(self): print('c')class B(bar): def f1(self): print('b')class D(B): def f1(self): print('d')class E(C,D): def f(self): print('e')e = E()e.f1()
Abstract classes and abstract methods:
From abc import ABCMetafrom abc import abstractclassmethodclass Absclass (metaclass = ABCMeta): # Abstract class + abstract method, similar to interface, constraint class @ abstractclassmethod def f1 (self ): pass @ abstractclassmethod def f2 (self): passclass B (Absclass): # B needs to fully implement the abstract method def f1 (self) in the abstract class: pass def f2 (self ): pass # If Class B does not fully implement the methods in the Absclass class, you can compile the statements. However, if executed, the following error occurs: def f3 (self): passc = B ()