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


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

Newbie Question: Obtain element from list of tuples

Started byHoneyMonster <someone@someplace.invalid>
First post2011-12-18 19:41 +0000
Last post2011-12-20 00:59 +0000
Articles 15 — 8 participants

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


Contents

  Newbie Question: Obtain element from list of tuples HoneyMonster <someone@someplace.invalid> - 2011-12-18 19:41 +0000
    Re: Newbie Question: Obtain element from list of tuples Arnaud Delobelle <arnodel@gmail.com> - 2011-12-18 19:49 +0000
    Re: Newbie Question: Obtain element from list of tuples Roy Smith <roy@panix.com> - 2011-12-18 15:04 -0500
      Re: Newbie Question: Obtain element from list of tuples HoneyMonster <someone@someplace.invalid> - 2011-12-18 20:22 +0000
        Re: Newbie Question: Obtain element from list of tuples Roy Smith <roy@panix.com> - 2011-12-18 15:25 -0500
      Re: Newbie Question: Obtain element from list of tuples alex23 <wuwei23@gmail.com> - 2011-12-18 18:35 -0800
        Re: Newbie Question: Obtain element from list of tuples Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-19 03:00 +0000
          Re: Newbie Question: Obtain element from list of tuples "Frank Millman" <frank@chagford.com> - 2011-12-19 08:46 +0200
            Re: Newbie Question: Obtain element from list of tuples DevPlayer <devplayer@gmail.com> - 2011-12-19 07:37 -0800
            Re: Newbie Question: Obtain element from list of tuples alex23 <wuwei23@gmail.com> - 2011-12-19 19:53 -0800
    Re: Newbie Question: Obtain element from list of tuples Chris Angelico <rosuav@gmail.com> - 2011-12-19 07:51 +1100
      Re: Newbie Question: Obtain element from list of tuples Roy Smith <roy@panix.com> - 2011-12-18 16:10 -0500
      Re: Newbie Question: Obtain element from list of tuples HoneyMonster <someone@someplace.invalid> - 2011-12-18 22:55 +0000
        Re: Newbie Question: Obtain element from list of tuples Chris Angelico <rosuav@gmail.com> - 2011-12-19 10:40 +1100
          Re: Newbie Question: Obtain element from list of tuples HoneyMonster <someone@someplace.invalid> - 2011-12-20 00:59 +0000

#17472 — Newbie Question: Obtain element from list of tuples

FromHoneyMonster <someone@someplace.invalid>
Date2011-12-18 19:41 +0000
SubjectNewbie Question: Obtain element from list of tuples
Message-ID<jclflh$u45$1@news.albasani.net>
Hi,

I'm just starting to learn Python, so please bear with me. I have in my 
program an object (recs) which is a list of tuples (returned as such by a 
database query).

My question is doubtless a very easy one to answer: Say I want the ninth 
element in the twentieth tuple put into variable PID, I can do this, 
bearing in mind that numbering starts at zero:

tup = recs[19]
PID = tup[8]

But there must be an easier way; i.e. to do it in one go without the 
extra variable. How do I achieve that please?

Secondly, I am more than happy to read the fine manuals. If someone could 
point me in the direction of one or two "for idiots" guides, that would 
be greatly appreciated.

[toc] | [next] | [standalone]


#17474

FromArnaud Delobelle <arnodel@gmail.com>
Date2011-12-18 19:49 +0000
Message-ID<mailman.3804.1324237776.27778.python-list@python.org>
In reply to#17472
On 18 December 2011 19:41, HoneyMonster <someone@someplace.invalid> wrote:
> Hi,
>
> I'm just starting to learn Python, so please bear with me. I have in my
> program an object (recs) which is a list of tuples (returned as such by a
> database query).
>
> My question is doubtless a very easy one to answer: Say I want the ninth
> element in the twentieth tuple put into variable PID, I can do this,
> bearing in mind that numbering starts at zero:
>
> tup = recs[19]
> PID = tup[8]
>
> But there must be an easier way; i.e. to do it in one go without the
> extra variable. How do I achieve that please?

