Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > lists v. tuples

Reply
Thread Tools

lists v. tuples

 
 
MartinRinehart@gmail.com
Guest
Posts: n/a
 
      03-17-2008
What are the considerations in choosing between:

return [a, b, c]

and

return (a, b, c) # or return a, b, c

Why is the immutable form the default?
 
Reply With Quote
 
 
 
 
castironpi@gmail.com
Guest
Posts: n/a
 
      03-17-2008
On Mar 17, 6:49*am, (E-Mail Removed) wrote:
> What are the considerations in choosing between:
>
> * *return [a, b, c]
>
> and
>
> * * return (a, b, c) # or return a, b, c
>
> Why is the immutable form the default?


Using a house definition from some weeks ago, a tuple is a data
structure such which cannot contain a refrence to itself. Can a
single expression refer to itself ever?
 
Reply With Quote
 
 
 
 
Ninereeds
Guest
Posts: n/a
 
      03-17-2008
On Mar 17, 11:49 am, (E-Mail Removed) wrote:
> What are the considerations in choosing between:
>
> return [a, b, c]
>
> and
>
> return (a, b, c) # or return a, b, c
>
> Why is the immutable form the default?


My understanding is that the immutable form is not the default -
neither form is a default. The syntax for mutable lists requires
square brackets. The syntax for immutable tuples only requires commas.
However, commas are also used for other purposes. The parens for
tuples are the same parens that might wrap any subexpression, in this
case guarding against misinterpretation of commas. Since the parens
are normally included for consistency as well as disambiguation, they
end up being part of the tuple psychologically, but to Python itself
they are separate.

Personally, I'd make the parens compulsory so that mindsets and
language specification are better aligned. If, that is, I was
inventing a new language. But you can be sure that there's plenty of
code out there that would break if a change like that was made now.

As for choosing, if you never plan to modify the members of the
sequence, a tuple expresses that intent and allows Python to enforce
it. Some operations on tuples are probably also more efficient as a
result. That said, 90%+ of the time I use a list either way. After
all, as requirements change I might find I do need to modify after
all.

A change from tuple to list in any non-trivial case would require a
thorough test suite to ensure that all cases are updated correctly
(partly because Python is dynamically typed), and ashamed as I am to
admit it, my test suites are rarely that thorough. Without that
testing, there might be an obscure case where you still create a
tuple, and that tuple gets passed to code that expects a list and
tries to replace an element.
 
Reply With Quote
 
Ninereeds
Guest
Posts: n/a
 
      03-17-2008
On Mar 17, 12:28 pm, (E-Mail Removed) wrote:

> > Why is the immutable form the default?

>
> Using a house definition from some weeks ago, a tuple is a data
> structure such which cannot contain a refrence to itself. Can a
> single expression refer to itself ever?


Can't imagine why that feature was highlighted in particular, but a
list can reference itself even though an expression can't.

The following example looks a bit self-referential, but isn't...

a = 2
a = [1, a, 3] # result [1, 2, 3]

The following additional line, however does create a self-referencing
list...

a [1] = a

The result being [1, [...], 2]

It's nice to see that Python can handle the output for this without
going into an infinite recursion - which is exactly what it used to do
in the distant past.

A tuple cannot be made to reference itself because it cannot be
modified after creation. The key point is that lists are mutable,
whereas tuples are not.
 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      03-17-2008
On Mon, 17 Mar 2008 05:28:19 -0700, castironpi wrote:

> a tuple is a data
> structure such which cannot contain a refrence to itself.




>>> a = [] # a list
>>> b = (a, None) # a tuple
>>> a.append(b)
>>> print b

([([...], None)], None)
>>> b[0][0] is b

True


So, yes tuples can contain a reference to themselves, but only indirectly.



> Can a single expression refer to itself ever?


You can't refer to an object until it exists, so no.




--
Steven
 
Reply With Quote
 
Duncan Booth
Guest
Posts: n/a
 
      03-17-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> What are the considerations in choosing between:
>
> return [a, b, c]
>
> and
>
> return (a, b, c) # or return a, b, c
>

A common explanation for this is that lists are for homogenous
collections, tuples are for when you have heterogenous collections i.e.
related but different things.

If you follow this line of argument then when you want to return some
values from a function, e.g. url, headers and data a tuple would be the
appropriate thing to use.

If you really are returning a homogenous collection (e.g. top 5 urls)
then a list would be more appropriate.

Another way to look at it is what you expect the caller to do with the
results. If they are just going to unpack a fixed set of values then a
tuple makes sense. If you write:

return url, headers, data

then the caller writing:

url, headers, data = frobozz()

