我需要创建一个类似于C语言的变量。 我需要一个范围在0-255之间的字节或无符号字符。 这个变量应该发生溢出,也就是说...
myVar = 255
myVar += 1
print myVar #!!myVar = 0!!
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
中展示的更多操作,但从这个例子和文档中,应该很清楚如何添加它们。
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)
>>> ctypes.c_byte(127 + 1).value
-128
c_ubyte(250) + 6
之外,我喜欢这种方法。:/ - Mark Rushakoffc_ubyte(250) + 6c_ubyte(6)
。 - fmark为确保变量保持在0-255的范围内,您需要执行myVar &= 0xFF
。
通常情况下,您可以对该数字进行任意数量的操作,只要在打印、发送到C语言编写的方法或其他需要它处于8位范围内的操作之前进行掩码处理即可。
&
是晦涩难懂的,不符合Python风格,并且只对2的幂次有效。在这里使用取模运算会更好。 - L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳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
为了进一步扩展@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