Introduced
This tutorial is one of the highlights of my several articles. The theme is the Magic method. What is the Magic method? They are all object-oriented python. They are special ways to add "magic" to your class. They are always surrounded by a double underline (e.g __init__ or __lt__). However, their documentation is far from providing what should be. All the magic methods in Python are described in the official Python documentation, but their descriptions are confusing and loosely organized. It is difficult to find an example (perhaps they intended to be very good, in the beginning of the language reference is described in detail, but then it is really a boring syntax description, etc.).
So, to fix the flaws I think the python document should fix, I decided to provide some of the magic methods in Python with plain language and instance-driven documents. I have written several posts at the beginning and now summarize them in this article.
I hope you will like this article. You can use it as a tutorial, a tutoring material, or a reference. The purpose of this article is simply to provide a friendly tutorial for the magic methods in Python.
Construction and initialization
Everyone knows one of the most basic magic methods, __init__. In this way we can define the initial operation of an object. However, when I call x = SomeClass (), __init__ is not the first method to be invoked. In fact, there is also a method called __new__ to construct this instance. Then give the initialization function to pass the argument at the start of the creation. At the other end of the object lifecycle, there is also a __del__ method. Now let's take a closer look at these three methods:
The __new__ (CLS, [...) __new__ is the first method invoked when an object is instantiated. Its first argument is this class, and the other parameters are used to pass directly to the __init__ method. The __new__ method is quite infrequently used, but it has its own characteristics, especially when inheriting an immutable type such as a tuple or string. I don't want to have too much detail on the __new__ because it's not very useful, but it's detailed in the Python documentation http://www.python.org/download/releases/2.2/descrintro/__.
__init__ (self, [...) This method is the initialization method for the class. Any arguments that are invoked when the constructor is called will be passed to it. (For example, if we call x = SomeClass (' foo ')], then __init__ will get two parameters 10 and foo. __INIT__ is widely used in Python's class definitions.
__del__ (self) if __new__ and __init__ are constructors of objects, then __del__ is the destructor. It does not implement the Statement del X (so the code will not translate to x.__del__ ()). It defines the behavior of an object when it is garbage collected. This method can be useful when an object needs more cleaning work when it is deleted, such as a socket object or a file object. Note that the __del__ can ' t serve as a replacement for good coding practices () ~~~~~~~ if the object still exists when the interpreter exits and does not guarantee that __del__ can be executed.
Put together, here is an example of the actual use of __init__ and __del__.
Copy Code code as follows:
From Os.path Import Join
Class FileObject:
"To wrap the file object to confirm that the file stream closes on deletion"
def __init__ (self, filepath= ' ~ ', filename= ' sample.txt '):
#读写模式打开一个文件
Self.file = open (Join (filepath, filename), ' r+ ')
def __del__ (self):
Self.file.close ()
Del Self.file
Make Custom classes work
The biggest advantage of using Python's magic methods is that they provide an easy way to make objects behave like built-in types. That means you can avoid ugly, counterintuitive, non-standard ways of doing things. In some languages, some of the operations are common, such as:
Copy Code code as follows:
If Instance.equals (other_instance):
# do something
You can do this in Python. But this can be confusing and unnecessarily redundant. The same operation can result in unnecessary work because different libraries use different names. However, with the power of the Magic method, we can define a method (in this case, __eq__) that explains what we mean:
Copy Code code as follows:
If instance = = Other_instance:
#do something
This is only a small part of the Magic Method's function. It allows you to define the meaning of the symbols so that we can use them in our class. Just like the built-in type.
A magic method for comparison
Python's comparison of implementing objects, using magic methods to make a big reversal, makes them very intuitive rather than clumsy method calls. It also provides a way to override Python's default behavior for object comparisons (by reference). Here are the methods and their roles.
__cmp__ (self, other) __cmp__ is the most basic magic method for comparison. It actually implements all the comparison symbols (<,==,!=,etc.), but its performance does not always work as you wish (for example, when an instance is equal to another instance is judged by a rule, and one instance is larger than the other is judged by another rule). If self < Other say __cmp__ should return a negative number, when self = = O will return 0, and when self > Other will return a positive number. Usually the best way is to define each comparison symbol separately rather than define them all at once. But the __cmp__ approach is that you want to implement all the comparison symbols and a good way to stay clear.
__eq__ (self, other) defines the behavior of an equal sign, = =.
__ne__ (self, other) defines a behavior that is not equal,!=.
__lt__ (self, other) defines the behavior of the less than number, <.
__gt__ (self, other) defines the behavior greater than the equals number, >=.
To give an example, create a class to represent a word. We might want to compare the dictionary order of words (through the alphabet) by default string comparisons, but we also want to implement some other criteria, such as the length of words or the number of syllables. In this example, we compare the length implementation. Here is the implementation code:
Copy Code code as follows:
Class Word (str):
"' stores the class of words, defines several ways of comparing words '"
def __new__ (CLS, Word):
# Note We have to use the __new__ method, Because STR is an immutable type of
# So we have to initialize it when we create it
if ' in Word:
print ' Value Contains spaces. Truncating to the.
Word = Word[:word.index (')] # Words are all characters before the first space
return str.__new__ (CLS, word)
def __gt__ (self, Other):
Return Len (self) > len (Other)
def __lt__ (self, Other):
Return Len (self) < Len (Other)
def __ge__ (self, Other):
Return Len (self) >= len (Other)
def __le__ (self, Other):
Return Len (self) <= len (Other)
Now we create two Words objects (by using Word (' foo ') and Word (' bar ') and then comparing them by length. Note that we do not define __eq__ and __ne__ methods. This is because there will be some weird results (e.g. word (' foo ') = = Word (' bar ') will return true). This is not very meaningful for testing based on length comparisons. So we're going to go back and use the STR built-in to compare.
Now you know you don't have to define every magic method of comparison to make a rich comparison. The very friendly decorator in the standard library that gives us a class in Functiontols defines all the rich comparison functions. If you just define __eq__ and the other one (e.g __gt__, __lt__,etc.) This feature only exists in Python 2.7, but you will save a lot of time and manager if you have a chance to run into it. You can use it by placing @total_ordering in front of the class you define.
The Magic method of numerical processing
As you create many methods when comparing instances of classes by comparing them, you can also define the characteristics of some numeric symbols. Fasten your seatbelt, come on, there's a lot of content here. For organizational convenience, I'll divide the numerical processing into five classes: unary operators, ordinary arithmetic operators, reflection arithmetic operators (which will be detailed later), incremental assignments, and type conversions.
unary operators and functions
There is only one unary operator and function for an action bit. such as absolute value, negative and so on.
__pos__ (self) implements the characteristics of a positive sign (e.g. +some_object)
__neg__ (self) implements the characteristics of the minus sign (e.g.-some_object)
__abs__ (self) implements the properties of the built-in ABS () function.
__invert__ (self) implements the character of the ~ symbol. To illustrate this feature. You can view this article in Wikipedia
Ordinary arithmetic operator
Now we just cover the normal binary operators: +,-, * and similar symbols. Most of these symbols are plain and easy to understand.
__add__ (self, other) implements addition. __sub__ (self, other) implements subtraction. __mul__ (self, other) implements multiplication. Integer division implemented//signed by __floordiv__ (self, other). __div__ (self, other) implementation/symbol division. __truediv__ (self, other) implements true division. Note that it works only if you use the From __FUTURE__ Import division. __mod__ (self, other) implements the modulo algorithm% __divmod___ (self, other) to implement the built-in Divmod () algorithm __pow__ implement the exponential operation __lshift__ (self, other) implementation using * * << The bitwise Left Movement __rshift__ (self, other) implementation uses >> bitwise LEFT Movement __and__ (self, other) implementations using & bitwise-and __or__ (self, other) implementations to make with | Bitwise OR __xor__ (self, other) implementations that use ^ 's bitwise XOR OR
Inverse operation
Below I will explain some of the inverse operation knowledge. There are some concepts that you might think are scary or unfamiliar. But it's actually very simple. Here is an example:
Copy Code code as follows:
This is a common addition operation, the inverse operation is the same, but the number of switches to the position:
Copy Code code as follows:
So, in addition to being the second operand when working with other objects, all of these magic methods are the same as normal operations. In most cases, the result of the inverse operation is the same as the normal operation. So you can you can equate __radd__ with __add__.
__radd__ (self, other) implements the anti-__rsub__ (self, other) implementation of the reverse subtraction __rmul__ (self, other) implementation///symbol counter removal __ The rdiv__ (self, other) implementation/symbol __rtruediv__ (self, other) implementations are reversed, only when the From __FUTURE__ Import Division __rmod__ (self, Other) Implement the inverse modulo operation of the% symbol __rdivmod__ (self, other) when Divmod (other, self) is invoked, implement the inverse operation of the built-in Divmod () __rpow__ implement the inverse of the * * symbol __RLSHIF T__ (self, other) implements the reverse-left displacement of the << symbol __rrshift__ (self, other) implementation >> symbol Anti-Rightist displacement __rand__ (self, other) realize & symbol Inverse and Operation _ _ror__ (self, other) implementation | Negation or operation of a symbol __xor__ (self, other) to achieve the negation or operation of the ^ symbol
Incremental assignment
Python also has a number of magic ways to customize incremental assignment statements. You may already be familiar with incremental assignment, which combines operators with assignments. If you're still not sure what I'm talking about, here's an example:
Copy Code code as follows:
x = 5
x + 1 # In the other words x = x + 1
__iadd__ (self, other) implements assignment addition __isub__ (self, other) implement assignment subtraction __imul__ (self, other) implement assignment multiplication __ifloordiv__ (self, other) implement//= Assignment floors except __idiv__ (self, other) implement the assignment of the symbol/= except __itruediv__ (self, other) implementation assignment true, only use the From __FUTURE__ Import Division to use the __i Mod_ (self, other) implementation of the symbolic%= assignment modulo __ipow__ implementation of the symbolic **= assignment power operation __ilshift__ (self, other) to implement the symbolic <<= assignment bit left-shift __irshift__ (self, Other) implements the assignment bit of the symbolic >>= right shift __iand__ (self, other) to implement the assignment bit of the symbolic &= and __ior__ (self, other) to implement the symbolic |= of the assigned bit or __ixor__ (self, oth ER) to implement the |= of the symbolic value or
Type Conversion Magic method
Python also has a number of magic ways to implement the built-in type conversion features like float (). __int__ (self) Implementation of the cast __long__ (self) to implement long shaping the cast __float__ (self) Implementation of a floating-point cast __complex__ (self) to implement a cast of a complex number __oct__ (self) Implementation of the octal cast __hex__ (self) Implementation of the binary cast __index__ (self) When an object is applied to a slice expression, a cosmetic cast is implemented, and if you define a custom numeric type that may be used in slicing, you should define the __index_ _ (see PEP357) __trunc__ (self) is invoked when math.trunc (self) is used. __TRUNC__ should return the value __coerce__ (self, other) that is truncated to a shape (usually long) to implement a mixed-mode arithmetic. If the type conversion is not possible, then __coerce__ will return None, otherwise he will return a length of 2 tuple for self and other, and two for the same type.
Show your class.
It would be useful if you had a string to represent a class. In Python, there are many ways to implement the return values of some functions built into a class definition. __STR__ (self) defines the return value that the return value __repr__ (self) defines when repr () is invoked when Str () is invoked. The main difference between STR () and repr () is that repr () returns machine-readable output, while STR () returns human-readable. __UNICODE__ (self) defines the return value when Unicode () calls are invoked. Unicode () and STR () are similar, but return a Unicode string. Note that if you call Str on your class (a) but you only define __UNICODE__ (), then it will not work. You should define __STR__ () to ensure that the correct values are returned when invoked.
__hash__ (self) defines the return value when the hash () call returns an integer that is used to quickly compare __nonzero__ (self) in the dictionary to define the return value when bool () is invoked. This method should return true or false, depending on the value you want it to return.
Control Property Access
Many people who go from other languages to Python complain that it lacks a real encapsulation of the class. (There is no way to define a private variable and then define a public getter and setter). Python can actually do the encapsulation by magic method. Let's take a look at:
__getattr__ (self, name) you can define the behavior when a user attempts to acquire an attribute that does not exist. This applies to getting and redirecting common spelling errors, warning you about getting some of the not-recommended attributes (you can calculate and give a value if you want), or handle a attributeerror. Will be returned only if no existing property is invoked. However, this is not a packaged solution. __setattr__ (self, name, value) differs from __getattr__, __SETATTR__ is a packaged solution. Regardless of whether the attribute exists, it allows you to define the assignment behavior to the attribute, thinking that you can personalize the value of the attribute. But you have to be very careful about using __setattr__. We'll elaborate on that later. __DELATTR__ is the same as __setattr__, but the function is to delete a property instead of setting them. Note the same as the __setattr__, prevent the occurrence of infinite recursive phenomenon. (The Call Del self.name occurs when the __delattr__ is implemented) __getattribute__ (self, name) __getattribute__ with its companion __setattr__ and __delattr__ with Very good. But I don't recommend using it. __GETATTRIBUTE__ can only be used in the new type class definition (all classes in the latest version of Python are new types, and in older versions you can create a new class by inheriting object.) This allows you to define an access rule for a property value. Sometimes there are also some phenomena of the emperor. (You can then call the __getattribute__ method of the base class to prevent this from happening.) It can eliminate the use of __getattr__, if it is explicitly called or a attributeerror is thrown, then the __getattribute__ can be invoked after implementation. Whether or not this method is used actually ultimately depends on your choice. I don't recommend using it because it's less likely to be used (it's very rare to have special behavior when we're getting a value instead of setting a value). And it does not prevent bugs from appearing.
You can easily cause an error when you make a property access control definition. Consider the following example.
Copy Code code as follows:
def __setattr__ (self, Name, value):
Self.name = value
#每当属性被赋值的时候, ' __setattr__ () ' will be invoked, thus causing a recursive call.
#这意味这会调用 ' self.__setattr__ (' name ', value '), each method calls itself. This can cause the program to crash.
def __setattr__ (self, Name, value):
Self.__dict__[name] = value #给类中的属性名分配值
#定制特有属性
Python's Magic method is very powerful, but with it comes responsibility. It is important to know the right way to use it.
So how much do we know about custom attribute access rights? It should not be used lightly. Actually, it's very powerful. But the reason for this is that Python does not try to make something bad impossible, but it makes it difficult to achieve. Freedom is paramount, so you can do whatever you want. This is a special example of attribute control (we use super because not all classes have __dict__ attributes):
Copy Code code as follows:
Class Accesscounter:
' A class that contains the control of a counter that is incremented whenever the value is changed
def __init__ (Self, Val):
Super (Accesscounter, self). __setattr__ (' counter ', 0)
Super (Accesscounter, self). __setattr__ (' value ', Val)
def __setattr__ (self, Name, value):
If name = = ' Value ':
Super (Accesscounter, self). __setattr__ (' counter ', Self.counter + 1)
#如果你不想让其他属性被访问的话, you can throw the Attributeerror (name) exception
Super (Accesscounter, self). __SETATTR__ (name, value)
def __delattr__ (self, name):
If name = = ' Value ':
Super (Accesscounter, self). __setattr__ (' counter ', Self.counter + 1)
Super (Accesscounter, self). __DELATTR__ (name)]
Create a custom sequence
There are many ways to make your Python class behave like a built-in sequence (Dict, Tuple,list, String, and so on). This is my favorite magic method because it gives you a lot of control and makes many functions work well on your class instances. But before you start, you need to talk about some of the necessary conditions.
Must condition
Now we're going to start talking about how to create a custom sequence in Python, and this is the time to talk about protocols. Protocol (protocols) is similar to interfaces in other languages. It gives you a lot of ways you have to define. However, the protocols in Python are very informal and do not need to be explicitly declared. In fact, they are more like a guide.
Why are we discussing the agreement now? Because these protocols are needed if you want to customize the container type. First, there is a protocol to implement the invariant container: You can only define __LEN__ and __getitem__ (for a few more) if you implement immutable containers. The variable container protocol requires all additional __setitem__ and __delitem__ for all immutable containers. Ultimately, if you want your object to be iterative, you need to define __iter__ to return an iterator. Iterators must follow the iterator protocol and need to have __iter__ (return itself) and next.
The magic behind the container
These are the magic methods used by the container. __len__ (self) is the container length. Part of the protocol required for variable immutable containers. __getitem__ (self, key) defines the use of the symbol Self[key] When an entry is accessed. This is also part of the protocol for immutable and variable containers. If the key is of type error and Keyerror or does not have an appropriate value. Then you should throw the appropriate TypeError exception. __setitem__ (self, key, value) defines the behavior when an entry is assigned, using self[key] = value. This is also part of a variable container and an immutable container protocol. __delitem__ (self, key) defines the behavior (such as Del Self[key]) when an entry is deleted. This is only part of the variable container protocol. The appropriate exception should be thrown when an invalid key is used. __ITER__ (self) Returns an iterator for a container. In many cases, the iterator is returned, especially if the built-in ITER () method is invoked, or when the for X in container mode is used. Iterators are objects of their own, and they must define the __iter__ method that returns self. __reversed__ (self) implements the behavior when reversed () is invoked. You should return a reverse version of the list. __contains__ (self, item) is defined when the call in and not is to test the presence of a member __contains__. You ask why this is not part of the serial protocol? That's because when __contains__ is not defined, Python iterates through the sequence and returns TRUE when the desired value is found. __concat__ (self, other) in the end, you can define the behavior of a two-sequence connection by using the __concat__. When the + operator is invoked, it returns a new sequence produced by the result of the invocation of self and other.__concat__.
An example
In our example, let's take a look at the implementation of a function construct statement that you might use in other languages (such as Haskell).
Copy Code code as follows:
Class Functionallist:
"A list class that encapsulates some additional magic methods such as head, tail, init, last, drop, and take.
'''
def __init__ (self, Values=none):
If values is None:
Self.values = []
Else
Self.values = values
def __len__ (self):
Return Len (self.values)
def __getitem__ (self, key):
#如果键的类型或者值无效, the list value will throw an error
return Self.values[key]
def __setitem__ (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 reversed (self.values)
def append (self, value):
Self.values.append (value)
def head (self):
return Self.values[0]
def tail (self):
Return Self.values[1:]
def init (self):
#返回一直到末尾的所有元素
return Self.values[:-1]
Def last (self):
#返回末尾元素
return Self.values[-1]
def drop (self, n):
#返回除前n个外的所有元素
Return Self.values[n:]
def take (self, n):
#返回前n个元素
return SELF.VALUES[:N]
Reflection
you can control the reflection behavior using Isinstance () and Issubclass () built-in methods by magic methods. These magic methods are:
Copy Code code as follows:
__instancecheck__ (self, instance)
Check that an instance is not an instance of the class you are defining
Copy Code code as follows:
__subclasscheck__ (self, subclass)
Check that a class is not a subclass of the class you define
It may be true that the use cases of these methods seem to be few. I will not spend more time on these magic methods because they are not important, but they do reflect some of the basic features of object-oriented programming in Python: It's very easy to do something, even if it's not necessary. These magic methods don't look very useful, but you'll be happy to have them when you need them.
Objects that can be invoked
You may already know that in Python, the method is also an advanced object. This means that they can also be passed into methods just like other objects. This is a very striking feature. In Python, a special magic method allows the behavior of instances of a class to behave like functions, and you can call them, pass a function as a 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 invoked like a function. Essentially, this means that X () is the same as x.__call__ (). Note that the __call__ parameter is variable. This means that you can define __call__ for other functions you want, regardless of the number of parameters.
__call__ can be very effective when instances of those classes often change state. Calling this instance is a direct and elegant way to change the state of this object. The best thing to say is to use an example:
Copy Code code as follows:
Class Entity:
"" calls the entity to change the position of the entity. '''
def __init__ (self, size, x, y):
self.x, self.y = x, y
Self.size = Size
def __call__ (self, x, y):
"Change the position of the entity"
self.x, self.y = x, y
Session Management
In Python 2.5, a new keyword with statement is defined for code use. Session control is not uncommon in Python (previously implemented as part of a library) until the PEP343
Copy Code code as follows:
With open (' foo.txt ') as bar:
# perform some action with bar
The reply controller sets up and cleans up the behavior by wrapping a with statement. The behavior of the reply controller is defined by two magic methods: __enter__ (self) defines the behavior of the session manager when the WITH statement is used to create the initial block. Note that the return value of the __enter__ is bound to the target of the WITH statement or the name after the 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, work clearly, or do a routine after the execution of some code blocks. If the code block executes successfully, Exception_type, Exception_value, and Traceback will be None. Otherwise, you can choose to handle this exception or direct it to the user. If you want to handle this exception, confirm that __exit__ returns True after all of the ends. If you want the exception to be handled by the session manager, then do so.
__enter and __exit__ are helpful for defining well-defined and routine behavior settings and cleaning work classes. You can also use these methods to create general session managers that can wrap other objects. Here is an example.
Copy Code code as follows:
Class Closer:
"' Closes the session manager ' of an object through the With statement and a Close method
def __init__ (self, obj):
Self.obj = obj
def __enter__ (self):
Return Self.obj # bound to target
def __exit__ (self, exception_type, Exception_val, trace):
Try
Self.obj.close ()
Except Attributeerror: # obj isn ' t closable
print ' Not closable. '
Return True # exception handled successfully
Here is an example of using Closer, using an FTP link to prove (a closed socket):
Copy Code code as follows:
>>> from magicmethods import Closer
>>> from Ftplib import FTP
>>> with Closer (FTP (' ftp.somesite.com ')) as Conn:
... conn.dir ()
...
>>> Conn.dir ()
>>> with Closer (int (5)) as I:
.. i + 1
...
Not closable.
>>> I
6
You have seen how our wrapper handles the proper and inappropriate use behavior in a silent way. This is a powerful feature of Session Manager and Magic methods.
To create a descriptor for an object
A descriptor is a class that is accessed by getting, setting, and deleting. Of course, you can modify other objects as well. Descriptors are not encouraged, they are destined to be held by an owner class. Descriptors are useful when creating object-oriented databases or classes that contain interdependent properties. A typical use is to represent the same number in different units, or to represent an additional attribute of a data (such as a point in a coordinate system that contains the distance from that point to the far point).
In order to construct a descriptor, a class must have at least __get__ or __set__ one of them, and __delete__ is implemented. Let's take a look at these magic methods. __get__ (self, instance, owner) defines the behavior when the value of the descriptor is obtained, instance is an instance of the owner object. Owner is the owner class itself. __set__ (self, instance, value) defines the behavior when the descriptor value is changed. Instance is an instance of the owner class value that you want to set. __delete__ (self, instance) defines the behavior when the value of the descriptor is deleted. Instance is an instance of the owner object. The following is an instance of a descriptor: unit conversion.
Copy Code code as follows:
Class Meter (object):
' descriptor for a Meter. '
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):
&nb sp; ' descriptor for a foot. ' "
def __get__ (self, instance, owner):
return instance.meter * 3.2808
& nbsp; def __set__ (self, instance, value):
instance.meter = float (value)/3.2808
Class Distance (object):
' class to represent Distance holding two descriptors for feet and
meters. '
meter = meter ()
foot = foot ()
Store your objects.
If you've been in contact with other Pythoner, you've probably heard of Pickle, Pickle is a module used to serialize Python data structures, which is useful when you need to temporarily store an object (such as caching), but it's also the birthplace of the pitfalls.
Serialization data is a very important feature, so he not only has the relevant modules (Pickle, Cpickle), but also his own protocols and magic methods, but first, we will first discuss the method of serialization of the built-in data structure.
Pickling: A simple example
Let's delve into Pickle, for example, you need to temporarily store a dictionary, you can write it to a file, and be careful to ensure that the format is correct, and then use EXEC () or process file input to restore the data, in fact it is very unsafe, If you use text to store some important data, any change in any way can affect your program, light program crashes, and heavy is exploited by malicious programs, so let's use Pickle instead:
Copy Code code as follows:
Import Pickle
data = {' foo ': [1, 2, 3],
' Bar ': (' Hello ', ' world! '),
' Baz ': True}
jar = open (' Data.pkl ', ' WB ')
Pickle.dump (data, jar) # write the pickled data to the file jar
Jar.close ()
Well, after a few hours, we need to use it, just unpickle it:
Copy Code code as follows:
Import Pickle
Pkl_file = open (' data.pkl ', ' RB ') # Connect to the pickled data
data = Pickle.load (pkl_file) # load it into a variable
Print data
Pkl_file.close ()
As you would expect, the data is back intact!
At the same time to give you a piece of advice: pickle is not perfect, pickle files can easily be inadvertently or intentionally damaged, pickle files than plain text files to a little more secure, but it could be exploited to run a malicious program. Pickle is not a cross version compatible (in the recent discussion in Python Cookbook, the Pickle described in the book is a cross version compatibility, which is to be validated), so try not to distribute Pickle text because someone else is not necessarily able to open it. But when it comes to caching or other data that needs to be serialized, Pickle is useful.
Serializing your own object.
Pickle does not support only built-in data results, any class that follows the Pickle protocol, the Pickle protocol provides 4 optional methods for Python objects to customize the Pickle behavior (there are some differences for the C-extended cpickle module, but this is not the case in our discussion fan Wai):
Copy Code code as follows:
If you want to call __init__ at the same time as deserialization, you can define the __getinitargs__ method, which should return a series of arguments that you want to be called __init__, and note that this method works only for old-style classes.
Copy Code code as follows:
For a new class, you can define any parameters that are passed to the __new__ method when the object is rebuilt. This method should also return a series of arguments that are called by __new__.
Copy Code code as follows:
Instead of using the __dict method, you can customize the state returned when the object is serialized, and the returned state will be called by the __setstate__ method when the object is deserialized.
Copy Code code as follows:
__SETSTATE__ (self, State)
When an object is deserialized, if __setstate__ is defined, the state of the object is passed to it rather than passed to __dict__. This method is paired with __getstate__, and when both methods are defined, you can fully control the entire serialization and deserialization process.
Example
Let's take Slate, which is a record of a value and when the value was written, but this Slate is a little bit special where the current value is not saved.
Copy Code code as follows:
Import time
Class Slate:
"' Class to store a string and a changelog, and forget their value when
Pickled. '
def __init__ (self, value):
Self.value = value
Self.last_change = Time.asctime ()
Self.history = {}
def change (self, new_value):
# Change the value. Commit last value to history
Self.history[self.last_change] = Self.value
Self.value = New_value
Self.last_change = Time.asctime ()
def print_changes (self):
print ' Changelog for Slate object: '
For K, v. in Self.history.items ():
print '%s\t%s '% (k, v)
def __getstate__ (self):
# deliberately don't return Self.value or Self.last_change.
# We want to have a ' blank slate ' when We unpickle.
Return self.history
def __setstate__ (self, State):
# Make self.history = state and Last_change and value undefined
Self.history = State
Self.value, Self.last_change = none, none
Conclusion
The hope of this guide will bring some knowledge to everyone, even if you are a Python or a master of object-oriented development. If you're a Python beginner, after reading this article you've got the basics of writing a rich, elegant, flexible class. If you're a Python programmer with some experience, you might find ways to make your code more concise. If you are a Python Daniel, you may be able to help you think about some of the things you've forgotten, or new features you haven't heard of. No matter how much experience you have now, I hope this trip to the Python special method will give you some help (it's really nice to use a pun. XD) (the pun here is titled Magic Methods here is a magical journey, but because of the Chinese-English word order, the literal translation is slightly top-heavy, So a little change of meaning, lost the meaning of pun).
Appendix: How to Invoke the Magic method
Some of the magic methods are directly relative to the built-in functions, in which case the method of invoking them is simple, but if it is another not particularly obvious invocation method, this appendix describes many of the calling forms that are not obvious magic methods.
Hopefully this form will help you with the question of when and how you should use it.