我正在将Ian Bell的Elite从C转换为Python。C (ab)使用16位整数,会溢出。Python使用神奇的Python整数,而不是。这是个问题。
我可以定义一个class UInt16:
(更新:或者使用ctype的内置UInt16),它的行为就像我想要的那样,但然后我必须"强制"整个程序中的每个数字都是UInt16
。我有没有办法告诉我的翻译"嘿,你知道Int
吗?"好吧,我希望你们在所有你们通常会用到的地方都使用这个类。"
或者,如果做不到这一点,有没有其他简单的方法可以实现整数溢出?
简短的回答:不可能像您希望的那样重写默认的整数行为。
长答:
首先,我们可以看到Python中存在一些16位无符号整数的实现:
- 在内置库
ctypes
中,16位无符号整数可作为c_uint16
Numpy库也包含 - 实现你自己的uint16数据类型(与操作符重载等)
unint16
我们是否可以使用这些或其他数据类型来覆盖Python中的默认整数的问题更棘手。
让我们假设用户使用int
方法创建程序中的所有整数。如果是这种情况,那么我们可以包装int方法来创建无符号整数,而不是普通整数:
from ctypes import c_uint16
_int = int
def int(x):
return c_uint16(x)
例如,下面的代码很好:
a = int(1)
我们可以检查:
>>> type(a)
<class 'ctypes.c_ushort'>
问题来了:
b = 1
在这种情况下,没有调用int
方法,而是将b
简单地赋值为1
。我们希望做的是重写这个行为,但不幸的是,这是不可能的。
这不可能。您想要猴子补丁内置类型,这在python中是不可能的。
整数字面值(1,不是int("1"))在builtins
/__builtins__
模块中总是int类型(取决于python版本)。你想做的基本上是复制unint16
上的所有方法到int类(因为方法只是函数类型的属性)。在本例中,在您声明1的每个地方,您将获得一个类型为int
的对象,其行为与unint16
相同。
这在python中是不可能的。我想底层的实现因此变得更容易了,但这背后有更深层次的逻辑。
int
是核心类之一,像list
, str
, object
, set
, dict
, tuple
等。假设有人创建了一个非常方便的库,几乎每个人都会使用。如果您曾经使用过Java,那么想象一下它对Apache Commons或Spring的影响。实际上,每个人都会使用它,因为它使开发更快。现在,假设有人创建了一个分支——在他的公司内部使用,说他这样做是为了保持代码库的稳定——这有一小段代码,改变了内置的object
行为,所以它向他发送了一些重要的数据。他可以欺骗数百万用户的私人数据(地址,然后他会出售,密码,等等)。令人毛骨悚然的场景,对吧?
现在,这看起来不太真实,但是如果您让最终用户评估python脚本呢?您可能见过内置python shell的文本编辑器(如gedit)或音乐播放器(Rhythmbox),它们为程序内部提供接口。现在,有人以某种方式将object
行为的改变注入你的机器。另一个令人毛骨悚然的场景。
这些都是我想到的例子,我真的不记得python的创造者是怎么说的——这就是为什么我提供了进一步讨论的链接。
有点跑题了——这实际上可能会导致一些很好的库("this"的意思是"允许内置的猴子补丁")。想象一下,猴子给所有插件打补丁,以便将它们存储在某个多处理管理器中。您实际上获得了基于多处理的java风格的多线程,并且可以以某种方式避免GIL。当然,还有许多其他的原因,为什么这不是真的很好("多线程的错觉不是多线程",例如),但我发现它对简单的日常桌面脚本很有用。