重新定义Pythons内置数据类型

时间:2011-06-02 16:29:29

标签: python list object subclass built-in-types

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

我可以继承list对象,但是如何让解释器使用我的子类代替buildin列表对象?可能吗?

(我很确定我使用的是错误的条款 - 随意编辑)

>>> 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 :(得分:7)

括号是该语言的一部分。它们用于创建列表。重新定义它是不可能的(也不可取!)。

答案 1 :(得分: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'

答案 2 :(得分:0)

您可以尝试使用不使用ml替换列表

list = mlist()

但只是

list = mlist

(您可能在解释器中运行此问题,因为mlist()以递归方式调用list()等等。但是如果您将定义mlist的代码放在不同的范围内,例如在您导入的模块中,那么它会工作。)然后你可以通过

创建一个新的mlist
testlist = list()

但有趣的是,不是

testlist = []
我认为它在语法上是等价的。显然[]被硬编码来调用内置列表类型,而不是当前任何对象被命名为“list”。

答案 3 :(得分:0)

这是可能的。如果你愿意变得足够脏,那么大多数事情都可能在软件中出现。 :)当然,这是一个坏主意。如果您使用此类更改编写任何软件,则会出现许多问题:

  • 您的代码很容易混淆读者。他们认为他们正在阅读Python,因此他们认为他们知道[]的意思,但是他们不知道。但是他们不知道。
  • 如果更改的范围是全局的(而不是仅限于,例如,单个源文件),那么您将难以将您的软件与其他任何人合并,因为您实际上是用两种不同的语言编写的。如果[]开始返回不同的类型,其他软件可能会中断,即使它是子类。
  • 如果更改的范围有限,那么当您查看具有不同语法规则的不同源文件时,您可能很容易混淆自己。如果您拥有由不同模块操作的数据,您可能会发现自己处于一种情况,即您的代码想要将数据放入mlist中,而其他一些代码则希望将其放在列表中,然后您可能会感到难过。

这是2003年a CPython extension moduleand example),与Python 2.3一起使用。它很可能需要更新才能与更新版本的Python一起使用,但它展示了您需要为这种特定方法获取多少脏东西。

另一种方法是在语法层面改变事物。 Logix为此方法提供了工具。这涉及较少的C黑客攻击,但引入了一个全新的解析器和编译器。