Python扩展内置类型的两种核心技术:嵌入与子类化
本文详解Python中扩展内置类型的两种主要技术:通过嵌入扩展类型和通过子类扩展类型。文章展示了如何利用嵌入方式包装列表并实现集合运算与运算符重载,以及自Python 2.2起如何通过子类化定制内置类型行为(如索引偏移)。通过具体代码示例,解析了Set类与MyList类的实现原理及运行结果,帮助开发者深入理解Python对象模型与类型扩展机制。
除了创建全新的对象类型外,类机制还具备扩展Python内置类型的功能。实现这一目标主要依赖以下两种技术手段:
通过嵌入方式扩展类型
以下示例演示了如何将部分集合操作封装为方法,并新增基本运算符的重载,从而构建出一个新的集合对象。对于大多数此类类而言,其核心逻辑是包装Python的列表对象,并在此基础上附加集合运算功能。
#File setwrapper.py
class Set:
def __init__(self,value=[]):#构造函数
self.data = []
self.concat(value)
def intersect(self,other):#求交集
res = []
for x in self.data:
if x in other:
res.append(x)
return Set(res) #返回一个新的Set
def union(self,other):#求并集
res = self.data[:] #复制self.data
for x in other:
if not x in res:
res.append(x)
return Set(res)
def concat(self,value):
for x in value:
if not x in self.data:
self.data.append(x)
def __len__(self): # len(self)
return len(self.data)
def __getitem__(self,key): # self[i]
return self.data[key]
def __and__(self,other): # self & other
return self.intersect(other)
def __or__(self,other): # self | other
return self.union(other)
def __repr__(self): # print
return 'Set:' + repr(self.data)
if __name__ == '__main__': #测试用例
x = Set([1,3,5,7])
print(x.union(Set([1,4,7])))
print(x | Set([1,4,6]))
print(x[2])
print(x[2:4])
通过重载索引运算,Set类的实例能够像真正的列表一样被访问。程序的运行结果如下所示:
>>> Set:[1, 3, 5, 7, 4] Set:[1, 3, 5, 7, 4, 6] 5 [5, 7]
通过子类化方式扩展类型
从Python 2.2版本开始,所有的内置类型均允许直接创建其子类。 这种机制允许用户通过自定义class语句来定制或扩展内置类型的行为:即建立该类型名称的子类并对其进行个性化定制。子类化的实例可以在任何原始内置类型适用的场景中使用。 例如,如果你一直对Python列表索引从0开始计算而非1感到困扰,你可以编写自己的子类来定制列表的核心行为,具体实现如下:
# File typesubclass.py
#Map 1..N to 0..N-1; call back to built-in version
class MyList(list):
def __getitem__(self,offset):
print('(indexing %s at %s)'%(self,offset))
return list.__getitem__(self,offset-1)
if __name__ == '__main__':
print(list('abc'))
x = MyList('abc')
print(x)
print(x[1])
print(x[3])
x.append('spam')
print(x)
x.reverse()
print(x)
在该文件中,MyList子类扩展了内置list类型的__getitem__索引运算方法,将索引1到N映射到实际的0到N-1。程序的运行结果如下:
>>> ['a', 'b', 'c'] ['a', 'b', 'c'] (indexing ['a', 'b', 'c'] at 1) a (indexing ['a', 'b', 'c'] at 3) c ['a', 'b', 'c', 'spam'] ['spam', 'c', 'b', 'a']
关于另一个类型子类的示例,可以参考bool类型的实现。可以看到bool类是int类的子类,拥有两个实例(True和False),其行为类似于整数1和0,但继承了定制后的字符串表达方式,从而显示变量名而非数值。
以上内容构成了本文的全部讲解,希望能为读者的学习提供有益帮助,同时也欢迎大家继续支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













