程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Advanced Python: implementing slicing with custom objects

編輯:Python

The slice is Python The most charming, the most powerful, the most Amazing Language characteristics of ( There is hardly one ), stay 《Python Advanced : The misunderstanding and advanced usage of slicing 》 in , I introduced the basic usage of slicing 、 Advanced usage and some mistakes . These are all based on native sequence types ( Such as a string 、 list 、 Tuples ……), that , Can we define our own sequence type and make it support slicing syntax ? Further more , Can we customize other objects ( Such as a dictionary ) And let it support slicing ?

1、 Magic methods :__getitem__()
It's not hard to make custom objects support slicing Syntax , You just need to implement magic methods when you define a class __getitem__() that will do . therefore , Let's introduce this method first .

grammar :object.__getitem__(self, key)

Interpretation of official documents :Called to implement evaluation of self[key]. For sequence types, the accepted keys should be integers and slice objects. Note that the special interpretation of negative indexes (if the class wishes to emulate a sequence type) is up to the __getitem__() method. If key is of an inappropriate type, TypeError may be raised; if of a value outside the set of indexes for the sequence (after any special interpretation of negative values), IndexError should be raised. For mapping types, if key is missing (not in the container), KeyError should be raised.

To sum up, translate :__getitem__() Method is used to return parameters key The corresponding value , This key It can be integer values and slice objects , And support negative index ; If key Not the above two types , Will throw TypeError; If the index is out of bounds , Flip a IndexError ; If you define a mapping type , When key When the parameter is not the key value of its object , You'll throw it KeyError .

2、 Custom sequence realizes slicing function
Next , We define a simple MyList , And add slicing to it .(PS: Just for demonstration , The completeness of other functions is not guaranteed ).

class MyList():
def __init__(self):
self.data = []
def append(self, item):
self.data.append(item)
def __getitem__(self, key):
print("key is : " + str(key))
return self.data[key]
l = MyList()
l.append("My")
l.append("name")
l.append("is")
l.append("Python Programming learning circle ")
print(l[3])
print(l[:2])
print(l['hi'])
### Output results :
key is : 3
Python Programming learning circle
key is : slice(None, 2, None)
['My', 'name']
key is : hi
Traceback (most recent call last):
...
TypeError: list indices must be integers or slices, not str
 Copy code 

Look at the output , Self defined MyList It supports searching by index , Slicing is also supported , That's what we're trying to do .

In particular , In this case __getitem__() Methods implement different functions according to different parameter types ( Take index bit value or slice value ), And handle exceptions properly , So we don't need to write complicated processing logic any more . There are a lot of learning materials on the Internet, which are completely misleading , They will teach you to distinguish between different types of parameters , Then write a large piece of code to implement index lookup and slicing Syntax , It's just like painting a snake and adding feet to it . Here's a typical example of an error :

### Leave out the rest of the code ####
def __getitem__(self, index):
cls = type(self)
if isinstance(index, slice): # If index It's a slice type , Then construct a new instance
return cls(self._components[index])
elif isinstance(index, numbers.Integral): # If index It's a number , Then return directly
return self._components[index]
else:
msg = "{cls.__name__} indices must be integers"
raise TypeError(msg.format(cls=cls))
 Copy code 

3、 Custom dictionary to realize slicing function
Slicing is a feature of sequence types , So in the example above , We don't need to write specific implementation logic for slicing . however , For other non sequence type custom objects , You have to implement slicing logic yourself . Take a custom dictionary for example (PS: Just for demonstration , The completeness of other functions is not guaranteed ):

class MyDict():
def __init__(self):
self.data = {}
def __len__(self):
return len(self.data)
def append(self, item):
self.data[len(self)] = item
def __getitem__(self, key):
if isinstance(key, int):
return self.data[key]
if isinstance(key, slice):
slicedkeys = list(self.data.keys())[key]
return {k: self.data[k] for k in slicedkeys}
else:
raise TypeError
d = MyDict()
d.append("My")
d.append("name")
d.append("is")
d.append("Python Programming learning circle ")
print(d[2])
print(d[:2])
print(d[-4:-2])
print(d['hi'])
### Output results :
is
{0: 'My', 1: 'name'}
{0: 'My', 1: 'name'}
Traceback (most recent call last):
...
TypeError
 Copy code 

The key point of the above example is to take out the key value of the dictionary , And do a list of sliced keys , The beauty is that , Don't worry about index overruns and negative indexes , Convert dictionary slice to dictionary key value slice , Finally achieve the goal .

4、 Summary
This paper introduces __getitem__() Magic methods , And used to implement custom objects ( Take list type and dictionary type for example ) Section function , I hope it helped you .

The above is all the content shared this time , Want to know more python Welcome to official account :Python Programming learning circle , send out “J” Free access to , Daily dry goods sharing


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved