Magic properties

In Python, all methods wrapped in __ double underscores are called Magic methods, such as class initializer __init__() and instance object creator __new__().

Magic properties and methods are properties and methods built into Python that have special meanings. The name is preceded by two underscores, which are automatically called when system-specific operations are performed.


Common magic properties

__doc__

Represents the description of the class


# __doc__
class Foo:
    """ Describes the class information. This is the class used for testing. ""
    
    def func(self) :
        pass

    
# ipython test
In [2]: Foo.__doc__
Out[2] :'Describe the class information, this is the class for testing.'
    
Copy the code


__module__ and magic __class__

  • __module__Indicates the module in which the object of the current operation resides
  • __class__What is the class of the object that represents the current operation

# __module__, magic __class__
# oop.py
class Student(object) :
    
    def __init__(self, name) :
        self.name = name
        
        
# main.py
from oop import Student

s = Student()
print(s.__module__)  Output OOP is: output module
print(s.__class__)   # output 
      
        i.e. : output class
      
Copy the code


__init__ 、__new__

The __init__() initializer method and __new__(), which are automatically triggered when objects are created from the class. __new__ is used to create a class and return an instance of the class, while __init__ simply initializes the instance with the parameters passed in.

  • Called when an object is created, __new__() returns an instance of the current object

  • __init__() is called after an object has been created. It initializes some instances of the current object and returns no value


# __init__, __new__
class Student(object) :

    def __init__(self, name, age) :
        print('__init__() called')
        self.name = name
        self.age = age

    def __new__(cls, *args, **kwargs) :
        print('__new__() called')
        print(cls, args, kwargs)
        return super().__new__(cls)
  

# ipython test
In [26]: s1 = Student('hui', age=21)
__new__() called
<class '__main__.Student'> ('hui'.) {'age': 21}
__init__() called

In [27]: s2 = Student('jack', age=20)
__new__() called
<class '__main__.Student'> ('jack'.) {'age': 20}
__init__() called

Copy the code


__del__

Execution is triggered automatically when an object is freed in memory.

Note: this method is generally do not need to define, because Python is a high-level language, memory management and garbage collection mechanism, programmers when use don’t need to care about memory allocation and release, is because the work is carried out to the Python interpreter, so __del__ call is triggered by the interpreter in garbage collected automatically.

# __del__
class Foo:
    def __del__(self) :
        print('__del__() called')

        
# ipython test
In [29]: f = Foo()

In [30] :del f
__del__() called
Copy the code


__call__

Make instances of classes behave like functions, you can call them, pass one function as an argument to another, and so on. This is a very powerful feature that makes Python programming a lot sweeter. Object is parenthesized to trigger execution.

Note: Execution of the __init__ method is triggered by the creation of an object, that is: object = class name (); Execution of the __call__ method is triggered by parentheses after the object: object () or class ()().

__call__ is useful when instances of those classes frequently change state. Calling this instance is a straightforward and elegant way to change the state of the object. This is best expressed as an example:

# __call__
class Rect(objectCall the instance object to change the position of the rectangle.def __init__(self, x, y) :
        # x, y for rectangular coordinates
        self.x, self.y = x, y

    def __call__(self, x, y) :        
        # Change the location of the entity
        self.x, self.y = x, y


# ipython test
In [33]: r = Rect(10.10)

In [34]: r.x, r.y
Out[34] : (10.10)

In [35]: r(0.0)

In [36]: r.x, r.y
Out[36] : (0.0)

In [37]: r(100.100)

In [38]: r.x, r.y
Out[38] : (100.100)
Copy the code


__dict__

All properties in a class or object

Instance attributes of a class belong to objects; Class attributes and methods in a class belong to a class, that is:

# __dict__
class Student(object) :

    def __init__(self, name, age) :
        self.name = name
        self._age = age

    @property
    def age(self) :
        return self._age

    
# ipython test
In [47] :Get class attributes

In [48]: Student.__dict__
Out[48]:
mappingproxy({'__module__': '__main__'.'__init__': <function __main__.Student.__init__(self, name, age)>,
              'age': <property at 0x210e2a005e8>,
              '__dict__': <attribute '__dict__' of 'Student' objects>,
              '__weakref__': <attribute '__weakref__' of 'Student' objects>,
              '__doc__': None})

In [49] :Get the properties of the instance object

In [50]: s = Student('hui'.21)

In [51]: s.__dict__
Out[51] : {'name': 'hui'.'_age': 21}

In [52]: s2 = Student('jack'.20)

In [53]: s2.__dict__
Out[53] : {'name': 'jack'.'_age': 20}
Copy the code


__str__

If a class defines a __str__ method, the return value of that method is printed by default when the object is printed.

In [65] :# __str__. :class Foo(object) :. :pass. : In [66]: f = Foo()

In [67] :print(f)
<__main__.Foo object at 0x00000210E2715608>

In [68] :class Foo(object) :. :... :def __str__(self) :. :return '< Custom Foo object str >'. : In [69]: f = Foo()

In [70] :print(f)
< Custom Foo object str >

Copy the code


__getitem__, __setitem__, __delitem__

Used for indexing operations, such as dictionaries. Get, set, and delete data respectively.

Used for slicing operations, such as lists.


The dictionary sample

# __getitem__, __setitem__, __delitem__
class MyDict(object) :

    def __init__(self) :
        self.my_dict = dict(a)def __getitem__(self, key) :
        print('__getitem__() ', key)
        return self.my_dict.get(key, None)

    def __setitem__(self, key, value) :
        print('__setitem__() ', key, value)
        self.my_dict.update(key=value)

    def __delitem__(self, key) :
        print('__delitem__() ', key)
        del self.my_dict[key]


# ipython test
In [33]: mdict = MyDict()

In [34] :print(mdict['name'])
__getitem__()  name
None

In [35] :# new

In [36]: mdict['name'] = 'hui'
__setitem__()  name hui

In [37]: mdict['age'] = 21
__setitem__()  age 21

In [38]: mdict['name']
__getitem__()  name
Out[38] :'hui'

In [39]: mdict['age']
__getitem__()  age
Out[39] :21

In [40] :# update

In [41]: mdict['name'] = 'jack'
__setitem__()  name jack

In [42]: mdict['name']
__getitem__()  name
Out[42] :'jack'

In [43] :# remove

In [44] :del mdict['age']
__delitem__()  age

In [45] :print(mdict['age'])
__getitem__()  age
None

Copy the code


The list of the sample

# Slice operation
class MyList(object) :

    def __init__(self) :
        self.mlist = list(a)def __getitem__(self, index) :
        print('__getitem__() called')
        print(index)
        if isinstance(index, slice) :return self.mlist[index]

    def __setitem__(self, index, value) :
        print('__getitem__() called')
        print(index, value)
        if isinstance(index, slice):
            self.mlist[index] = value

    def __delitem__(self, index) :
        print('__delitem__() called')
        if isinstance(index, slice) :del self.mlist[index]
     
    
# ipython test
In [70]: mlist = MyList()

In [71]: mlist[0]
__getitem__() called
0

In [72]: mlist[0: -1]
__getitem__() called
slice(0, -1.None)
Out[72]: []

In [73]: mlist[:] = [1.2.3]
__getitem__() called
slice(None.None.None) [1.2.3]

In [74]: mlist[:]
__getitem__() called
slice(None.None.None)
Out[74] : [1.2.3]

In [75]: mlist[0:2]
__getitem__() called
slice(0.2.None)
Out[75] : [1.2]

In [76]: mlist[::-1]
__getitem__() called
slice(None.None, -1)
Out[76] : [3.2.1]

In [77]: mlist[0]
__getitem__() called
0

In [78]: mlist[0:1]
__getitem__() called
slice(0.1.None)
Out[78] : [1]

In [79] :del mlist[0:1]
__delitem__() called

In [80]: mlist[:]
__getitem__() called
slice(None.None.None)
Out[80] : [2.3]
Copy the code


Note: When mlist[0] is passed, it is not a slice object. It is not a number of type int, so it is not possible to retrieve a value with an index of 0, change it to mlist[0, 1] or add a number judgment to __getitem__(). You can try it.


__enter__, __exit__

The with declaration is a keyword imported from Python2.5. You should have encountered code that looks like this:

with open('foo.txt') as bar:
    # do something with bar
    pass
Copy the code

In the with declaration snippet, we can start and exit objects and handle exceptions. This requires implementing two magic methods: __enter__ and __exit__.

__enter__(self):
Copy the code

Defines the behavior of the session manager when the block is initially created when the with statement is used. Note that the return value of __enter__ is bound to the target of the with statement or to the name after as.

__exit__(self, exception_type, exception_value, traceback):
Copy the code

Defines what the session manager should do when a block of code is executed or terminated. It can be used to handle exceptions, perform cleanup, or do routine work after a block of code has been executed. Exception_type, Exception_value, and Traceback will be None if the code block executes successfully. Otherwise, you can choose to handle the exception or hand it directly to the user. If you want to handle this exception, make sure __exit__ returns True at the end of all statements. If you want the exception to be handled by the session manager, let it generate the exception.


__copy__, __deepcopy__

Sometimes, especially if you’re dealing with mutable objects, you might want to copy an object and then make some changes to it without affecting the original object. This is where Python’s copy comes in.

__copy__(self):
Copy the code

Defines the behavior that happens when you call copy.copy() on an instance of your class. Copy. The copy () returns a shallow copy of the object you – this means that when the instance itself is a new instance, all of its data were cited – for example, when an object itself is copied, its data is still cited (so, for shallow copy still may lead to change the data in the data change in the original object).

__deepcopy__(self, memodict={}):
Copy the code

Defines the behavior that happens when copy.deepCopy () is called on an instance of your class. Copy.deepcopy () returns a deepcopy of your object — both the object and its data have been copied. Memodict is a cache of previously copied objects — this optimizes the copying process and prevents infinite recursion when copying recursive data structures. When you want to make a deepcopy of an individual property, call copy.deepcopy() with memodict as the first argument.


The use cases for these magic methods seem small, and are indeed very practical. They reflect something important about object-oriented programming in Python, and in general Python is always an easy way to find something, even if it’s not necessary. These magic methods may not seem very useful, but if you need them, you’ll be glad they’re there.


Other magic methods

Since there are too many magic properties and methods, I won’t describe them and show them here. The rest will be presented in table form.

Magic method for comparison

methods role
__cmp__(self, other) The most basic magic method in comparison method
__eq__(self, other) The act of defining an equality sign,= =
__ne__(self,other) Defining the behavior of unequal symbols,! =
__lt__(self,other) Defining the behavior of less than sign,<
__gt__(self,other) Defining behavior larger than sign,>
__le__(self,other) Defining the behavior of the less than or equal sign,< =
__ge__(self,other) Defining the behavior of the greater than or equal sign,> =


Magic method of numerical calculation

Unary operators and functions

methods role
__pos__(self) Implement a positive operation
__neg__(self) Implement an operation that takes a negative number
__abs__(self) Implement a built-inabs()Behavior of a function
__invert__(self) Implements an action that takes the inverse operator (the ~ operator)
__round__(self, n) Implement a built-inround()Behavior of a function
__floor__(self) implementationmath.floor()Function behavior of
__ceil__(self) implementationmath.ceil()Function behavior of
__trunc__(self) implementationmath.trunc()Function behavior of


Binocular operator or function

methods role
__add__(self, other) Implement an addition
__sub__(self, other) Implement a subtraction
__mul__(self, other) Implement a multiplication
__floordiv__(self, other) To implement a//The divisible operation produced by the operator
__div__(self, other) To implement a/Operator represents the division operation
__truediv__(self, other) Implement real division
__mod__(self, other) To implement a%The modulo fetch operation represented by the
__divmod__(self, other) Implement a built-in functiondivmod()
__pow__(self, other) Implements the behavior of an exponential operation (****** operator)
__lshift__(self, other) Implement a bit left shift operation ** (<<) ** function
__rshift__(self, other) Implement a bit right shift operation ** (>>) ** function
__and__(self, other) Implements a bitwise action with operation ** (&) **
__or__(self, other) The act of implementing a bitwise operation or operation
__xor__(self, other) The xOR operator is equivalent to^


Incremental algorithms

methods role
__iadd__(self, other) Add the assignment
__isub__(self, other) Subtraction assignment
__imul__(self, other) Multiplication assignment
__ifloordiv__(self, other) Divisible assignment, floor division, is equal to/ / =The operator
__idiv__(self, other) Division assignment is equal to/ =The operator
__itruediv__(self, other) In addition to the assignment
__imod_(self, other) Module assignment is equal to% =The operator
__ipow__(self, other) The power assignment is equal to* * =The operator
__ilshift__(self, other) Left shift assignment is equal to< < =The operator
__irshift__(self, other) Left shift assignment is equal to> > =The operator
__iand__(self, other) And assignment, equivalent to& =The operator
__ior__(self, other) Or assignment
__ixor__(self, other) The xOR operator is equivalent to^ =The operator


Type conversion

methods role
__int__(self) To an integer
__long__(self) Converts to a long integer
__float__(self) Convert to floating point
__complex__(self) Convert to the complex form
__oct__(self) Convert to octal
__hex__(self) Convert to hexadecimal
__index__(self) If you define a numeric type that can be used for slicing, you should__index__
__trunc__(self) whenmath.trunc(self)Called when used__trunc__Returns an interception of an integer of its own type
__coerce__(self, other) Performs operations of mixed types


The source code

The source code has been uploaded to Gitee PythonKnowledge: PythonKnowledge Repository.

✍ code word is not easy, but also hope you heroes support ❤️.


The public,

Create a new folder X

Nature took tens of billions of years to create our real world, while programmers took hundreds of years to create a completely different virtual world. We knock out brick by brick with a keyboard and build everything with our brains. People see 1000 as authority. We defend 1024. We are not keyboard warriors, we are just extraordinary builders of ordinary world.