has a certain symmetry.

It isn't set in stone of course: use whatever you want or whatever feels
right at the time.

> Why is the immutable form the default?
>

It isn't. It uses whichever type you specify but tuples may involve a
little less typing.
 
Reply With Quote
 
Robert Bossy
Guest
Posts: n/a
 
      03-17-2008
(E-Mail Removed) wrote:
> On Mar 17, 6:49 am, (E-Mail Removed) wrote:
>
>> What are the considerations in choosing between:
>>
>> return [a, b, c]
>>
>> and
>>
>> return (a, b, c) # or return a, b, c
>>
>> Why is the immutable form the default?
>>

>
> Using a house definition from some weeks ago, a tuple is a data
> structure such which cannot contain a refrence to itself. Can a
> single expression refer to itself ever?
>

In some way, I think this answer will be more confusing than
enlightening to the original poster...

The difference is that lists are mutable, tuples are not. That means you
can do the following with a list:
- add element(s)
- remove element(s)
- re-assign element(s)
These operations are impossible on tuples. So, by default, I use lists
because they offer more functionality.
But if I want to make sure the sequence is not messed up with later, I
use tuples. The most frequent case is when a function (or method)
returns a sequence whose fate is to be unpacked, things like:

def connect(self, server):
# try to connect to server
return (handler, message,)

It is pretty obvious that the returned value will (almost) never be used
as is, the caller will most probably want to unpack the pair. Hence the
tuple instead of list.

There's a little caveat for beginners: the tuple is immutable, which
doesn't mean that each element of the tuple is necessarily immutable.

Also, I read several times tuples are more efficient than lists, however
I wasn't able to actually notice that yet.

Cheers,
RB

 
Reply With Quote
 
Ninereeds
Guest
Posts: n/a
 
      03-17-2008
On Mar 17, 1:31 pm, Duncan Booth <(E-Mail Removed)> wrote:

> A common explanation for this is that lists are for homogenous
> collections, tuples are for when you have heterogenous collections i.e.
> related but different things.


I interpret this as meaning that in a data table, I should have a list
of records but each record should be a tuple of fields, since the
fields for a table usually have different forms whereas the records
usually all have the same record layout.

Makes sense, but not exactly *because* of the homogenous/heterogenous
thing but rather because a record is smaller than a table, and a
records component fields are more closely bound together than the
records in a table.

In short, adding, removing and overwriting records are essential
operations (though Haskell programmers might disagree). Any
modifications to records themselves can practically be handled as
replacing one complete tuple with another.

As a final note, I tend to implement tables as either lists of
dictionaries, or lists of class instances. That way my fields are
named. Its better in maintenance terms if I need to add new fields to
the tables later on.
 
Reply With Quote
 
Duncan Booth
Guest
Posts: n/a
 
      03-17-2008
Ninereeds <(E-Mail Removed)> wrote:

> On Mar 17, 1:31 pm, Duncan Booth <(E-Mail Removed)> wrote:
>
>> A common explanation for this is that lists are for homogenous
>> collections, tuples are for when you have heterogenous collections i.e.
>> related but different things.

>
> I interpret this as meaning that in a data table, I should have a list
> of records but each record should be a tuple of fields, since the
> fields for a table usually have different forms whereas the records
> usually all have the same record layout.


That is indeed what Python's Database API usually does (although it doesn't
mandate it):

.fetchmany([size=cursor.arraysize])

Fetch the next set of rows of a query result, returning a
sequence of sequences (e.g. a list of tuples). An empty
sequence is returned when no more rows are available.


 
Reply With Quote
 
castironpi@gmail.com
Guest
Posts: n/a
 
      03-17-2008
On Mar 17, 11:03*am, Duncan Booth <(E-Mail Removed)>
wrote:
> Ninereeds <(E-Mail Removed)> wrote:
> > On Mar 17, 1:31 pm, Duncan Booth <(E-Mail Removed)> wrote:

>
> >> A common explanation for this is that lists are for homogenous
> >> collections, tuples are for when you have heterogenous collections i.e.
> >> related but different things.

>
> > I interpret this as meaning that in a data table, I should have a list
> > of records but each record should be a tuple of fields, since the
> > fields for a table usually have different forms whereas the records
> > usually all have the same record layout.

>
> That is indeed what Python's Database API usually does (although it doesn't
> mandate it):
>
> * * * * .fetchmany([size=cursor.arraysize])
>
> * * * * * * Fetch the next set of rows of a query result, returning a
> * * * * * * sequence of sequences (e.g. a list of tuples). An empty
> * * * * * * sequence is returned when no more rows are available.


Two things:

