13

Consider this code

description = ""
desc = hxs.select('/html/head/meta[2]/@content').extract()
if len(desc) > 0:
    description = desc[0]       
item["description"] = description

desc is a list of strings. If list is empty description is an empty string, if not it's the first elements from the list. How to make it more pythonic?

Forgot to mention that I have to use 2.7

4 Answers 4

17

Alternately you could use make use of the fact that next supports a default

item["description"]  = next(iter(desc), "")
Sign up to request clarification or add additional context in comments.

2 Comments

To those that are wondering what is iterable in Python
Note that this is not idempotent. (Meaning that next() will only return the first element the first time it is called).
13

You can write:

desc = hxs.select("/html/head/meta[2]/@content").extract()
item["description"] = desc[0] if len(desc) > 0 else ""

As pointed out in the comments below, you can also directly evaluate the list in a boolean context:

item["description"] = desc[0] if desc else ""

10 Comments

if len(desc) > 0 could be replaced by if len(desc).
@WaleedKhan or just if desc, since empty lists are falsy.
Or item["description"] = desc and desc[0] or "" if this needs to work on earlier pythons that would choke on the 'else' part.
@tdelaney, version 2.5, to be specific.
@FrédéricHamidi: But you're being explicit about the wrong thing. You care about the emptiness of the list, not the length; the fact that using the length to check the emptiness might be the fastest way to do that is irrelevant. (And the fact that it might not means it may even be harmful.)
|
1

You can use exception handling (although it's more verbose than using the conditional expression).

desc = hxs.select('/html/head/meta[2]/@content').extract()
try:
    description = desc[0]
except IndexError:
    description = ""

2 Comments

It may be more verbose, but that doesn't mean it's worse. As the docs say: "This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C."
In this case, both approaches are so simple and readable that I would probably choose the conditional expression as the shorter approach :)
0

I don't think you should actually do this in your case, but for completeness…

For an iterator that might be empty, you just use the optional default value for next:

desc = foo.finditer(bar)
item["description"] = next(desc, "")

Meanwhile, you can always use iter() to "peek" at the iterator you would get from a sequence (or other non-iterator iterable).

So:

desc = foo.findall(bar)
item["description"] = next(iter(desc), "")

I think this is less readable than just using the list as a sequence (whether you use chepner's EAFP answer or Frédéric Hamidi's LYBL) rather than just an iterable. After all, we have the sequence API for a reason.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.