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


Groups > comp.lang.python > #11105

Re: Restricted attribute writing

Path csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!aioe.org!feeder.news-service.com!news2.euro.net!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail
Return-Path <t@jollybox.de>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.001
X-Spam-Evidence '*H*': 1.00; '*S*': 0.00; 'else:': 0.03; 'elif': 0.04; 'attributes': 0.05; 'attribute': 0.07; 'bits': 0.07; 'slices': 0.07; 'used.': 0.07; 'append': 0.09; 'integers': 0.09; 'modulo': 0.09; 'subclass': 0.09; 'writable': 0.09; 'exception': 0.12; 'def': 0.15; 'class,': 0.15; '"""ensure': 0.16; '@property': 0.16; 'appends': 0.16; 'attribute,': 0.16; 'doing,': 0.16; 'int):': 0.16; 'item)': 0.16; 'length)': 0.16; 'received:192.168.1.40': 0.16; 'simplified': 0.16; 'subject:writing': 0.16; 'wrote:': 0.16; 'simpler': 0.18; 'solutions,': 0.19; 'seems': 0.20; 'header:In-Reply-To:1': 0.22; 'input': 0.24; 'index': 0.24; 'code': 0.25; "i'm": 0.27; 'raise': 0.28; 'channel': 0.28; 'lists': 0.28; 'elements': 0.29; 'easier.': 0.30; 'email name:': 0.30; 'tuples': 0.30; 'class': 0.30; 'url:library': 0.31; 'changing': 0.31; 'list': 0.32; 'probably': 0.33; 'to:addr:python-list': 0.33; 'instead': 0.33; 'header:User- Agent:1': 0.34; 'checking': 0.34; 'setting': 0.34; 'controlling': 0.34; 'option.': 0.34; 'retain': 0.34; 'list.': 0.35; 'data,': 0.35; 'lists,': 0.35; 'hold': 0.35; 'url:python': 0.36; 'checks': 0.37; 'later,': 0.37; 'list,': 0.37; 'but': 0.37; 'two': 0.37; 'think': 0.38; 'strong': 0.38; 'url:org': 0.38; 'subject:: ': 0.39; 'received:192': 0.39; 'getting': 0.39; 'option': 0.39; 'url:docs': 0.39; 'ways': 0.39; 'else': 0.39; 'user': 0.39; 'format.': 0.39; 'to:addr:python.org': 0.39; 'case': 0.39; 'called': 0.40; 'might': 0.40; 'where': 0.40; 'your': 0.61; 'kind': 0.61; 'order': 0.62; 'john': 0.62; 'below': 0.62; 'property': 0.63; 'works,': 0.68; 'relevant': 0.69; 'received:62': 0.70; 'container': 0.73; 'from:addr:t': 0.84; 'lastly,': 0.84; 'lis': 0.84; 'point:': 0.84; 'so:': 0.84; 'url:functions': 0.84
Date Wed, 10 Aug 2011 11:38:46 +0200
From Thomas Jollans <t@jollybox.de>
User-Agent Mozilla/5.0 (X11; Linux x86_64; rv:5.0) Gecko/20110628 Thunderbird/5.0
MIME-Version 1.0
To python-list@python.org
Subject Re: Restricted attribute writing
References <20110808013500.7c9e30ff44caee0f0bbf988a@johnohagan.com>
In-Reply-To <20110808013500.7c9e30ff44caee0f0bbf988a@johnohagan.com>
X-Enigmail-Version 1.2
OpenPGP id=5C8691ED
Content-Type text/plain; charset=ISO-8859-1
Content-Transfer-Encoding 7bit
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.12
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <http://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <http://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Newsgroups comp.lang.python
Message-ID <mailman.2094.1312969150.1164.python-list@python.org> (permalink)
Lines 94
NNTP-Posting-Host 2001:888:2000:d::a6
X-Trace 1312969150 news.xs4all.nl 23890 [2001:888:2000:d::a6]:40116
X-Complaints-To abuse@xs4all.nl
Xref x330-a1.tempe.blueboxinc.net comp.lang.python:11105

Show key headers only | View raw


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
> 

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

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

csiph-web