Python self study notes - Chapter 6 object oriented programming

Keywords: Programming Python MySQL Database Attribute

3. Magic method

Python's objects naturally have some magical methods. They are always surrounded by double underscores. They are everything of object-oriented python. They are special methods that can add magic to your class. If your object implements (overloads) one of these methods, then this method will be called by Python in a special case. You can define your desired behavior, and all this happens automatically.

All in all, Python's magic method is very powerful.

The following will list these magic methods, and focus on some of the methods.

3.1. Basic magic methods

3.1.1. New and init__

  • __The new uuuu method is a real class constructor used to generate instantiated objects (empty properties). Overriding the new method controls the generation of objects.
  • __Init method is the initialization method, which is responsible for initializing the property value of the instantiated object. This method must return None, and the new method must return an object. Overriding the init method controls the initialization of the object.

Use new to create a singleton pattern

class Person(object):
    __instance = None
    __init_flag = False

    def __new__(cls, name):
        if cls.__instance == None:
            cls.__instance = object.__new__(cls)
            return cls.__instance
        else:
            # Returns a reference to the last created object
            return cls.__instance
    
    def __init__(self,name):
        if Person.__init_flag == False:
            self.name = name
            Person.__init_flag = True
aP = Person('Xiao Ming')
print(id(aP))
print(aP.name)
Operation result:
140005334645616
 Xiao Ming
bP = Person('Xiao Wang')
print(id(bP))
print(bP.name)
Operation result:
140005334645616
 Xiao Ming

3.1.2. STR and repr__

The purpose of both is to display some necessary information of the object explicitly, and to facilitate viewing and debugging. __str is called by print by default, and repr is called by console by default. That is, use str to control the user presentation and repr to control the debugging presentation.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person('Xiao Ming', 26)
print(p)
Operation result:
<__main__.Person object at 0x7f55883cfd30>
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __str__(self):
        return f'{self.__class__}, {self.name}, {self.age}'

p = Person('Xiao Ming', 26)
print(p)
Operation result:
< class'. Person '> Xiaoming, 26

3.1.3.__call__

__The call method provides the ability for an object to be executed, just like a function. In essence, a function is an object, and a function is an object with a call method. For an object with a call method, you can use the call function to get the result of True. You can use () to execute. When executing, you can pass in parameters or return values. So we can use the call method to implement the instantiated object as a decorator:

Object becomes callable

class Person(object):
    def __init__(self, name):
        self.name = name

    def __call__(self, friend):
        print('My name is %s...' % self.name)
        print('My friend is %s...' % friend)
        
p = Person('Xiao Ming')
p('Xiao Wang')
Operation result:
My name is Xiaoming
 My friend is Xiao Wang

Instance object version decorator

class Checker:
    def __init__(self, require_num):
        self.require_num = require_num

    def __call__(self, func):
        self.func = func

        def inner(*args, **kw):
            if len(args) != self.require_num:
                print('The number of function parameters does not meet the predefined requirements, unable to execute the function')
                return None

            return self.func(*args, **kw)
        return inner

@Checker(2)
def show(*args):
    print('show Function executed successfully!')
    
show(1)
Operation result:
The number of function parameters does not meet the predefined requirements, unable to execute the function

3.1.4.__del__

  • __del UU is used to call automatically when the reference count of an object is 0.
  • __Del_uuuugenerally appears in two places: 1. Manually use del to reduce the object reference count to 0, which is called when it is garbage collected. 2. Called at the end of the program.
  • __del? Is generally used to declare resource recovery operations that need to be processed before an object is deleted

Calling del manually can reduce the object reference count by one. If it is reduced to 0, garbage collection will be triggered

