Python Magic Method-Custom sequence

Source: Internet
Author: User

The associated magic method of a custom sequence allows us to create a class that has the characteristics of a sequence that is used like a python built-in sequence (dict,tuple,list,string, etc.).

If you want to implement this function, you should follow the relevant Python protocol. The so-called agreement is a few agreed content. For example, if you want to implement an iteration of a class, you must implement two magical methods: __iter__, Next (__new__ in python3.x). __ITER__ should return an object that must implement the next method, usually returning the self itself. The next method must return the next element each time it is called, and the stopiteration exception is triggered when the element is exhausted.

In fact, the essence of the For loop is to call the __iter__ method of the object first, and then repeatedly call the next method of the object returned by the __iter__ method, stop when the stopiteration exception is triggered, and handle the exception internally, so we don't see the exception thrown.

This relationship is like an interface, and if you look back at some of the previous magic methods, you can see that many of the built-in functions get the result of the corresponding Magic method's return value.

Here's a little bit about the Magic method:

  • __len__ (self)

  • Returns the length of the container. Both mutable and immutable containers have to implement it, which is part of the protocol.

  • __getitem__ (self, key)

  • Defines the behavior that occurs when an item is accessed using Self[key]. This is also part of the variable container and immutable 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)

  • Defines the behavior that occurs when an entry is assigned, using self[key] = value. This is also part of the variable container protocol . Moreover, Keyerror and TypeError can also be produced in the corresponding situation.

  • __delitem__ (self, key)

  • Defines the behavior that occurs when an item is deleted. (e.g. del Self[key]). This is part of the mutable container protocol. When you use an invalid key, you must throw the appropriate exception.

  • __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 the __iter__ method that returns self.

  • __reversed__ (self)

  • Implements the behavior when reversed () is called. The inverted version of the sequence should be returned . Implement it only when the sequence is ordered, such as a list or tuple.

  • __contains__ (self, item)

  • Defines the behavior that occurs when both in and not are called to test the presence of a member. This is not what the protocol requires, but you can implement it according to your own requirements. When __contains__ is not defined, Python iterates over the sequence and returns True when the desired value is found.

  • __missing__ (self, key)

  • It is used in Dict subclasses . It defines the behavior that occurs when a key in a nonexistent dictionary is accessed. (For example, if I have a dictionary d, when "George" is not a key in the dictionary, d["George" is used), then d.__missing__ ("George") will be called.

Here is a code example:

classFoo (object):def __init__(self, Key, value): Self.key=[] Self.value=[] self.key.append (key) Self.value.append (value)def __len__(self):returnLen (self.key)def __getitem__(self, item):Try:            __index=Self.key.index (item)returnself.value[__index]        exceptValueError:RaiseKeyerror ('can not find the key')    def __setitem__(self, Key, value):ifKey not inchself.key:self.key.append (Key) Self.value.append (value)Else:            __index=Self.key.index (key) self.value[__index] =valuedef __delitem__(self, key):Try:            __index=Self.key.index (Key)delself.key[__index]            delself.value[__index]        exceptValueError:RaiseKeyerror ('can not find the key')    def __str__(self): result_list= []         forIndexinchxrange (len (Self.key)):__key=Self.key[index]__value=Self.value[index] Result=__key,__valueresult_list.append (Result)returnStr (result_list)def __iter__(self): self.__index=0return SelfdefNext (self):ifSelf.__index==Len (self.key): Self.__index=0Raisestopiteration ()Else:            __key= Self.key[self.__index]            __value= Self.value[self.__index] Result=__key,__valueSelf .__index+ = 1returnresultdef __reversed__(self):__result=self.value[:]__result. Reverse ()return __result    def __contains__(self, item):ifIteminchSelf.value:returnTrueElse:            returnFalse

This creates a class that simulates the dictionary, which maintains two lists within the class, the key is responsible for storing the keys, the value is responsible for storing the values, and the two lists correspond to the one by one of the index to achieve the purpose of the mock dictionary.

First, let's look at the __len__ method, according to the protocol, this method should return the length of the container, because this class is designed to require two lists must be equal, so theoretically return which list is the same length, here I choose to return the length of the key.

Then the __getitem__ method. This method calls a.__getitem__ (' Scolia ') when a[' Scolia ']. This means that the method defines the acquisition of the element, and my idea here is to find the index in the key list, then use the index to find the corresponding element in the value list, and then return it. Then, in order to disguise it as a dictionary, I capture the possible valueerror (which is the exception that is triggered when item is not in the key list) and disguise it as keyerror when the dictionary cannot find the key.

Theoretically, as long as the above two methods are implemented, an immutable container can be obtained. But I didn't feel satisfied so I continued to expand.

The __setitem__ (self, Key, value) method defines the behavior of a[' scolia '] = ' good ', at which time a.__setitem__ (' Scolia ', ' good ') is invoked because it is a binding method, So self is automatically passed, and we don't have to. Here I also simulate the characteristics of the dictionary that will cause overrides when assigning the same key. This method does not return any values, so the return statement is omitted.

The __delitem__ (self, Key) method defines the behavior of the operation of Del a[' Scolia ', where the ' Scolia ' is passed in as a parameter. An unusual conversion is also done here.

Only four of the above methods can be used as variable containers. Some students may find that there is no magic method for slicing, and in fact, I have not found the first, this part of the content first aside.

The next __str__ is corresponding to the STR () function, which will continue to be discussed in the class representation, which is added in order for the print statement to look good, because the print statement defaults to calling the STR () function.

The __iter__ and next methods are discussed at the beginning, and are added to allow iterative operations.

The __reversed__ (self) method returns a reverse-reversed copy, which manifests the order and, of course, whether or not you need to see the individual.

__CONTAINS__ implements the member judgment, where we are more concerned with the data in the value list, so we are judging the value list. This method requires that a Boolean value be returned.

Here are the corresponding tests:

A = Foo ('Scolia','Good') a[123] = 321a[456] = 654a[789] = 987Printadela[789]Printa forX, yinchA:Printx, yPrintreversed (a)Print123inchaPrint321inchA

    • __missing__ (self, key)

class Boo (dict):     def __new__ (CLS, *args, * *Kwargs)        : return Super (Boo, CLS). __new__ (CLS)     def __missing__ (self, key):         return ' The key (%s) can not be find. '% key

Test:

b = Boo () b['scolia'good'print b['  scolia']print b['123']

Of course, you can not find the key to trigger the exception, the specific implementation to see individual needs.

You are welcome to exchange.

Reference: Poke here

Python Magic Method-Custom sequence

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.