2010-06-05 5 views
9

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

myVar = 255 
myVar += 1 

print myVar #!!myVar = 0!! 
+0

делает модуль оператор помощи? myVar + = 1; myVar = myVar% 256 – mawimawi

ответ

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 

Я понимаю, что вы можете поддерживать больше операций, чем I 've показано в Num, но из этого примера и документации должно быть достаточно ясно, как их добавить.

+0

Возможно, оболочка ctypes, которая реализовала интерфейсы, описанные здесь, была бы идеальной. – fmark

+0

+1 вот как это сделать. –

5

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

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

+0

'&' неясен, нерентичен и работает только для двух. Намного лучше использовать модуль здесь –

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 
+0

Мне нравится этот подход, за исключением того, что Python не позволяет вам делать 'c_ubyte (250) + 6'. :/ –

+0

Да, его уродливый не так ли?Вы даже не можете делать 'c_ubyte (250) + 6c_ubyte (6)' – fmark

+0

Это, вероятно, зависит от реализации ... OP никогда не говорил, что он обращается к некоторым ABI, он просто хочет модульную арифметику. –

1

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

импорта 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 
+0

Это приведет к неопределенному поведению. OP не хочет неопределенного поведения, он хочет модульную арифметику. –

1

чтобы продлить на @Blair Conrad's answer: alternat Реализация может ив подкласс 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 
Смежные вопросы