Я должен сделать переменную с подобным поведением как на языке C. Мне нужны байт или неподписанный символ с диапазоном 0-255. Эта переменная должна переполниться, который означает...
myVar = 255
myVar += 1
print myVar #!!myVar = 0!!
Я вижу здесь много хороших ответов. Однако, если вы хотите создать свой собственный тип, как вы упомянули, вы можете посмотреть документацию модели данных Python . В нем объясняется, как создавать классы с настраиваемым поведением, например , эмулирующими числовые типы .
Используя эту информацию, вы можете создать такой класс:
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)
Вы можете распаковать объект, чтобы получить примитив int примерно так:
>>> ctypes.c_byte(127 + 1).value
-128
В дополнение к ответ @Blair Conrad : альтернативная реализация может создать подкласс 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
Объединение отличного ответа Блэра и моего предыдущего (потому что все они являются разными решениями, и одно может вам понравиться больше, чем другое:
import 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
Он похож на ответ Блэра, за исключением того, что вы можете передать ему конструктор типа ctypes, который вы хотите использовать в конструкторе:
>>> n = CInt(ctypes.c_byte, 127)
>>> n + 1
-128
Вам придется сделать myVar &= 0xFF
, чтобы он оставался в диапазоне 0-255.
Вообще, вы можете делать с числом столько манипуляций, сколько захотите, если только вы замаскируете его перед печатью, отправкой в метод, написанный на C, или чем-либо, что требует, чтобы оно находилось в 8-битном диапазоне.