Python Sequence Modification, hash, and Slicing,

Source: Internet
Author: User
Tags hypot

Python Sequence Modification, hash, and Slicing,

Vector: User-defined sequence type

We will use the combination mode to implement the Vector class without using inheritance. The vector component is stored in the floating-point array, and the method required to implement an immutable flat sequence is also implemented.

The Vector version 1st should be compatible with the Vector2d class defined in the previous chapter.

 

Vector version 1st: compatible with Vector2d 

The Vector version 1st should be compatible with the Vector2d class defined in the previous chapter. However, we will intentionally prevent the Vector constructor from being compatible with the Vector2d constructor. To compile code such as Vector (3, 4) and Vector (3, 4, 5), we can make the _ init _ method accept any parameter (through * args ); however, the construction method of the sequence type is best to accept the iteratable object as the parameter, because all the built-in sequence types do this.

Test the methods of Vector. _ init _ and Vector. _ repr _.

>>> Vector([3.1, 4.2])Vector([3.1, 4.2])>>> Vector((3, 4, 5))Vector([3.0, 4.0, 5.0])>>> Vector(range(10))Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])

Vector_v1.py: Derived from vector2d_v1.py

1 from array import array 2 import reprlib 3 import math 4 5 6 class Vector: 7 typecode = 'D' 8 9 def _ init _ (self, components): 10 self. _ components = array (self. typecode, components) # self. _ components is the "protected" instance attribute. It stores the Vector component in an array 11 12 def _ iter _ (self): 13 return iter (self. _ components) # For iteration, we use self. _ components build an iterator 14 15 def _ repr _ (self): 16 components = reprlib. repr (self. _ components) # Use reprlib. the repr () function obtains self. _ components Finite Length representation (such as array ('D', [0.0, 1.0, 2.0, 3.0, 4.0,...]) 17 components = components [components. find ('['):-1] # Remove the previous array ('D' and later) before inserting the string into the construction method of the Vector) 18 return 'vecotr ({})'. format (components) # directly use self. _ components build bytes Object 19 20 def _ str _ (self): 21 return str (tuple (self) 22 23 def _ bytes _ (self ): 24 return (bytes ([ord (self. typecode)]) + 25 bytes (self. _ components) 26 27 def _ eq _ (self, other): 28 return tuple (self) = tuple (other) 29 30 def _ abs _ (self): 31 return math. hypot (sum (x * x for x in self) # You cannot use the hypot method. Therefore, we first calculate the sum of the squares of each component, then use the sqrt method to open square 32 33 def _ bool _ (self): 34 return bool (abs (self) 35 36 @ classmethod37 def frombytes (cls, octets ): 38 typedcode = chr (octets [0]) 39 memv = memoryview (octets [1:]). cast (typedcode) 40 return cls (memv) # we only need. modify the last line based on the frombytes method: Pass the memoryview directly to the constructor, and do not use the * package as before.

 

Protocol and duck type

To create a fully functional sequence type in Python, you only need to implement methods that comply with the sequence protocol. But what is the protocol here?

In object-oriented programming, protocols are informal interfaces that are defined only in the document and not in the code. For example, the sequence protocol of Python only requires two methods: _ len _ and _ getitem. Any class (such as Spam), as long as the two methods are implemented using the standard signature and semantics, can be used in any desired sequence. It doesn't matter whether Spam is a subclass of a class. You only need to provide the required method.

 1 class FrenchDeck: 2     ranks = [str(n) for n in range(2, 11)] + list('JQKA') 3     suits = 'spades diamonds clubs hearts'.split() 4  5     def __init__(self): 6         self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks] 7  8     def __len__(self): 9         return len(self._cards)10 11     def __getitem__(self, position):12         return self._cards[position]

The Protocol is informal and has no force. Therefore, if you know the specific application scenario of the class, you usually only need to implement the part of a protocol. For example, to support iteration, you only need to implement the _ getitem _ method, and the _ len _ method is not required.

 

Vector version 2nd: Slice Sequence

As shown in the FrenchDeck class, if sequence attributes (such as the self. _ components array) can be delegated to an object, the sequence protocol is particularly simple. Only the _ len _ and _ getitem _ methods of one line of code below are a good start:

Class Vector: # omitting many rows #... def _ len _ (self): return len (self. _ components) def _ getitem _ (self, index): return self. _ components [index]

After adding these two methods, you can perform the following operations:

>>> v1 = Vector([3, 4, 5])>>> len(v1)3 >>> v1[0], v1[-1](3.0, 5.0)>>> v7 = Vector(range(7))>>> v7[1:4]array('d', [1.0, 2.0, 3.0])

We can see that slice is supported now, but it is not perfect. If the slice of the Vector instance is also a Vector instance, rather than an array, it would be better. The preceding FrenchDeck class has a similar problem: the slice produces a list. For Vector, if slices generate common arrays, a large number of functions are missing.

To convert the slice of a Vector instance into a Vector instance, we cannot simply delegate the slice to an array. We need to analyze the parameters passed to the _ getitem _ Method for proper processing.

 Slice Principle

Learn about _ getitem _ and slice Behavior

>>> Class MySeq :... def _ getitem _ (self, index ):... return index... >>> s = MySeq () >>> s [1] #__ getitem _ directly return the value passed to it 1 >>> s [] # [] indicates that it is changed to slice (1, 4, None) slice (1, 4, None) >>> s [] # [] means starting from 1st indexes and ending with 4th indexes, the step size is 2 slice (1, 4, 2) >>> s [, 9] (slice (1, 4, 2), 9) # The magic happened .. wtf... if [] contains commas, _ getitem _ receives the ancestor >>> s [,] # The ancestor can also contain multiple slice objects (slice (1, 4, 2), slice (7, 9, None ))

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.