Restricted attribute writing
John O'Hagan
research at johnohagan.com
Sun Aug 7 11:35:00 EDT 2011
I'm looking for good ways to ensure that attributes are only writable such that they retain the characteristics the class requires.
My particular case is a class attribute which is initialised as a list of lists of two integers, the first of which is a modulo remainder. I need to be able to write to it like a normal list, but want to ensure it is only possible to do so without changing that format.
Below is a what I eventually came up with; a container class called OrderElement for the inner lists, and subclass of list called Order for the main attribute, which is a property of the main class, simplified below as SeqSim. It works, but seems like a hell of a lot of code for a simple idea. I'm interested in ideas for simpler solutions, and general advice on how to do this kind of thing in a straightforward way.
class OrderElement():
"""Container class which can only hold two integers
the first of which is a modulo of the 'length' arg"""
def __init__(self, lis, length):
self.__data = [None, None]
self.__length=length
self[:] = lis
def __setitem__(self, index, item):
if isinstance(index, slice):
inds = range(*index.indices(2))
for k, v in enumerate(item):
self[inds[k]] = v
elif isinstance(item, int):
if index == 0:
item %= self.__length
self.__data[index] = item
else:
raise TypeError("OrderElement takes two integers")
def __getitem__(self, index):
return self.__data[index]
class Order(list):
"""Can only contain OrderElements"""
def __init__(self, lis, length):
self.__length = length
self[:] = lis
def __setitem__(self, index, item):
if isinstance(index, slice):
item = [i if isinstance(i, OrderElement)
else OrderElement(i, self.__length)
for i in item]
elif not isinstance(item, OrderElement):
item = OrderElement(item, self.__length)
list.__setitem__(self, index, item)
def __getitem__(self, index):
"""Ensure slices are of the same class"""
if isinstance(index, slice):
return self.__class__(list.__getitem__(self, index),
self.__length)
return list.__getitem__(self, index)
class SeqSim():
"""Just the relevant bits of the main class"""
def __init__(self, lis, length):
self.__order = Order(lis, length)
self.length = length
@property
def order(self):
return self.__order
@order.setter
def order(self, lis):
if not isinstance(lis, Order):
lis = Order(lis, self.length)
self.__order = lis
--
John O'Hagan
More information about the Python-list
mailing list