All of the following tutorials and code are based on python3.7

An overview of the

In Python, all methods wrapped in a double underscore of “__” are called Magic methods, such as the class initializer __init__. If your object implements (overloads) one of these methods, that method will be called by Python in special cases. This happens because all class objects in Python inherit from the Object class, which you can see in the buildins.py file along with the defined Magic Method

List of magic methods

Magic methods meaning
Basic magic methods
__new__ (CLS [,…]. ) 1. __new__ is the first method called when an object is instantiated. 2. __new__ determines whether to use the __init__ method, because ___new__ can call the constructor of another class or directly return another instance object as an instance of this class. If __new__ does not return an instance object, __init__ is not called. __new__ is mainly used to inherit an immutable type such as a tuple or string
__init__ (self [,…]. ) Constructor, the initialization method that is called when an instance is created
__del__(self) Destructor, a method called when an instance is destroyed
__call__ (self, args […]. ) Allows an instance of a class to be called like a function: x(a, b) calls x.__call__(a, b).
__len__(self) Defines the behavior when len() is called
__repr__(self) Defines the behavior when called by repr()
__str__(self) Defines the behavior when called by STR ()
__bytes__(self) Defines the behavior when called by bytes()
__hash__(self) Defines the behavior when called with hash()
__bool__(self) Defines the behavior when called by bool(), which should return True or False
__format__(self, format_spec) Defines the behavior when called by format()
The attributes
__getattr__(self, name) Defines the behavior when a user tries to obtain a property that does not exist
__getattribute__(self, name) Defines the behavior when properties of the class are accessed
__setattr__(self, name, value) Defines the behavior when a property is set
__delattr__(self, name) Defines the behavior when an attribute is deleted
__dir__(self) Defines the behavior when dir() is called
__get__(self, instance, owner) Defines the behavior of a descriptor when its value is fetched
__set__(self, instance, value) Defines the behavior of a descriptor when its value is changed
__delete__(self, instance) Defines the behavior of a descriptor when its value is deleted
Comparison operator
__lt__(self, other) Define the less-than sign behavior: x < y calls x.__lt__(y)
__le__(self, other) Defining the behavior of a less than or equal sign: x <= y calls x.__le__(y)
__eq__(self, other) Define the behavior of equals: x == y calls x.__eq__(y)
__ne__(self, other) The act of defining inequality: x! = y calls x.__ne__(y)
__gt__(self, other) Defining greater than sign behavior: x > y calls x.__gt__(y)
__ge__(self, other) Defining greater than or equal behavior: x >= y calls x.__ge__(y)
Arithmetic operator
__add__(self, other) Define the behavior of addition: +
__sub__(self, other) Defines the behavior of subtraction: –
__mul__(self, other) Define the behavior of multiplication: *
__truediv__(self, other) Defines the behavior of true division: /
__floordiv__(self, other) Defines the behavior of integer division: //
__mod__(self, other) Defines the behavior of the modulus algorithm: %
__divmod__(self, other) Defines the behavior when called by divmod()
__pow__(self, other[, modulo]) Defines the behavior when called by power() or when operated on by **
__lshift__(self, other) Define the behavior of bitwise left-shift: <<
__rshift__(self, other) Define bitwise right shift behavior: >>
__and__(self, other) Defines the behavior of bitwise and operations: &
__xor__(self, other) Defines the behavior of bitwise xor operations: ^
__or__(self, other) Define the behavior of bitwise or operations:
The operation
__radd__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rsub__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rmul__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rtruediv__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rfloordiv__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rmod__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rdivmod__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rpow__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rlshift__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rrshift__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__rxor__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
__ror__(self, other) (As above, called when the left-hand operand does not support the corresponding operation)
Incremental assignment
__iadd__(self, other) Defines the behavior of assignment addition: +=
__isub__(self, other) Defines the behavior of assignment subtraction: -=
__imul__(self, other) Defines the behavior of assignment multiplication: *=
__itruediv__(self, other) Defines the behavior of assigning true division: /=
__ifloordiv__(self, other) Defines the behavior of assigning integer division: //=
__imod__(self, other) Defines the behavior of the assignment modulus algorithm: %=
__ipow__(self, other[, modulo]) Defines the behavior of an assignment power operation: **=
__ilshift__(self, other) Defines the bitwise left shift behavior of assignment: <<=
__irshift__(self, other) Defines the bitwise right shift behavior of assignment: >>=
__iand__(self, other) Defines the behavior of assignment bitwise and operations: &=
__ixor__(self, other) Defines the behavior of the bitwise xor operation of assignment: ^=
__ior__(self, other) Defines the behavior of assigning bitwise or operations:
Unary operator
__neg__(self) Define the behavior of a plus sign: +x
__pos__(self) Define the behavior of the minus sign: -x
__abs__(self) Defines the behavior when called by abs()
__invert__(self) Define the bitwise inverse behavior: ~x
Type conversion
__complex__(self) Define what to do when called by complex() (need to return the appropriate value)
__int__(self) Defines the behavior when called by int() (needs to return the appropriate value)
__float__(self) Define the behavior when called by float() (need to return the appropriate value)
__round__(self[, n]) Defines the behavior when called round() (needs to return the appropriate value)
__index__(self) 1. Implement an integer cast when the object is applied to a slice expression. If you define a custom numeric type that might be used in slicing, you should define __index__ 3. If __index__ is defined, __int__ needs to be defined as well and returns the same value
Context Management (with statement)
__enter__(self) Define the initialization behavior when using the with statement. 2. The return value of __enter__ is bound to the target of the with statement or the name after as
__exit__(self, exc_type, exc_value, traceback) 1. Define what the context manager should do after a code block is executed or terminated. It is usually used to handle exceptions, clean up work, or do routine work after a block of code has been executed
Container type
__len__(self) Defines the behavior when len() is called (returns the number of elements in the container)
__getitem__(self, key) Defines the behavior of getting a specified element in a container, equivalent to self[key]
__setitem__(self, key, value) Defines the behavior of a specified element in a container, equivalent to self[key] = value
__delitem__(self, key) Defines the action of deleting specified elements from a container, equivalent to del self[key]
__iter__(self) Defines the behavior of elements in a container when iterating over them
__reversed__(self) Defines the behavior when called with reversed()
__contains__(self, item) Defines the behavior when the member test operator (in or not in) is used