class Person:

    def __del__(self):
        print('Calling object's del Method, which reclaims the memory address of this object')

p = Person()  # Call the object's del method to reclaim the object's memory address

del p

print('There are other codes in the program')
Operation result:
Call the del method of the object, which will reclaim the memory address of the object
 There are other codes in the program

When the program ends directly, it also calls the object's del method to reclaim the address

3.2. Attribute related

The relevant instructions have been described in the descriptor section

  • The setattr method of the object is triggered when obj.x = y is used, and the delattr method of the object is triggered when del obj.x is used.
  • When an attempt is made to access a nonexistent property of an object, the getattr method is triggered, which has the lowest priority in property lookup.
  • If \
  • __getatrribute is a property access interceptor, that is, when you access a property, this method will truncate your access behavior and give priority to the code in this method, which should be the highest priority in the property search order.
  • Attribute search order: getattribute -- > instance object dictionary of the instance -- > class Dictionary of the instance -- > parent class (MRO order) dictionary of the instance -- > getattr -- > error of the class of the instance

3.3. Comparison operator

class Car():
    def __init__(self,carname,oilcp100km, price):
        self.carname,self.oilcp100km,self.price = carname,oilcp100km, price
   
    def __lt__(self,other):
        print("execute __lt__")
        return self.price<other.price

car1,car2 = Car('Elysee',8,10),Car('Camry',7,27)
car1>car2
Operation result:
execute __lt__
False

3.4. Arithmetic operator

3.5. Inverse operation

3.6. Incremental assignment

3.7. Unary operator

3.8. Type conversion

3.9. Context management (with statement)

The rewriting of these two methods allows us to use the with method on an object to deal with the preparation before work and the cleaning behavior after work.

class MySQL:
    def connect(self):
        print('Start database connection and apply for system resources')

    def execute(self):
        print('implement sql Command, operating data')

    def finish(self):
        print('Database connection is closed and system resources are cleaned up')

    def __enter__(self):  # Triggered when with and assigned to as variable
        self.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):  # Triggered when leaving the with statement block
        self.finish()

with MySQL() as mysql:
    mysql.execute()
Operation result:
Start database connection and apply for system resources
 Execute sql command, operate data
 Database connection is closed and system resources are cleaned up

3.10. Type of container

3.10.1. ITER and next__

These two methods are used to simulate an object into a sequence. Built in types such as lists and tuples can be iterated, and file objects can also be iterated to get each line of content. By overriding these two methods, you can implement a custom iterative object.

Defines a natural number class with a specified range and can provide iteration. Using for loop does not prompt stopinteraction error

class Num:
    def __init__(self, max_num):
        self.max_num = max_num
        self.count = 0
        
    def __iter__(self):
        return self

    def __next__(self):
        if self.count < self.max_num:
            self.count += 1
            return self.count
        else:
            raise StopIteration('Has reached the threshold')
        
num = Num(10)
for i in num:
    print(i)  # Cycle printing 1-10
Operation result:
1
2
3
4
5
6
7
8
9
10

Use the next() method to iterate one by one, and finally prompt for stopinteraction error

num = Num(2)
print(next(num))
print(next(num))
print(next(num))
Operation result:
1
2
---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-18-e4a5cb14ad24> in <module>
      2 print(next(num))
      3 print(next(num))
----> 4 print(next(num))
<ipython-input-15-ac9e7199252c> in __next__(self)
     13             return self.count
     14         else:
---> 15             raise StopIteration('Has reached the threshold')
     16 
     17 num = Num(10)


StopIteration: Has reached the threshold

3.10.2. Getitem, setitem and delete__

Overriding this series of methods can simulate objects into lists or dictionaries, that is, the key value type can be used.

class PersonManager:

    def __init__(self):
        self.li = []
        self.dic = {}

    def __getitem__(self, item):
        if isinstance(item, int):
            # Get object by subscript
            return self.dic[self.li[item]]
        elif isinstance(item, slice):
            # Slice to get a list of objects
            start = item.start
            stop = item.stop
            return [ self.dic[p] for p in self.li[start:stop]]
        else:
            # The given key type is wrong
            raise TypeError('What you entered key error in type!')
            
    def __setitem__(self,key,value):
        self.li.append(key)
        self.dic[key]=value
        

class Person:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f'personnel: {self.name}'

    __repr__ = __str__
    
pm = PersonManager()
pm[0]= Person('Xiao Ming')
pm[1]= Person('Great white')
pm[2]= Person('Xiaohong')
pm[3]= Person('Fat tiger')

print(pm[0])
print(pm[0:3])
Operation result:
Personnel: Xiao Ming
 [personnel: Xiaoming, personnel: Dabai, personnel: Xiaohong]

For more articles, please pay attention to:

Posted by suspect on Fri, 13 Mar 2020 03:08:30 -0700