Well, you were almost there:

pid = recs[19][8]

Note: all caps is usually reserved for constants in Python.

-- 
Arnaud

[toc] | [prev] | [next] | [standalone]


#17476

FromRoy Smith <roy@panix.com>
Date2011-12-18 15:04 -0500
Message-ID<roy-B739A1.15041318122011@news.panix.com>
In reply to#17472
In article <jclflh$u45$1@news.albasani.net>,
 HoneyMonster <someone@someplace.invalid> wrote:

> Hi,
> 
> I'm just starting to learn Python, so please bear with me. I have in my 
> program an object (recs) which is a list of tuples (returned as such by a 
> database query).

Sounds like a standard database interface -- each tuple represents one 
row in the query result.  Very common.

> My question is doubtless a very easy one to answer: Say I want the ninth 
> element in the twentieth tuple put into variable PID, I can do this, 
> bearing in mind that numbering starts at zero:
> 
> tup = recs[19]
> PID = tup[8]

Sure, you could do:

PID = recs[19][8]

That's shorter, but it probably not better.  Presumably, the tuple 
elements represent columns in the database.  It would make the code 
easier to read if you unpacked the tuple into something with 
human-readable names:

col_1, col_2, col_3, ...... col_n = recs[19]

and then use the name for the column of interest.  A common convention 
is that when you're unpacking a tuple (or a list, I suppose) and are 
only interested in some of the elements, you unpack the others into "_".  
Thus:

_, _, _, _, pid, _, _, _ = recs[19]

