Extracting item from list of tuples?

R

Roy Smith

I'm using httplib, and want to get the Location header from the
response. The getheaders() method gives you back a list of (name,
value) tuples. It would be a lot more convenient if it gave you back a
dict, but it is what it is.

Anyway, I came up with:

location = [t[1] for t in headers if t[0] == 'location'][0]

which works, but is getting on towards the cryptic end of things. Is
there a better idiom for this?
 
P

Philip Semanchuk

I'm using httplib, and want to get the Location header from the
response. The getheaders() method gives you back a list of (name,
value) tuples. It would be a lot more convenient if it gave you
back a
dict, but it is what it is.

Anyway, I came up with:

location = [t[1] for t in headers if t[0] == 'location'][0]

which works, but is getting on towards the cryptic end of things. Is
there a better idiom for this?

Are you concerned about efficiency? If it's not important, being less
terse would make it less cryptic:
location = None
for name, value in headers:
if name == "location":
location = value
break

If you prefer terse, IMHO this is less cryptic (but untested):

location = [value for name, value in headers if name == 'location']
[0]


Be careful if you decide to turn the list of tuples into a dictionary.
HTTP headers can repeat and straightforward code to turn the (name,
value) pairs into a dict could end up overwriting data.

Cheers
P
 
P

Peter Otten

Philip said:
I'm using httplib, and want to get the Location header from the
response. The getheaders() method gives you back a list of (name,
value) tuples. It would be a lot more convenient if it gave you
back a
dict, but it is what it is.

Anyway, I came up with:

location = [t[1] for t in headers if t[0] == 'location'][0]

which works, but is getting on towards the cryptic end of things. Is
there a better idiom for this?

Are you concerned about efficiency? If it's not important, being less
terse would make it less cryptic:
location = None
for name, value in headers:
if name == "location":
location = value
break

This is actually more efficient because unlike Roy's (and your other
solution) it doesn't build a list, and it doesn't waste cycles in the loop
once the location is found. You can write it as a generator expression like
so:

location = next((value for name, value in headers if name == "location"),
None)

But just converting the headers to a dict is clearer and probably even
faster because it moves the loop from Python to C.
If you prefer terse, IMHO this is less cryptic (but untested):

location = [value for name, value in headers if name == 'location']
[0]


Be careful if you decide to turn the list of tuples into a dictionary.
HTTP headers can repeat and straightforward code to turn the (name,
value) pairs into a dict could end up overwriting data.
 
P

Philip Semanchuk

Philip said:
I'm using httplib, and want to get the Location header from the
response. The getheaders() method gives you back a list of (name,
value) tuples. It would be a lot more convenient if it gave you
back a
dict, but it is what it is.

Anyway, I came up with:

location = [t[1] for t in headers if t[0] == 'location'][0]

which works, but is getting on towards the cryptic end of things.
Is
there a better idiom for this?

Are you concerned about efficiency? If it's not important, being less
terse would make it less cryptic:
location = None
for name, value in headers:
if name == "location":
location = value
break

This is actually more efficient because unlike Roy's (and your other
solution) it doesn't build a list, and it doesn't waste cycles in
the loop
once the location is found.

Upon further reflection, though, I realize that my solution is not
equivalent to the original. In the case of duplicated headers, the
original would return the last value of the location header, my code
would return the first. For the HTTP Location header this is only a
theoretical problem because the HTTP spec doesn't provide for sending
more than one.

However if this code were made into a function for retrieving the
value of an arbitrary header (as seems likely), one would have to
decide how to handle repeating headers. Neither my code nor the
original handle that possibility. Nor does a naive conversion into a
dict, as I mentioned before.

Cheers
P
You can write it as a generator expression like
so:

location = next((value for name, value in headers if name ==
"location"),
None)

But just converting the headers to a dict is clearer and probably even
faster because it moves the loop from Python to C.
If you prefer terse, IMHO this is less cryptic (but untested):

location = [value for name, value in headers if name ==
'location']
[0]


Be careful if you decide to turn the list of tuples into a
dictionary.
HTTP headers can repeat and straightforward code to turn the (name,
value) pairs into a dict could end up overwriting data.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,961
Messages
2,570,131
Members
46,689
Latest member
liammiller

Latest Threads

Top