Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #11105 > unrolled thread

Re: Restricted attribute writing

Started byThomas Jollans <t@jollybox.de>
First post2011-08-10 11:38 +0200
Last post2011-08-10 11:38 +0200
Articles 1 — 1 participant

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Restricted attribute writing Thomas Jollans <t@jollybox.de> - 2011-08-10 11:38 +0200

#11105 — Re: Restricted attribute writing

FromThomas Jollans <t@jollybox.de>
Date2011-08-10 11:38 +0200
SubjectRe: Restricted attribute writing
Message-ID<mailman.2094.1312969150.1164.python-list@python.org>
On 07/08/11 17:35, John O'Hagan wrote:
> 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.  

What I think you're looking for is properties:

http://docs.python.org/py3k/library/functions.html#property

So: with a property, channel getting and setting through functions that
can check the value for validity.
Secondly, use tuples instead of lists where possible: they're not
mutable, which makes controlling their value a lot easier.
If your attribute is a list that users may append elements to, consider
adding an addelement(tpl) method to your class that checks the value
and appends it to the list.

Lastly, consider the option of not checking vigorously at all at that
point: If the value is invalid, it will raise an exception later, when
it is used. Depending on what you're doing, this might be all the
checking you need. If you're going to serialise the data, or if you want
to use the property setter to check user input directly, that's probably
not a strong option.

Thomas

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

[toc] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web