A detailed introduction to the Python Magic method

Source: Internet
Author: User
Tags integer division

Introduced

In Python, all the "double-underline" methods are collectively referred to as "magic methods", such as the initialization method of a class, init where all the magic methods in Python are described in official documents, but the official description is confusing and loosely organized. It is hard to find an example.

Construct and initialize

Every pythoner knows one of the most basic methods of magic init . With this method we can define the initial operation of an object. However, when x = SomeClass () is called, it init is not the first method to be called. In fact, there is a new method called, the two together constitute the "constructor."

  newis used to create a class and return an instance of the class, but init simply to initialize the instance with the arguments passed in.

At the end of the object life cycle call, the del method is called and can be del interpreted as a destructor. Here's a look at these three methods through the code:

From Os.path import joinclass fileobject:    "" Wraps the file object to confirm that the file stream is closed when deleting '    def init (self, filepath= ' ~ ', filename= ' Sample.txt '):        #读写模式打开一个文件        self.file = open (Join (filepath, filename), ' r+ ')    def del (self):        Self.file.close ()        del self.file

Controlling Property access

Many people who go from other languages to Python complain that it lacks a true encapsulation of classes. (There is no way to define a private variable and then define a public getter and setter). Python can actually complete the encapsulation by magic method. Let's take a look:

    • getattr(self, name):

Defines the behavior when a user attempts to obtain a property that does not exist. This applies to getting and redirecting common misspellings, giving a warning if you want to get some unwanted attributes (you can also calculate and give a value if you like) or handle a attributeerror . It is returned only when a property that does not exist is called.

    • setattr(self, name, value):

With getattr(self, name) different, setattr is a packaged solution. Regardless of whether a property exists, it allows you to define the assignment behavior of the property, so that you can personalize the value of the property. setattrAvoid "infinite recursion" errors when implemented.

    • delattr:

With the setattr same, but the function is to delete a property instead of setting them. When implemented, it is also necessary to prevent the occurrence of infinite recursion.

    • getattribute(self, name):

  getattributeDefines the behavior when your property is accessed, and it getattr only works if the property does not exist. Therefore, in a supported getattribute python version, it getattr must be called before the call getattribute . getattributealso avoid "infinite recursion" errors. To be reminded, it's best not to try it getattribute out, because it's rare to see it, and it's easy to make bugs.

The "infinite recursion" is likely to be easily caused by the definition of a property access control. As in the following code:

#  Error Usage def setattr (self, Name, value):    self.name = value    # Every time a property is assigned (such as Self.name = value), ' setattr () ' will be called , which results in recursive invocation.    # This means that it will call ' self.setattr ' (' name ', value) ', each time the method calls itself. This can cause the program to crash. #  correct usage def setattr (self, Name, value):    self.dict[name] = value  # Assigns a value to a property name in a class    # custom-specific properties

Python's magic methods are powerful, but they need to be handled with great caution, and it is important to understand how to use them correctly.

Creating a custom container

There are many ways to make your Python class behave like a built-in container type, such as the list, dict, tuple, string, and so on that we use. Python's container types are divided into mutable types (such as list, dict) and immutable types (such as string, tuple), variable containers and immutable containers, where immutable containers cannot be modified once they have been assigned a value.
Before you talk about creating a custom container, you should understand the following protocol. The protocol here is similar to the so-called "interface" concept in other languages, and it gives you a lot of methods you have to define. However, the protocol in Python is very informal and does not require a clear declaration of implementation. In fact, they are more like a guide.

Magic Method for custom containers

The following is a detailed understanding of the Magic method used to define the container. First, if you implement an immutable container, you can only define len and getitem (more below). The variable container protocol requires all of the immutable containers, plus the setitem and delitem . If you want your object to be iterative, you need to define iter an iterator that will return. Iterators must follow the iterator protocol and need to have iter (return itself) and next.

    • len(self):

Returns the length of the container. This is part of the protocol for mutable and immutable containers.

    • getitem(self, key):

Defines the behavior that occurs when an item is accessed using Self[key] . This is also part of the immutable container and the variable container protocol. If the type of the key is wrong, the TypeError will be generated and if the key does not have a proper value then the Keyerror is generated.

    • setitem(self, key, value):

When you execute self[key] = value , the method is called.

    • delitem(self, key):

Defines the behavior when an item is deleted (such as del Self[key]). This is only part of the Mutable container protocol. The appropriate exception should be thrown when an invalid key is used.

    • iter(self):

Returns a container iterator that, in many cases, returns an iterator, especially when the built-in iter () method is called, and when using the for x in container: mode loop. Iterators are objects of their own, and they must define a method that returns self iter .

    • reversed(self):

