Python и переполняющийся байт?

Я должен сделать переменную с подобным поведением как на языке C. Мне нужны байт или неподписанный символ с диапазоном 0-255. Эта переменная должна переполниться, который означает...

myVar = 255
myVar += 1

print myVar #!!myVar = 0!!
10
задан Meloun 5 June 2010 в 11:52
поделиться

5 ответов

Я вижу здесь много хороших ответов. Однако, если вы хотите создать свой собственный тип, как вы упомянули, вы можете посмотреть документацию модели данных 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 , но из этого примера и документации должно быть достаточно ясно, как их добавить.

9
ответ дан 3 December 2019 в 18:32
поделиться

Модуль 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
5
ответ дан 3 December 2019 в 18:32
поделиться

В дополнение к ответ @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
1
ответ дан 3 December 2019 в 18:32
поделиться

Объединение отличного ответа Блэра и моего предыдущего (потому что все они являются разными решениями, и одно может вам понравиться больше, чем другое:

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
1
ответ дан 3 December 2019 в 18:32
поделиться

Вам придется сделать myVar &= 0xFF, чтобы он оставался в диапазоне 0-255.

Вообще, вы можете делать с числом столько манипуляций, сколько захотите, если только вы замаскируете его перед печатью, отправкой в метод, написанный на C, или чем-либо, что требует, чтобы оно находилось в 8-битном диапазоне.

5
ответ дан 3 December 2019 в 18:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: