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."
new
is 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:
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.
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. setattr
Avoid "infinite recursion" errors when implemented.
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
Defines 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
. getattribute
also 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.
Returns the length of the container. This is part of the protocol for mutable and immutable containers.
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.
When you execute self[key] = value , the method is called.
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.
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
.
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.
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.
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:
Check if an instance is not an instance of the class you defined
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.
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.
call
It 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
.
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.
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.
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.
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
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 |
TR class= "odd" >
coerce (self, other) |
perform mixed-type operations |