Implements the behavior when reversed () is called. The inverted version of the sequence should be returned. Implement it only when the sequence can be ordered, for example, for lists or tuples.

    • contains(self, item):

Defines the behavior that occurs when both in and not are called to test the presence of a member. You may ask why is this not part of the sequence protocol? Because when not defined, contains python iterates over the elements in the container to make a comparison, thus determining whether to return true or false.

    • missing(self, key):

The Dict dictionary type has this method, which defines the behavior that is triggered if key is not found in the container. For example, d = {' A ': 1}, when you execute d[notexist] , d.missing['notexist'] it will be called.

A column child

The following is an example of a book that implements a data structure in the Haskell language using magic methods.

#-*-Coding:utf-8-*-class functionallist: ' Implements the built-in type list function and enriches some other methods: Head, tail, init, last, drop, take ' de F init (self, values=none): If values is None:self.values = [] Else:self.values = Val UEs def len (self): return Len (self.values) def getitem (self, key): Return Self.values[key] def SETI TEM (self, Key, value): Self.values[key] = value def delitem (self, key): Del Self.values[key] def ITER ( Self): return iter (self.values) def reversed (self): return functionallist (Reversed (self.values)) def a Ppend (self, Value): Self.values.append (value) def head: # Get the first element return Self.values[0] D EF tail (self): # gets all elements after the first element return Self.values[1:] def init (self): # gets all elements before the last element re Turn self.values[:-1] def end (self): # Gets the last element return SELF.VALUES[-1] def drop (self, n): # get All elements except the first n return Self.values[n:] def takes (self, n): # Gets the first n elements return self.values[:n] 

  
In fact, in the collections module has a lot of similar implementations, such as counter, ordereddict and so on.

Reflection

You can also control how to use the built-in function sisinstance () and the Issubclass () method to define the magic method of reflection. This magic method is:

    • instancecheck(self, instance):

Check if an instance is not an instance of the class you defined

    • subclasscheck(self, subclass):
      Check whether a class is a subclass of a class that you define

The use cases for these magic methods look small and really practical. They reflect something important about object-oriented programs on Python, and in general Python: There's always a simple way to find something, even if it's not necessary. These magical methods may not seem very useful, but once you need them, you will feel thankful for their existence.

Objects that can be called

As you may already know, in Python, the method is the most advanced object. This means that they can also be passed to the method, just like any other object. This is a very amazing feature.

In Python, a special magic method allows instances of a class to behave like functions, you can invoke them, pass a function as one parameter to another function, and so on. This is a very powerful feature that makes Python programming more comfortable and sweet.

    • call(self, [args...]):

Allows an instance of a class to be called like a function. Essentially, this means that x () x.call() is the same as it is. Note that call the parameters are variable. This means that you can define the call other functions you want, regardless of the number of arguments.

  callIt is very effective when instances of those classes often change state. Invoking this instance is a direct and elegant way to change the state of this object. Use an example to express the best:

#-*-Coding:utf-8-*-class entity: "" "    invokes entities to change the position of the entity    " "Def init (self, size, x, y):    self.x, self.y = x, y    self.size = Sizedef call (self, x, y): ""    Change the position of the entity    "" "    self.x, self.y = x, y

Context Management

   The WITH declaration is a keyword introduced from Python2.5. You should have encountered a code like this:

With open (' foo.txt ') as bar:    # does something with bar

In the code snippet with declarations, we can do some object start and exit operations, and we can also handle exceptions. This requires the implementation of two magic methods: enter and exit .

    • enter(self):

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

    • exit(self, exception_type, exception_value, traceback):

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 work, or do routine work after some code blocks have been executed. If the code block executes successfully, Exception_type,exception_value, and Traceback will be none. Otherwise, you can choose to handle this exception or simply hand it over to the user. If you want to handle this exception, be sure to exit return true after all statements have been completed. If you want the exception to be handled by the session manager, let it produce the exception.

Creating an Object Descriptor

A descriptor is a class that is accessed by acquiring, setting, and deleting. Of course, you can change other objects as well. The descriptor is not independent. Instead, it means being held by an owner class. Descriptors are useful when creating object-oriented databases or classes that contain interdependent zodiac. A typical use method is to represent the same value in different units, or to represent an attached property of a data.
In order to become a descriptor, a class must have at least one get set , and the delete method is implemented:

    • get(self, instance, owner):

      Defines the behavior when the value of the descriptor is taken. Instance is an instance of the object that owns the descriptor. Owner is the owner itself

    • set(self, instance, value):

      Defines the behavior when the value of the descriptor is changed. Instance is an instance of the class that owns the descriptor. Value is the values to set.

    • delete(self, instance):

      Defines the behavior when the value of the descriptor is deleted. Instance is an instance of the object that owns the descriptor.