The magic of the method

__eq__

== Compares whether the contents of two objects are equal. That is, the memory address can be different, but the contents are the same.

By default, the object’s __eq__() method is called. The __eq__ method, inherited from object, compares the ids of two objects. The following verifies that the two instance attributes are equal by implementing __eq__.

class Person(object): def __init__(self, name, age): self.name = name self.age = age def __eq__(self, other): A = Person('x', 12) b = Person('x', 12) print(a == b) print(a is b) #### LST = [] lst.append(a) if b not in LST: lst.append(b) print(LST) LST = [] lst.append(b) print(LST) lst.append(b) print(LST)Copy the code

__new__

The __new__ method is called before __init__ and is used to generate instance objects. Most commonly used for singleton patterns in design patterns. Singleton pattern: A singleton class can have only one instance.

class Singleton(object):
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance

s = Singleton()
print('Object created', s)
s1 = Singleton()
print('Object created', s1)

Copy the code

__getattr__

__getattr__ is called when the accessed attribute does not exist, which can be used to encapsulate access to other class attributes, or when the current class attribute does not exist. Therefore, it can be used to facilitate the implementation of proxy mode. Proxy mode: Provides a proxy for other objects to control access to that object. In some cases, an object is inappropriate or cannot directly reference another object, and a proxy object can act as an intermediary between the client and the target object.

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


class PersonProxy(object):
    def __init__(self, name, sex, age):
        self.__obj = Person(name, sex, age)

    @property
    def proxy_type(self):
        return self.__obj.__class__.__name__

    def __getattr__(self, item):
        if getattr(self.__obj, 'sex') == 'female' and item == 'age':
            return "access denied"
        else:
            return getattr(self.__obj, item)


if __name__ == '__main__':
    a = PersonProxy('a','male','12')
    b = PersonProxy('b','female', '15')
    print(b.proxy_type)
    print(a.name)
    print(b.name)
    print(a.age)
    print(b.age)

Copy the code

__enter__ and __exit__

The two are often used in combination to achieve the effect of a context manager. Context managers are often used for resource operations that require operations related to resource acquisition and release. A typical example is database connection, query, and close processing.

current_conn = "A"


class switch_db(object):
    def __init__(self, db_alias):
        self.conn = db_alias

    def __enter__(self):
        global current_conn
        self.org_conn = current_conn
        current_conn = self.conn
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        global current_conn
        current_conn = self.org_conn

    def query(self):
        return "current connection: " + current_conn


if __name__ == '__main__':
    with switch_db('B') as db:
        print(db.query())
    print(db.query())

Copy the code

This article uses the article synchronization assistant to synchronize