python和溢出字节?

时间:2010-06-05 11:52:33

标签: python variables overflow

我需要创建一个类似于C语言的变量。 我需要范围为0-255的字节或无符号字符。 这个变量应该溢出,这意味着......

myVar = 255
myVar += 1

print myVar #!!myVar = 0!!

5 个答案:

答案 0 :(得分:8)

我在这里看到很多好的答案。但是,如果您想要创建自己的类型,可以查看Python Data model documentation。它解释了如何创建具有自定义行为的类,例如emulating numeric types

使用此信息,您可以创建一个类似的类:

class Num:
    def __init__(self, n):
        self.n = (n % 256)

    def __repr__(self):
        return repr(self.n)

     def __add__(self, other):
        return Num(self.n+int(other))

    # transform ourselves into an int, so
    # int-expecting methods can use us
    def __int__(self):
        return self.n

然后你可以这样做:

>>> a = Num(100)
>>> print a
100
>>> b = a + 50
>>> print b
150
>>> c = Num(200)
>>> d = a + c
>>> print d
44

我意识到您可能希望支持比我在Num中显示的更多操作,但是从这个示例和文档中,应该非常清楚如何添加它们。

答案 1 :(得分:5)

您必须myVar &= 0xFF确保其保持在0-255范围内。

您通常可以根据需要对数字执行尽可能多的操作,只要在打印前屏蔽它,发送到用C编写的方法,或者需要它在8位范围内的任何操作。

答案 2 :(得分:5)

ctypes模块包含您需要的功能,尽管是一种难以使用的形式。例如:

>>> import ctypes
>>> ctypes.c_ubyte(255)
c_ubyte(255)
>>> ctypes.c_ubyte(255 + 1)
c_ubyte(0)

这也适用于签名类型:

>>> ctypes.c_byte(127 + 1)
c_byte(-128)

您可以取消装入对象以获取基元  int喜欢这样:

>>> ctypes.c_byte(127 + 1).value
-128

答案 3 :(得分:1)

结合Blair的优秀答案和我之前的答案(因为它们都是截然不同的解决方案,你可能比另一个更喜欢:

导入ctypes

class CInt:
    def __init__(self, ctype, n):
        self.ctype = ctype
        self.n = ctype(n)

    def __repr__(self):
        return repr(self.n.value)

    def __add__(self, other):
        return CInt(self.ctype, self.n.value + int(other))

    # transform ourselves into an int, so
    # int-expecting methods can use us
    def __int__(self):
        return self.n.value

它类似于Blair,除了你可以传递你想在构造函数中使用的ctypes类型构造函数:

>>> n = CInt(ctypes.c_byte, 127)
>>> n + 1
-128

答案 4 :(得分:1)

要扩展@Blair Conrad's answer:替代实现可以继承int并覆盖所需的方法:

class Byte(int):
    _all = None # cache
    __slots__ = ()
    def __new__(cls, value):
        if Byte._all is None:
           Byte._all = [int.__new__(cls, i) for i in xrange(256)]
        return Byte._all[value % 256]
    def __iadd__(self, other):
        return self + Byte(other)
    def __isub__(self, other):
        return self - Byte(other)
    def __add__(self, other):
        if isinstance(other, Byte):            
            return Byte(int(self) + other)
        return int(self) + other
    def __sub__(self, other):
        if isinstance(other, Byte):            
            return Byte(int(self) - other)
        return int(self) - other
    def __neg__(self):
        return Byte(-int(self))
    def __repr__(self):
        return "Byte(%d)" % self

示例:

>>> myvar = Byte(255)
>>> myvar
Byte(255)
>>> myvar += 1
>>> myvar
Byte(0)
>>> myvar -= 1
>>> myvar
Byte(255)
>>> -myvar
Byte(1)
>>> myvar.i = 1
Traceback (most recent call last):
...
AttributeError: 'Byte' object has no attribute 'i'
>>> from itertools import permutations
>>> for a,b in permutations((Byte(1), Byte(-1), 1), 2):
...     print "%r + %r = %r" % (a,b, a+b)
...     print "%r - %r = %r" % (a,b, a-b)
Byte(1) + Byte(255) = Byte(0)
Byte(1) - Byte(255) = Byte(2)
Byte(1) + 1 = 2
Byte(1) - 1 = 0
Byte(255) + Byte(1) = Byte(0)
Byte(255) - Byte(1) = Byte(254)
Byte(255) + 1 = 256
Byte(255) - 1 = 254
1 + Byte(1) = 2
1 - Byte(1) = 0
1 + Byte(255) = 256
1 - Byte(255) = -254
>>> id(Byte(255)) == id(Byte(1)+Byte(254))
True