changing value of 'self' when subclassing int

D

David Coffin

I'd like to subclass int to support list access, treating the integer
as if it were a list of bits.
Assigning bits to particular indices involves changing the value of
the integer itself, but changing 'self' obviously just alters the
value of that local variable.
Is there some way for me to change the value of the BitSequence
object itself? I've also tried wrapping and delegating using
__getattr__, but I couldn't figure out how to handle in-place methods.

Thanks for your help,
David Coffin


class BitSequence(int):
"""An integer emulating a sequence of bits, subclassing int."""
def __new__(cls, value, length=32):
inst = super(BitSequence,cls).__new__(cls, value)
inst.length = length
return inst

def __setitem__(self, index, bit):
mask = 1 << self.length - index - 1
if bit == 1:
# XXX only changing local 'self'
self |= mask
elif bit == 0:
self &= ~mask

def __getitem__(self, i):
return (self >> (self.length - i -1)) & 1

def __repr__(self):
s = ''
for i in xrange(self.length):
s = str(self >> i & 1) + s
return s + " : " + str(self)
 
A

Alex Martelli

David Coffin said:
I'd like to subclass int to support list access, treating the integer
as if it were a list of bits.

Fine, but:
Assigning bits to particular indices involves changing the value of
the integer itself, but changing 'self' obviously just alters the

....integers are immutable, like all other numbers in Python: there is NO
way to "change the value of the integer itself".

I originally proposed to have "mutable numbers" (at least optionally) in
gmpy, but the reaction was a broadside against the idea, to the point
that I never got around to it -- gmpy includes a lot of functionality
for bit-level manipulation, but still only with immutable bitlists
(mapped into gmpy.mpz instances).


Alex
 
F

Fuzzyman

David said:
I'd like to subclass int to support list access, treating the integer
as if it were a list of bits.
Assigning bits to particular indices involves changing the value of
the integer itself, but changing 'self' obviously just alters the
value of that local variable.
Is there some way for me to change the value of the BitSequence
object itself? I've also tried wrapping and delegating using
__getattr__, but I couldn't figure out how to handle in-place methods.

Probably your best bet is to have the assignment done as a method call
which returns the new value.

All the best,

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml
 
N

Nick Craig-Wood

David Coffin said:
I'd like to subclass int to support list access, treating the integer
as if it were a list of bits.
Assigning bits to particular indices involves changing the value of
the integer itself, but changing 'self' obviously just alters the
value of that local variable.
Is there some way for me to change the value of the BitSequence
object itself? I've also tried wrapping and delegating using
__getattr__, but I couldn't figure out how to handle in-place
methods.

Here was my take on the problem when it came up for me. Note the
FIXMEs ;-) My first attempt was to subclass long which was a dismal
failure.

class bits:
"""
Space efficient bit storage. It returns something which acts
like an infinitely long array. The array is initialised to all 0s

FIXME need to implement lots more methods!
FIXME check for -ve indices etc!
FIXME can do boolean methods by arithmetic on longs
FIXME can't subclass long as long is immutable :-(
"""
def __init__(self, initial = None):
"Initialise with the initial state of the array or nothing for it to be set to all 0s"
self.i = 0L
if initial:
for i in initial:
self.i <<= 1
self.i |= i
def mask(self, n):
return 1L << n
def __getitem__(self, n):
return (self.i & self.mask(n)) != 0L
def __setitem__(self, n, v):
m = self.mask(n)
if v:
self.i |= m
elif self.i & m:
self.i ^= m
# FIXME implement len() and use it in __repr__ to output directly!
def __repr__(self):
# FIXME is there a way to convert a long to binary?
content = ""
if self.i:
L = []
i = self.i
while i:
L.append(int(i & 1L))
i >>= 1
L.reverse()
content = str(L)
return "%s(%s)" % (self.__class__.__name__, content)
 
D

David Coffin

Thanks for all the help.
On 20 Feb 2006, at 17:34, Alex Martelli wrote:

...integers are immutable, like all other numbers in Python: there
is NO
way to "change the value of the integer itself".

So, on learning that I could subclass the number types, I didn't even
consider the fact that they're immutable. I feel slightly foolish.
And I'll look at gmpy straight away, it looks like it contains
functionality I'll find useful.
On 21 Feb 2006, at 10:58, Fuzzyman wrote:

Probably your best bet is to have the assignment done as a method call
which returns the new value.

I not sure that would be suitable in this case. I'm using genetic
algorithm code containing some methods that assume 'individuals' are
represented as bitstrings, and some that assume individuals are
represented as lists of integers. Ideally, I could have created a
class for the bitstring individuals that also supported list based
bit assignment (without too much overhead).

Best wishes,
David Coffin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top