The following is an example of a descriptor: unit conversion.

#-*-Coding:utf-8-*-class Meter (object): ""    for the unit "meter" descriptor "" "    def init (self, value=0.0):        Self.value = Float (value)    def get (self, instance, owner):        return self.value    def set (self, instance, value):        Self.value = Float (value) class Foot (object): ""    for the unit "foot" of the descriptor    "" "    def get (self, instance, Owner):        return instance.meter * 3.2808    def set (self, instance, value):        Instance.meter = float (value)/ 3.2808class Distance (object): "" "    means the distance between two descriptors in meters and inches" "    meter = meter (x)    foot = foot ()

When used:

>>>d = Distance () >>>print d.foot>>>print d.meter32.80810.0

Copy

Sometimes, especially when you're working with mutable objects, you might want to copy an object and then make some changes to it instead of trying to influence the original object. This is where Python's copy works.

    • copy(self):

Defines the behavior that occurs when you call copy.copy () on an instance of your class. copy.copy () returns a shallow copy of your object-which means that when the instance itself is a new instance, all its data is referenced-for example, when an object itself is copied, its data is still referenced (therefore, Changes to data in a shallow copy can still cause the data to change in the original object.

    • deepcopy(self, memodict={}):

Defines the behavior that occurs when you call copy.deepcopy () on an instance of your class. copy.deepcopy () returns a deep copy of your object-the object and its data are copied. Memodict is a cache of previously copied objects-this optimizes the copy process and prevents infinite recursion when copying a recursive data structure. When you want to make a deep copy of a separate property, call copy.deepcopy ()and take memodict as the first parameter.

Appendix

The Magic method for comparison

Magic Method explain
cmp(self, other) Is the most basic method of magic in comparison.
eq(self, other) Define the behavior of the equality symbol, = =
ne(self,other) Define the behavior of unequal symbols! =
lt(self,other) Defines a behavior that is less than a symbol,<
gt(self,other) Defines a behavior greater than the symbol,>
le(self,other) Defines behavior that is less than or equal to the symbol, <=
ge(self,other) Defines behavior that is greater than or equal to the symbol, >=

The Magic method of numerical calculation

Monocular Operators and functions

Magic Method explain
pos(self) Implement an operation that takes a positive number
neg(self) Implement an operation that takes a negative number
abs(self) Implement the behavior of an built-in ABS () function
invert(self) Implementing the behavior of a take-back operator (~ operator)
round(self, n) Implement the behavior of a built-in round () function
floor(self) Implementing the function behavior of Math.floor ()
ceil(self) Implementing the function behavior of Math.ceil ()
trunc(self) Implementing the function behavior of Math.trunc ()

Binocular operator or function

Magic Method explain
add(self, other) Implement an addition
sub(self, other) Implement a subtraction
mul(self, other) Implement a multiplication
floorp(self, other) Implements an integer division operation produced by a "//" operator ()
p(self, other) Implement a division operation represented by a "/" operator
truep(self, other) Achieve Real Division
mod(self, other) Implement a modulo operation represented by a "%" operator
pmod(self, other) Implement a built-in function pmod ()
pow Implements the behavior of an exponential operation (the "* *" operator)
lshift(self, other) Implements the function of a bitwise left shift (<<)
rshift(self, other) Implements a bitwise right SHIFT operation (>>) function
and(self, other) Implementing a bitwise AND operation (&) behavior
or(self, other) Implement a bitwise OR action behavior
xor(self, other) xor(self, other)

Increment operation

Magic Method explain
iadd(self, other) Addition Assignment
isub(self, other) Subtraction Assignment
imul(self, other) Multiply Assign Value
ifloorp(self, other) Divisible assignment, floor divide, equivalent to//= operator
ip(self, other) Division assignment, equivalent to the/= operator
itruep(self, other) True except Assignment
imod_(self, other) Modulo assignment, equivalent to the%= operator
ipow Exponentiation, equivalent to the **= operator
ilshift(self, other) Shift assignment to the left, equivalent to the <<= operator
irshift(self, other) Shift assignment to the left, equivalent to the >>= operator
iand(self, other) With assignment, equivalent to the &= operator
ior(self, other) or assign a value
ixor(self, other) Xor operator, equivalent to ^= operator

Type conversions

TR class= "odd" >
Magic method explain
int (self) Convert to Integer
long (self) convert growth integer
float (self) Convert to floating-point
complex (self) convert to complex type
Oct (self) convert to octal
hex (self) convert to hex
index (self) If you define a numeric type that might be used for slicing, you should define index
trunc (self) when Math.trunc is called trunc returns an integer intercept of its own type
coerce (self, other) perform mixed-type operations
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.