UserList.__getslice__(): copy.copy(self.data) vs. self.__class__(self.data).

Tom Funk _spam_sux_tdfunk at _spam_sux_nettally.com
Wed Mar 15 05:25:16 CET 2000


Alex:

Thanks so much for responding.

In an article posted 14 Mar 2000 17:37:00 -0500,
Alex (alex at somewhere.round.here) said:

> Sometimes, that's what you want, and, in my experience, sometimes not.

It seems to me that *not* carrying forward the currently active 
attributes is counter-intuitive (of course, that's probably just me....).  
*I* can't think of a case where I'd want to lose the attributes I'd built 
up over the course of the current program execution when I slice off a 
sub-set of the list of things I'm tracking.  Can you give me an example 
of where losing the additional attributes after taking a subset of an 
existing collection is desirable?  

Consider an inventory system and a class that implements an order, with 
the list holding each of the order items.  Each of the items "belongs" to 
the order and shares the order's attributes: order number, ship date, 
customer id, shipping address, etc.  Assume further that the user changes 
her order and she now wants only the middle three of the five items 
ordered:

  neworder = order[1:4]

The neworder instance shouldn't have to go back to the order instance to 
collect the order-specific attributes (order id, customer id, etc.)

Or perhaps the last two items in the order are back ordered:

  backordered = order[len(order)-1:len(order)]
  backordered.status = Order.BACKORDERED
  backordered.shipdate = None
  backordered.bodate = DateTime.today()

In this instance, losing all the original order information would be a 
huge pain, and would be counter-intuitive -- I'd expect the order ID, 
customer ID, shipping address, etc, to end up in the new back ordered 
instance.

With the other approach, all of the order attributes are lost and would 
have to be copied from the original order.  Ouch.  What if I forget one?  
Enter one sneaky little bug, hard to catch.

It just seems to me that if one goes to the trouble to create a class 
(FancyList) that has attributes beyond the data attribute, then each of 
the items in the list are "children" of FancyList and share the 
attributes of FancyList.  It's a one-to-many relationship.  It seems to 
me that slicing off a subset of the list would only rarely disconnect the 
items in the subset from super-set. It also seems to me that such 
behavior would be the exception rather than the rule.

> UserList is intended as a base class, so you can override any methods
> that aren't doing what you want.  

True, but to my thinking the current implementation is neither intuitive 
nor does it mimic a "real" list object.  Shouldn't the counter-intuitive 
and the non-list-like implementation be the overridden implementation 
rather than the "normal" one?  We learn how lists work when we learn 
Python, but UserList doesn't act like a "real" list, and we have to be 
aware of those differences when we use it - or suffer for it.  

I'm not terribly experienced with Python and I stumbled over this quirk 
myself.  I expected UserList to act like a true list.  When I decided to 
inherit from it I gave the code a cursory glance and, seeing no 
indication that UserList's behavior departs from that of a native list, I 
started coding.  The test cases I wrote bumped up against the deviations 
-- I was treating the derived class like a real list, and it failed to 
act like a native list object under certain conditions. This led to my 
research and this series of messages and what-not.

My assertion is that UserList should mimic a true list object as 
precisely as possible and any deviation from "acting like a native list" 
should be left as an exercise for the implementor.  

My biggest worry over UserList is that it doesn't properly handle out-of-
bounds negative numbers.  Instead of raising an IndexError for what is 
likely a programming error, it quietly returns an unexpected result.  Not 
good.  Silently returning incorrect results goes against everything I 
know about "defensive" programming.  Steve McConnell would have a cow.

The purpose of my article was to elicit feedback on whether UserList.py 
should be changed to mimic a real list.  If I understand you correctly, 
you believe that UserList, seemingly flawed as it is, should be left as 
it is?  

I've made my case as strongly as I can.  Now I'll just sit back and tally 
the "votes." <wink>

-- 
-=< tom >=-
Thomas D. Funk (tdfunk at asd-web.com)      |        "Software is the lever
Software Engineering Consultant          | Archimedes was searching for"
Advanced Systems Design, Tallahassee FL. |




More information about the Python-list mailing list