重新定义 Python 内置数据类型

发布于 2024-11-13 14:07:46 字数 664 浏览 8 评论 0原文

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

我可以对 list 对象进行子类化,但是如何让解释器使用我的子类来代替内置列表对象?是否可以?

(我很确定我在这个问题上使用了错误的术语 - 请随意编辑)

>>> 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
>>> 

我对此没有实际用途 - 只是好奇。

Is it possible to redefine which object the brackets [] use?

I can subclass the list object, but how to I make the interpreter use my subclass in place of the buildin list object? Is it possible?

(I'm pretty sure I'm using the wrong terms for the question- feel free to edit)

>>> 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
>>> 

I don't have a practical use for this- just curious.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

染墨丶若流云 2024-11-20 14:07:46

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

The brackets are part of the language. They're used to create lists. It's not possible to redefine that (and not desirable either!).

何处潇湘 2024-11-20 14:07:46

运行您发布的代码后尝试运行代码

>>> 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,而不是 < code>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< /code> 将调用分配给它的任何内容,而 [] 将转换为 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'

Try running the code after you've run the code you posted

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

Now, determine the type using the code I've posted

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

it seems that [] creates list, instead of mlist, it looks strange :S

Update

I checked the bytecode generated using dis, and the code below was generated

>>> 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

It appears that list will invoke whatever is assigned to it, while [] will be converted to BUILD_LIST bytecode. It appears that [] is not translated to list, hence []'s behavior is stucked to creating list.

Update 2

Python class can be updated

>>> 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

Well, except for builtin classes, like 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'
jJeQQOZ5 2024-11-20 14:07:46

您可以使用 not 来替换 list 为 mlist ,正如您所尝试的那样,

list = mlist()

而是简单地

list = mlist

使用(您在解释器中运行它可能会遇到问题,因为 mlist() 递归地调用 list() 等。但是如果您将定义 mlist 的代码放在一个不同的范围,例如在您导入的模块中,那么它将起作用。)然后您可以创建一个新的 mlist,

testlist = list()

但有趣的是,

testlist = []

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

You can replace list with mlist by using not, as you tried,

list = mlist()

but simply

list = mlist

(You might have problems running this in the interpreter, because mlist() calls list() and so on recursively. But if you put the code that defines mlist in a different scope, such as in a module you import, then it will work.) Then you can create a new mlist by

testlist = list()

but interestingly, not by

testlist = []

which I had thought was syntactically equivalent. Apparently [ ] is hardcoded to call the built-in list type, rather than whatever object is currently named "list".

静若繁花 2024-11-20 14:07:46

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

  • 读者很容易被您的代码迷惑。他们认为自己正在阅读 Python,所以他们认为自己知道 [] 的含义,但糟糕的是,他们不知道。
  • 如果更改的范围是全局的(而不是仅限于单个源文件),那么您将很难将您的软件与其他人的软件结合起来,因为您实际上是用两种不同的语言编写的。如果 [] 开始返回不同的类型,即使它是子类,其他软件也可能会崩溃。
  • 如果更改的范围有限,那么当您查看具有不同语法规则的不同源文件时,您可能很容易感到困惑。如果您有由不同模块操作的数据,您可能会发现自己处于这样一种情况:您的代码希望该数据位于 mlist 中,而其他一些代码希望该数据位于列表中,然后您可能会感到难过。

这是一个 CPython 扩展模块,来自2003(和示例)适用于 Python 2.3。它很可能需要更新才能与更新版本的 Python 一起使用,但它演示了这种特定方法需要多么肮脏。

另一种方法是在语法层面进行改变。 Logix 提供了用于此方法的工具。这涉及较少的 C 黑客攻击,但带来了全新的解析器和编译器。

It's possible. Most things are possible in software, if you're willing to get sufficiently dirty. :) It's a bad idea, of course. If you wrote any software using such a change, it would have a number of problems:

  • Readers would be easily confused by your code. They think they're reading Python, so they think they know what [] means, but oops nope they don't.
  • If the scope of the change was global (instead of limited to, say, a single source file) then you would have difficulty combining your software with anyone else's, since you're effectively writing in two different languages. Other software might break if [] starts returning a different type, even if it's a subclass.
  • If the scope of the change is limited, then you may easily end up being confused yourself as you look at different source files with different syntax rules. If you have data that is operated on by different modules, you may find yourself in a circumstance where your code wants that data in an mlist and some other code wants it in a list and then you're probably sad.

Here's a CPython extension module from 2003 (and example) which works with Python 2.3. It very likely needs to be updated to work with more recent versions of Python, but it demonstrates how dirty you need to get for this particular approach.

Another approach is to change things at the level of the grammar. Logix provides tools for this approach. This involves less C hacking, but brings in an entire new parser and compiler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文