>>> b in b

False

in S. D'Aprano's example, which somewhat obscures (casts a shadow on)
its intuitive meaning. "Hand me everything that's in there. > For x
in There: hand( me, x ).

> For x in rchain( There ): hand( me, x ) < Hand me anything that's in anything that's in there, or is in there.


Closet = [ Box[ ball ] ] >
Box[ ball ]?
or Box, ball?

Despite that 'in' is a very common word [lacks cit.], you don't often
get ambiguities (read: questions) about containers in something. Too
custom. The word isn't defined at that extremity of combinations /
cartesian products of particulars (context). It doesn't have a common
sense, and computer science is a pretty unique field in that it finds
(or, invents) all-and-only definitions of words.

(Which reminds me, what about a classmethod __getitem__ construtor?)

However, from mathematics, which is at least older, if not more in
tune with the common senses and uses, (there exists an a and b such
that) Member( a, b ) != Exists x such that Member( a, b ) & Member( b,
x ). In other words, Python honors math's definition.

In the example, would you treat 'ball' separately unless explicity
asked to? (But, keep sure not to alter the contents of any of the
containers that are in there.) There's a fine example of
miscommunication: neither behavior was the default between the pair:
one knew one default; the other knew another. (But, it's ok to alter
the contents of any containers.) Aside, do you think there are trends
among who and when uses what defaults? Such as math background,
social status, etc.?

Computers are very good at attention to detail: ("I" am.) "You did
not specify whether to alter containers in it." Of course, the
program that's following would have to have noticed two things: that
there's a short-cut if you can, and you might not want it to. It's
not only a problem of formal systems: No= { X, Y, Z }. Some (finite)
context hasn't determined the convention of wish-expression in every
combination of (future possible) cases.

while 1:
print( "You made an assumption!" )
print( "No, -you- made an assumption!" )
break

while 1:
print( "I made an assumption." )
print( "I also made an assumption." )

But is it determined whether it's determined whether the person meant
to? That is, can you tell whether the person didn't specify? "I'm
sorry, we haven't spoken about containers in containers enough for me
to tell what your wishes are."

My worry is that popular judgment isn't best in science. What factors
in to the architect's decision? His feelings about use cases? His
calculations about use cases? His feelings about popularity of each?
His calculations about popularity? Mabye Python would have ten extra
speakers if __contains__ had been defined differently! X percent of
all shortest-form syntactic combinations can be written in less tokens
with one definition, but no matter how much I remind them, they won't
remember combination C, so only Y percent are actually, practically
ever written in 2008 Earth programming. Because we're stupid, no.
Because we have other priorities than programming. (But my bigger
house for me was more important.)

'rchain', recursive chain, might be the next function on the path that
itertools is on.



Databases have come to (but don't have to stay) use integers as
autokeys in records. That makes one way to refer to a record to refer
to its integer. However, if one's testing for identity between
records, that key is redundant. Just identify yourself, and refer
back to earlier in context. And incidentally, why namedtuples but no
namedlists? Or nameddicts? And could one define an anonymous type?

This is interesting:

>>> type('A',(),{}) is type('A',(),{})

False
>>> type('A',(),{}) == type('A',(),{})

False

>>> type('G',(),{})

<class '__main__.G'>
>>> G

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'G' is not defined

A type went out of scope. Is there an abstraction of 'pickle' which
doesn't need the type defined in its target module?

>>> pickle.dumps( type('A',(),{}) )

pickle.PicklingError: Can't pickle <class '__main__.A'>: it's not the
same object as __main__.A
>>> pickle.dumps( type('A',(),{})() )

pickle.PicklingError: Can't pickle <class '__main__.A'>: it's not the
same object as __main__.A
>>> del A
>>> pickle.dumps( type('A',(),{}) )

pickle.PicklingError: Can't pickle <class '__main__.A'>: it's not
found as __main__.A
>>> pickle.dumps( type('A',(),{})() )

pickle.PicklingError: Can't pickle <class '__main__.A'>: it's not
found as __main__.A

But all the information's there!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Dictionaries with tuples or tuples of tuples Jon Reyes Python 18 02-19-2013 03:56 AM
Passing tuples of tuples to sqlite xera121 Python 8 09-30-2009 05:45 AM
tuples within tuples korovev76@gmail.com Python 12 10-27-2007 08:16 PM
Re: Lists of lists and tuples, and finding things within them Daniel Nogradi Python 3 11-10-2006 07:57 AM
Different tuples to one container? (One type of a pointer to point to different kinds of tuples?) fff_afafaf@yahoo.com C++ 5 10-05-2006 11:17 PM



Advertisments