参考资料:《Python3编程指南》第六章
组合类型的特殊方法
| 特殊方法 | 使用 | 描述 |
|---|---|---|
| getitem(self,key) | y[k] | 返回序列y中的第key项或者映射类型y中k为键的值 |
| delitem(self,key) | del y[k] | 删除序列y中的第key项或者映射类型y中k为键的值 |
| iter(self) | for x in y:pass | 返回序列y或者映射类型y得迭代子 |
| len(self) | len(y) | 返回序列y的字符数或者映射类型y的个数 |
| reversed(self) | reversed(y) | 返回序列y中的第key项或者映射类型y的反向迭代子 |
| setitem(self,key,v) | y[k] = v | 将序列中的第k项设置为v或者将映射类型y中k的值设置为v |
| contains(self,x) | x in y | 如果x在序列y中或者x为映射类型y的键,则返回True |
SortedList实现
利用list和上述特殊方法,自定义一个可排序的list,代码如下:
_identify = lambda x: x
class SortedList:
def __init__(self,sequence=None,key=None):
"""初始化SortedList(参考list的创建方式)
:param sequence:
:param key:
"""
# key用于指定排序规则,如果没有指定,则通过Lambda函数指定自身作为排序规则
self.__key = key or _identify
# 如果key是可调用对象(函数和方法),则返回True
assert hasattr(self.__key, "__call__")
# SortList()形式
if sequence is None:
self.__list = []
# SortList(SortList)形式
elif (isinstance(sequence, SortedList) and
sequence.key == self.__key):
self.__list = sequence.__list[:]
# SortList(tuple)形式
else:
self.__list = sorted(list(sequence), key=self.__key)
@property
def key(self):
"""将传入的key函数作为私有属性,提供只读权限
"""
return self.__key
def add(self, value):
"""添加元素
:param value:
"""
# 获取插入值的索引
index = self.__bisect_left(value)
print("----index:",index)
if index == len(self.__list):
self.__list.append(value)
else:
self.__list.insert(index, value)
def __bisect_left(self, value):
"""使用二分法
"""
# 如果没指定key,则调用_identify(value),如果指定,则调用对应key的方法,相当于回调
key = self.__key(value)
left, right = 0, len(self.__list)
while left < right:
middle = (left+right) // 2
if self.__key(self.__list[middle]) < key:
left = middle+1
else:
right = middle
return left
def remove(self, value):
index = self.__bisect_left(value)
if index < len(self.__list) and self.__list[index] == value:
del self.__list[index]
else:
raise ValueError("{0}.remove(x):x not in list".format(self.__class__.__name__))
def count(self, value):
count = 0
index = self.__bisect_left(value)
while(index < len(self.__list) and
self.__list[index] == value):
index += 1
count += 1
return count
def index(self, value):
index = self.__bisect_left(value)
if index < len(self.__list) and self.__list[index] == value:
return index
else:
raise ValueError("{0}.index(x):x not in list.".format(self.__class__.__name__))
# 支持del L[xx]
def __delitem__(self, key):
del self.__list[key]
# 支持 x = L[k]
def __getitem__(self, index):
return self.__list[index]
def __iter__(self):
return iter(self.__list)
def __reversed__(self):
return reversed(self.__list)
def __contains__(self, value):
index = self.__bisect_left(value)
return index < len(self.__list) and self.__list[index] == value
def pop(self, index=-1):
return self.__list.pop(index)
def clear(self):
self.__list.clear()
def __len__(self):
return len(self.__list)
def __str__(self):
return str(self.__list)
def copy(self):
return SortedList(self, self.key)
if __name__ == "__main__":
s = SortedList(("J","S","N","L","I","P")) # ['I', 'J', 'L', 'N', 'P', 'S']
s1 = SortedList(s)
s1.add("M")
def key(value): # 指定一个key
return value
s3 = SortedList(s1, key)
print(s1) # ['I', 'J', 'L', 'M', 'N', 'P', 'S']
关键点和难点
- 要支持排序,通过sorted()方法实现,同时,必须提供一个key,但这里,如果不提供key值,则默认使用自身为排序规则。
- add()方法结合了list的append()和insert()方法,实现了插入到特定的位置,保持了顺序。
- 判断索引位置时,使用的方法
__bisect_left()使用二分法实现。 - 在
__init__()方法中使用了hasattr(obj,"__call__")进行判断:如果作为第一个参数的对象包含一个属性,这个属性和第二个参数相同,那么就返回True,所有可调用对象(函数和方法)都包含一个__call__属性.因此,如果传入一个函数对象,则ok,如果传入的不是一个函数对象,则不ok。
本文介绍了如何利用Python的特殊方法创建一个自定义的可排序SortedList。SortedList结合了list的功能并支持排序,通过sorted()方法和key参数实现。add()方法采用二分法确保元素按顺序插入。此外,文章探讨了如何判断对象是否包含特定属性以确定其可调用性。

1061

被折叠的 条评论
为什么被折叠?



