重定义Python内置数据类型

3 投票
4 回答
2167 浏览
提问于 2025-04-16 18:51

可以重新定义方括号 [] 使用哪个对象吗?

我可以创建一个列表的子类,但我该如何让解释器使用我的子类,而不是内置的列表对象呢?这可能吗?

(我觉得我用的术语可能不太对,欢迎修改)

>>> class mlist(list):
...     def __init__(self):
...         list.__init__(self)
...     def __getitem__(self, item):
...         return list.__getitem__(self, item) * 2
... 
>>> testlist = mlist()
>>> testlist.append(21)
>>> testlist[0]
42
>>> list = mlist() # maybe setting the 'list' type will do it?
>>> testlist = []
>>> testlist.append(21)
>>> testlist[0]
21                 # Nope
>>> 

我并没有实际的用途,只是好奇而已。

4 个回答

0

你可以用 not 来把 list 替换成 mlist,就像你尝试的那样,

list = mlist()

但其实只需要

list = mlist

(你在解释器中运行这个可能会遇到问题,因为 mlist() 会递归地调用 list() 等等。不过,如果你把定义 mlist 的代码放在一个不同的范围,比如在你导入的模块里,那就没问题了。)然后你可以通过

testlist = list()

来创建一个新的 mlist,

testlist = []

但有趣的是,不能通过

我原以为这两者在语法上是等价的。显然,方括号 [ ] 是硬编码的,用来调用内置的 list 类型,而不是当前名为 "list" 的任何对象。

7

这些括号是编程语言的一部分。它们用来创建列表。我们不能重新定义它们的用法(而且也没有必要这样做!)。

2

试着在你运行了你发的代码之后再运行这段代码

>>> testlist = list()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'mlist' object is not callable

现在,使用我发的代码来确定类型

>>> type([])
<type 'list'>
>>> type(list)
<class '__main__.mlist'>
>>> type(testlist)
<type 'list'>

看起来 [] 创建的是 list,而不是 mlist,这看起来有点奇怪 :S

更新

我用 dis 检查了生成的字节码,下面的代码被生成了

>>> import dis # python's disassembler

>>> def code1():
...     return []
...
>>> dis.dis(code1)
  2           0 BUILD_LIST               0
              3 RETURN_VALUE

>>> def code2():
...     return list()
...
>>> dis.dis(code2)
  2           0 LOAD_GLOBAL              0 (list)
              3 CALL_FUNCTION            0
              6 RETURN_VALUE

看起来 list 会调用分配给它的任何东西,而 [] 会被转换成 BUILD_LIST 字节码。似乎 [] 并不是被翻译成 list,因此 [] 的行为就是创建列表。

更新 2

Python 类是可以更新的

>>> class NewList(list):
...     pass
...
>>> a = NewList()
>>> a.append(23)
>>> a[0]
23
>>> def double_getitem(self, key):
...     return list.__getitem__(self, key) * 2
...
>>> NewList.__getitem__ = double_getitem
>>> a[0]
46

不过,内置类,比如 list,除外

>>> list.__getitem__ = double_getitem
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'list'

撰写回答