I am getting new_tag from a form text field with self.response.get("new_tag") and selected_tags from checkbox fields with
self.response.get_all("selected_tags")
I combine them like this:
tag_string = new_tag
new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)
(f1.striplist is a function that strips white spaces inside the strings in the list.)
But in the case that tag_list is empty (no new tags are entered) but there are some selected_tags, new_tag_list contains an empty string " ".
For example, from logging.info:
new_tag
selected_tags[u'Hello', u'Cool', u'Glam']
new_tag_list[u'', u'Hello', u'Cool', u'Glam']
How do I get rid of the empty string?
If there is an empty string in the list:
>>> s = [u'', u'Hello', u'Cool', u'Glam']
>>> i = s.index("")
>>> del s[i]
>>> s
[u'Hello', u'Cool', u'Glam']
But if there is no empty string:
>>> s = [u'Hello', u'Cool', u'Glam']
>>> if s.index(""):
i = s.index("")
del s[i]
else:
print "new_tag_list has no empty string"
But this gives:
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
if new_tag_list.index(""):
ValueError: list.index(x): x not in list
Why does this happen, and how do I work around it?
1) Almost-English style:
Test for presence using the
inoperator, then apply theremovemethod.The
removemethod will remove only the first occurrence ofthing, in order to remove all occurrences you can usewhileinstead ofif.2) Duck-typed, EAFP style:
This shoot-first-ask-questions-last attitude is common in Python. Instead of testing in advance if the object is suitable, just carry out the operation and catch relevant Exceptions:
Off course the second except clause in the example above is not only of questionable humor but totally unnecessary (the point was to illustrate duck-typing for people not familiar with the concept).
If you expect multiple occurrences of thing:
However, with contextlib’s suppress() contextmanager (introduced in python 3.4) the above code can be simplified to this:
Again, if you expect multiple occurrences of thing:
3) Functional style:
Around 1993, Python got
lambda,reduce(),filter()andmap(), courtesy of a Lisp hacker who missed them and submitted working patches*. You can usefilterto remove elements from the list:There is a shortcut that may be useful for your case: if you want to filter out empty items (in fact items where
bool(item) == False, likeNone, zero, empty strings or other empty collections), you can pass None as the first argument:filter(function, iterable)used to be equivalent to[item for item in iterable if function(item)](or[item for item in iterable if item]if the first argument isNone); in Python 3.x, it is now equivalent to(item for item in iterable if function(item)). The subtle difference is that filter used to return a list, now it works like a generator expression – this is OK if you are only iterating over the cleaned list and discarding it, but if you really need a list, you have to enclose thefilter()call with thelist()constructor.filter– along with companionsmapandreduce(they are not gone yet butreducewas moved into the functools module, which is worth a look if you like high order functions).4) Mathematical style:
List comprehensions became the preferred style for list manipulation in Python since introduced in version 2.0 by PEP 202. The rationale behind it is that List comprehensions provide a more concise way to create lists in situations where
map()andfilter()and/or nested loops would currently be used.Generator expressions were introduced in version 2.4 by PEP 289. A generator expression is better for situations where you don’t really need (or want) to have a full list created in memory – like when you just want to iterate over the elements one at a time. If you are only iterating over the list, you can think of a generator expression as a lazy evaluated list comprehension:
Notes
!=instead ofis not(the difference is important)