子类化list时super()是什么?如何直接访问底层列表?
问题与代码示例
class Foo(list): def bar(self): return super().__getitem__(slice(None)) def baz(self): return super() a = Foo([0, 1, 2, 3]) print(a.bar()) # [0, 1, 2, 3] print(a.baz()) # <super: <class 'Foo'>, <Foo object>> # a.bar() provides a copy of the underlying list as can be seen from the fact that each result of a.bar() has a different id print(id(a.bar())) # id1 print(id(a.bar())) # id2 != id1
我近期遇到一个开发场景,需要子类化list,并在子类Foo内部访问底层列表。我原本以为super()可以直接提供底层列表,但实际并非如此。目前只能通过super().__getitem__(slice(None))获取到底层列表的副本。请问如何直接访问底层列表?我对super()的理解存在哪些误区?
解答
一、如何直接访问底层列表
你不需要刻意“访问底层列表”——你的Foo实例本身就是list的子类实例,它继承了list的所有状态与特性,直接操作self就是操作原列表:
- 如果要获取原列表的引用,直接
return self即可,得到的是原列表对象而非副本:class Foo(list): def get_original_list(self): return self a = Foo([0,1,2,3]) print(id(a.get_original_list())) # 和id(a)完全相同 - 如果要修改原列表,直接调用
self的方法(比如self.append(4)、self.pop())即可,所有操作都会直接作用在原列表上。
CPython中list的底层存储是内部缓冲区,但Python语言层面没有直接暴露这个缓冲区的接口——因为设计上子类实例本身就继承了父类的所有状态,直接使用self就是最直接合理的方式。
二、对super()的理解误区
super()不是父类实例:super()返回的是一个代理对象,它的作用是帮你在子类中调用父类的方法,而非返回父类的实例。你看到的<super: <class 'Foo'>, <Foo object>>就是这个代理对象的标识,它本身不是列表。- 返回副本是
list的固有行为:list的__getitem__方法在传入slice(None)(即[:])时,本身就会返回列表的浅拷贝,这是list类的特性,和super()无关——哪怕直接调用self[:],得到的也是副本。 - 无需通过
super()获取父类状态:子类实例本身就继承了父类的所有属性和状态,直接使用self就能访问父类的功能,不需要通过super()去“获取底层列表”。super()的核心场景是在子类重写父类方法时,调用父类的原有实现逻辑。
内容的提问来源于stack exchange,提问作者joseville
相关产品推荐
相关产品推荐

