2010-06-05 23 views
9

Necesito hacer una variable con un comportamiento similar como en C lanquage. Necesito byte o char sin signo con rango 0-255. Esta variable se debe volcar, lo que significa ...python y byte desbordante?

myVar = 255 
myVar += 1 

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

ayuda el operador módulo? myVar + = 1; myVar = myVar% 256 – mawimawi

Respuesta

8

veo un montón de buena respuestas aquí. Sin embargo, si desea crear su propio tipo como lo mencionó, puede consultar el Python Data model documentation. Explica cómo crear clases que tengan comportamientos personalizados, por ejemplo, emulating numeric types.

Con esta información, se puede hacer una clase de esta manera:

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 continuación, puede hacer cosas como esta:

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

Soy consciente de que es posible que desee apoyar a más operaciones que yo Se ha mostrado en Num, pero a partir de este ejemplo y la documentación, debe quedar bastante claro cómo agregarlos.

+0

Quizás una envoltura de ctypes que implementó las interfaces que describió aquí sea perfecta. – fmark

+0

+1 esta es la forma de hacerlo. –

5

Vas a tener que hacer myVar &= 0xFF para asegurar que se mantiene en el rango de 0-255.

En general, puede hacer tantas manipulaciones como desee al número, siempre que lo enmascare antes de imprimir, lo envíe al método escrito en C, o lo que sea que requiera que esté en el rango de 8 bits.

+0

'&' es oscuro, antiponético, y solo funciona para potencias de dos. Mucho mejor para usar el módulo aquí –

5

El módulo ctypes contiene la funcionalidad que necesita, aunque en una forma difícil de usar. Por ejemplo:

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

Esto también funciona para este tipo firmados:

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

Usted puede desempacar el objeto de obtener la primitiva int modo:

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

Me gusta este enfoque, excepto que Python no te permite hacer 'c_ubyte (250) + 6'. :/ –

+0

Sí, es feo ¿no?Ni siquiera puedes hacer 'c_ubyte (250) + 6c_ubyte (6)' – fmark

+0

Esto probablemente depende de la implementación ... OP nunca dijo que estaba accediendo a un ABI, solo quería una aritmética modular. –

1

combinación de una excelente respuesta de Blair, y mi anterior (porque son todas soluciones distintas y que te pueden gustar uno más que los otros:

ctypes importación

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 

Es similar a la de Blair, excepto que puede pasar que el constructor de tipos ctypes que desea utilizar en el constructor:

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

Esto dará lugar a un comportamiento indefinido. OP no quiere un comportamiento indefinido, quiere aritmética modular. –

1

extender en @Blair Conrad's answer: una alternat ive aplicación podría subclase int y reemplazar los métodos deseados:

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 

Ejemplo:

>>> 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 
Cuestiones relacionadas