Of course, if you're going to do all that, you probably could have 
written a better query which returned just the column you were 
interested in.  Instead of "select * from foo", you could have done 
"select pid from foo" (assuming you're using some SQL-based database).

> Secondly, I am more than happy to read the fine manuals. If someone could 
> point me in the direction of one or two "for idiots" guides, that would 
> be greatly appreciated.

The on-line tutorial is pretty good.  
http://docs.python.org/tutorial/index.html

[toc] | [prev] | [next] | [standalone]


#17478

FromHoneyMonster <someone@someplace.invalid>
Date2011-12-18 20:22 +0000
Message-ID<jcli1s$6r3$1@news.albasani.net>
In reply to#17476
On Sun, 18 Dec 2011 15:04:13 -0500, Roy Smith wrote:

> In article <jclflh$u45$1@news.albasani.net>,
>  HoneyMonster <someone@someplace.invalid> wrote:
> 
>> Hi,
>> 
>> I'm just starting to learn Python, so please bear with me. I have in my
>> program an object (recs) which is a list of tuples (returned as such by
>> a database query).
> 
> Sounds like a standard database interface -- each tuple represents one
> row in the query result.  Very common.
> 
>> My question is doubtless a very easy one to answer: Say I want the
>> ninth element in the twentieth tuple put into variable PID, I can do
>> this, bearing in mind that numbering starts at zero:
>> 
>> tup = recs[19]
>> PID = tup[8]
> 
> Sure, you could do:
> 
> PID = recs[19][8]
> 
> That's shorter, but it probably not better.  Presumably, the tuple
> elements represent columns in the database.  It would make the code
> easier to read if you unpacked the tuple into something with
> human-readable names:
> 
> col_1, col_2, col_3, ...... col_n = recs[19]
> 
> and then use the name for the column of interest.  A common convention
> is that when you're unpacking a tuple (or a list, I suppose) and are
> only interested in some of the elements, you unpack the others into "_".
> Thus:
> 
> _, _, _, _, pid, _, _, _ = recs[19]
> 
> Of course, if you're going to do all that, you probably could have
> written a better query which returned just the column you were
> interested in.  Instead of "select * from foo", you could have done
> "select pid from foo" (assuming you're using some SQL-based database).
> 
>> Secondly, I am more than happy to read the fine manuals. If someone
>> could point me in the direction of one or two "for idiots" guides, that
>> would be greatly appreciated.
> 
> The on-line tutorial is pretty good.
> http://docs.python.org/tutorial/index.html

Thanks, Arnaud and Roy. I had no idea it could be so easy. I think I 
rather like Python!

OK, I'll change PID to pid if that's best practice.

Yes, it's an SQL-based database, PostgreSQL actually. I'm using psycopg2 
to access it and wxGlade to construct the GUI interface. It all seems to 
be progressing very smoothly.

Thanks again.

[toc] | [prev] | [next] | [standalone]


#17479

FromRoy Smith <roy@panix.com>
Date2011-12-18 15:25 -0500
Message-ID<roy-69CF7D.15250618122011@news.panix.com>
In reply to#17478
In article <jcli1s$6r3$1@news.albasani.net>,
 HoneyMonster <someone@someplace.invalid> wrote:

> I think I rather like Python!

+1 QOTD?

[toc] | [prev] | [next] | [standalone]


#17492

Fromalex23 <wuwei23@gmail.com>
Date2011-12-18 18:35 -0800
Message-ID<2c286dea-efba-45d5-85a7-a7503733575a@i6g2000vbe.googlegroups.com>
In reply to#17476
Roy Smith <r...@panix.com> wrote:
> A common convention
> is that when you're unpacking a tuple (or a list, I suppose) and are
> only interested in some of the elements, you unpack the others into "_".
> Thus:
>
> _, _, _, _, pid, _, _, _ = recs[19]

Pre-namedtuple, I used to like using named slices for this:

    cPID = slice(19)
    pid = recs[cPID]

    cHostPort = slice(99,100)
    host, port = recs[cHostPort]

etc.

The suggestions of having your query return a dictionary where
possible are the most ideal, but if it's not possible you can always
wrap the result tuple in a namedtuple:

    from collections import namedtuple

    Staff = namedtuple('Staff',
['firstname','lastname','age','position'])

    sql_result = ('John', 'Example', '30', 'Dummy')
    staff_record = Staff(sql_result)

    print staff_record.firstname, staff_record.age

[toc] | [prev] | [next] | [standalone]


#17494

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-12-19 03:00 +0000
Message-ID<4eeea8eb$0$11091$c3e8da3@news.astraweb.com>
In reply to#17492
On Sun, 18 Dec 2011 18:35:47 -0800, alex23 wrote:

> Pre-namedtuple, I used to like using named slices for this:
> 
>     cPID = slice(19)
>     pid = recs[cPID]

You know, that is an incredibly simple thing and yet it never dawned on 
me before now. Thank you for sharing that.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#17500

From"Frank Millman" <frank@chagford.com>
Date2011-12-19 08:46 +0200
Message-ID<mailman.3815.1324277206.27778.python-list@python.org>
In reply to#17494
"Steven D'Aprano" <steve+comp.lang.python@pearwood.info> wrote in message 
news:4eeea8eb$0$11091$c3e8da3@news.astraweb.com...
> On Sun, 18 Dec 2011 18:35:47 -0800, alex23 wrote:
>
>> Pre-namedtuple, I used to like using named slices for this:
>>
>>     cPID = slice(19)
>>     pid = recs[cPID]
>
> You know, that is an incredibly simple thing and yet it never dawned on
> me before now. Thank you for sharing that.
>

I also like it, but it does not work quite so simply for me.

>>> row = tuple(range(20))
>>> cPID = slice(15)
>>> pid = row[cPID]
>>> pid
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
>>>

This works -

>>> row = tuple(range(20))
>>> cPID = slice(15, 16)
>>> pid, = row[cPID]  # note the trailing comma
>>> pid
15
>>>

Still nice, but not quite so elegant.

Am I missing something?

Frank Millman

[toc] | [prev] | [next] | [standalone]


#17513

FromDevPlayer <devplayer@gmail.com>
Date2011-12-19 07:37 -0800
Message-ID<ebd6cc29-c66e-47be-a028-83c4beb8a277@n6g2000vbz.googlegroups.com>
In reply to#17500
On Dec 19, 1:46 am, "Frank Millman" <fr...@chagford.com> wrote:
> "Steven D'Aprano" <steve+comp.lang.pyt...@pearwood.info> wrote in message
>
> news:4eeea8eb$0$11091$c3e8da3@news.astraweb.com...
>
> > On Sun, 18 Dec 2011 18:35:47 -0800, alex23 wrote:
>
> >> Pre-namedtuple, I used to like using named slices for this:
>
> >>     cPID = slice(19)
> >>     pid = recs[cPID]
>
> > You know, that is an incredibly simple thing and yet it never dawned on
> > me before now. Thank you for sharing that.
>
> I also like it, but it does not work quite so simply for me.
>
> >>> row = tuple(range(20))
> >>> cPID = slice(15)
> >>> pid = row[cPID]
> >>> pid
>
> (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
>
>
>
> This works -
>
>
>
> >>> row = tuple(range(20))
> >>> cPID = slice(15, 16)
> >>> pid, = row[cPID]  # note the trailing comma
> >>> pid
> 15
>
> Still nice, but not quite so elegant.
>
> Am I missing something?
>
> Frank Millman

if you're going to do:
> >>> cPID = slice(15, 16)
> >>> pid, = row[cPID]  # note the trailing comma

Why not just:
>>>row = tuple(range(20))
>>>cPID = 15 # a proposed constant
>>>pid = row[cPID]
>>>pid
15

It might be better for other's to debug if you use
>>> pid, _ = row[cPID]
as a little tiny comma like that is easy to miss in some text editors.
Not everyone has large LCD screens. Not that I like the "_" for this
purpose.

Personally I'd love to see the "_" used instead of "self" as a common
practice (useful when you use lots of "self...." on a line).

[toc] | [prev] | [next] | [standalone]


#17549

Fromalex23 <wuwei23@gmail.com>
Date2011-12-19 19:53 -0800
Message-ID<0b32499a-5e7d-4fb6-a790-df28bd05d887@s5g2000vbj.googlegroups.com>
In reply to#17500
On Dec 19, 4:46 pm, "Frank Millman" <fr...@chagford.com> wrote:
> Am I missing something?

No, I seem to be. I have _no_ idea how I got that original syntax to
work :|

My apologies, DevPlayer's suggestion is much more sensible, although
slices are still handy when dealing with groups of values.

[toc] | [prev] | [next] | [standalone]


#17480

FromChris Angelico <rosuav@gmail.com>
Date2011-12-19 07:51 +1100
Message-ID<mailman.3807.1324241477.27778.python-list@python.org>
In reply to#17472
On Mon, Dec 19, 2011 at 6:41 AM, HoneyMonster <someone@someplace.invalid> wrote:
> My question is doubtless a very easy one to answer: Say I want the ninth
> element in the twentieth tuple put into variable PID, I can do this,
> bearing in mind that numbering starts at zero:
>
> tup = recs[19]
> PID = tup[8]
>
> But there must be an easier way; i.e. to do it in one go without the
> extra variable. How do I achieve that please?

The specific answer has already been given, but I'd like to fill in
the generality. In Python, everything's an object; if you can do
something with a variable, you can do it with an expression too. I
don't know what your function call is to obtain your record list, but
imagine it's:

recs = conn.query("SELECT * FROM some_table")

Then you can actually do all of this in a single statement. It's not
usually what you'll want to do, but this is legal:

pid = conn.query("SELECT * FROM some_table")[19][8]

If you're absolutely certain that you'll always get precisely one
value from a query, this becomes rather more useful:

mode = conn.query("SELECT mode FROM config WHERE id=5")[0][0]

In any case: You can work with a function's return value directly,
without first storing it in a temporary variable.

Hope that helps!

Chris Angelico

[toc] | [prev] | [next] | [standalone]


#17481

FromRoy Smith <roy@panix.com>
Date2011-12-18 16:10 -0500
Message-ID<roy-78470D.16102518122011@news.panix.com>
In reply to#17480
In article <mailman.3807.1324241477.27778.python-list@python.org>,
 Chris Angelico <rosuav@gmail.com> wrote:

> If you're absolutely certain that you'll always get precisely one
> value from a query, this becomes rather more useful:
> 
> mode = conn.query("SELECT mode FROM config WHERE id=5")[0][0]

Although, if you're going to do that, you might as well take advantage 
of the fetchone() method that most Python database APIs have and 
eliminate one of the indexes.  Typical code would be something like:

cursor.execute("SELECT mode FROM config WHERE id=5")
mode = cursor.fetchone()[0]

If you're going to be doing any database work in Python, you should be 
familiar with the Python Database API Specification, 
http://www.python.org/dev/peps/pep-0249/.  Most of the vendor-specific 
database modules have interfaces which hold pretty close to the style 
described there.

You might also want to explore SQL_Alchemy.  I personally find it 
difficult and painful to work with, but it does have the powerful 
advantage that it abstracts away all the vendor-specific differences 
between databases.

[toc] | [prev] | [next] | [standalone]


#17482

FromHoneyMonster <someone@someplace.invalid>
Date2011-12-18 22:55 +0000
Message-ID<jclr1a$kjn$2@news.albasani.net>
In reply to#17480
On Mon, 19 Dec 2011 07:51:08 +1100, Chris Angelico wrote:

> On Mon, Dec 19, 2011 at 6:41 AM, HoneyMonster
> <someone@someplace.invalid> wrote:
>> My question is doubtless a very easy one to answer: Say I want the
>> ninth element in the twentieth tuple put into variable PID, I can do
>> this, bearing in mind that numbering starts at zero:
>>
>> tup = recs[19]
>> PID = tup[8]
>>
>> But there must be an easier way; i.e. to do it in one go without the
>> extra variable. How do I achieve that please?
> 
> The specific answer has already been given, but I'd like to fill in the
> generality. In Python, everything's an object; if you can do something
> with a variable, you can do it with an expression too. I don't know what
> your function call is to obtain your record list, but imagine it's:
> 
> recs = conn.query("SELECT * FROM some_table")
> 
> Then you can actually do all of this in a single statement. It's not
> usually what you'll want to do, but this is legal:
> 
> pid = conn.query("SELECT * FROM some_table")[19][8]
> 
> If you're absolutely certain that you'll always get precisely one value
> from a query, this becomes rather more useful:
> 
> mode = conn.query("SELECT mode FROM config WHERE id=5")[0][0]
> 
> In any case: You can work with a function's return value directly,
> without first storing it in a temporary variable.
> 
> Hope that helps!

Thanks, Chris. Actually I had simplified the question somewhat. The 
actuality is indeed - as you suspected - that recs = conn.query("SELECT * 
FROM some_table") but I am then using the recs object to populate a (non 
editable) wxGrid.

When the user selects a row and clicks a button, I am using:
pos = self.grid_1.GetGridCursorRow() to establish which tuple in recs is 
involved, and then pid = recs[pos][4] to determine the key value (I 
suspected that accessing recs directly would be more efficient that 
trying to determine the wxGrid column value, and in any case the pid is 
in recs but not in the wxGrid).

I trust this all makes sense. Thanks again.

[toc] | [prev] | [next] | [standalone]


#17483

FromChris Angelico <rosuav@gmail.com>
Date2011-12-19 10:40 +1100
Message-ID<mailman.3808.1324251610.27778.python-list@python.org>
In reply to#17482
On Mon, Dec 19, 2011 at 9:55 AM, HoneyMonster <someone@someplace.invalid> wrote:
> When the user selects a row and clicks a button, I am using:
> pos = self.grid_1.GetGridCursorRow() to establish which tuple in recs is
> involved, and then pid = recs[pos][4] to determine the key value (I
> suspected that accessing recs directly would be more efficient that
> trying to determine the wxGrid column value, and in any case the pid is
> in recs but not in the wxGrid).

Yep, this looks like a sensible way to do it!

I would recommend, though, that you avoid "magic numbers" - the
process ID might happen to be in cell 4, but what if your column list
changes? This is especially problematic when you use "select * from
table", because changes outside your code can break things.

There's two solutions. One is to carefully match your SELECT statement
to a set of constants:

exec("SELECT FOO,BAR,QUUX,ASDF,PID,WHATEVER FROM table")
FOO,BAR,QUUX,ASDF,PID,WHATEVER,*_=range(20) # Cool trick to avoid
having to count the columns

But a better way is to let the database handle it. Check your
interface library to see if you can have it return dictionaries or
objects instead of tuples - then you could use:

pid = recs[pos]["pid"]
# or
pid = recs[pos]->pid

which avoids the need to count columns at all.

Other than that, though, yep - your code concept looks fine.

ChrisA

[toc] | [prev] | [next] | [standalone]


#17534

FromHoneyMonster <someone@someplace.invalid>
Date2011-12-20 00:59 +0000
Message-ID<jcomlk$6m9$1@news.albasani.net>
In reply to#17483
On Mon, 19 Dec 2011 10:40:06 +1100, Chris Angelico wrote:

> On Mon, Dec 19, 2011 at 9:55 AM, HoneyMonster
> <someone@someplace.invalid> wrote:
>> When the user selects a row and clicks a button, I am using:
>> pos = self.grid_1.GetGridCursorRow() to establish which tuple in recs
>> is involved, and then pid = recs[pos][4] to determine the key value (I
>> suspected that accessing recs directly would be more efficient that
>> trying to determine the wxGrid column value, and in any case the pid is
>> in recs but not in the wxGrid).
> 
> Yep, this looks like a sensible way to do it!
> 
> I would recommend, though, that you avoid "magic numbers" - the process
> ID might happen to be in cell 4, but what if your column list changes?
> This is especially problematic when you use "select * from table",
> because changes outside your code can break things.
> 
> There's two solutions. One is to carefully match your SELECT statement
> to a set of constants:
> 
> exec("SELECT FOO,BAR,QUUX,ASDF,PID,WHATEVER FROM table")
> FOO,BAR,QUUX,ASDF,PID,WHATEVER,*_=range(20) # Cool trick to avoid having
> to count the columns
> 
> But a better way is to let the database handle it. Check your interface
> library to see if you can have it return dictionaries or objects instead
> of tuples - then you could use:
> 
> pid = recs[pos]["pid"]
> # or pid = recs[pos]->pid
> 
> which avoids the need to count columns at all.
> 
> Other than that, though, yep - your code concept looks fine.

Thanks again, Chris. I'm completely new to Python, but am an old had at 
databases. I *never* use "select *" in a production environment; rather 
an explicit list of columns. Thus it doesn't matter if a column is added 
to the table, nor if the column order in the table is changed.

But I have used this at the start if my code to make it more readable 
anyway:

# Define constants (position in tuple)
Title = 0
Episode = 1
Categories = 2
Channel = 3
PID = 4
Index = 5

so that in the bit where I populate the grid, the code is now:

cnt = 0
for tup in recs:
    self.grid_1.SetCellValue(cnt, Title, tup[Title])
    self.grid_1.SetCellValue(cnt, Episode, tup[Episode])
    self.grid_1.SetCellValue(cnt, Categories, tup[Categories])
    self.grid_1.SetCellValue(cnt, Channel, tup[Channel])
    cnt = cnt + 1

just so that is more legible.

Cheers,
HM

[toc] | [prev] | [standalone]


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


csiph-web