This feels like one of those python weird things. I am interested in explanations.
If I have a list=[1,2,3,4] and I do list.pop() the result is list=[1,2,3].
Perfect, just what I wanted.
However, if I am not careful and instead do list.pop--note there are no parentheses this time--I get no syntax error or warning and nothing happens, leading me to a strange debug session.
In the repl, if I do l.pop it just identifies it as a built-in method of list object at 0xwhatever. That's useful, but why is there not at least a runtime warning when I make this mistake in my code?
Videos
Are your lists large? If so, use ifilter from itertools to filter out elements that you don't want lazily (with no up front cost).
Lists not so large? Just use a list comprehension:
newlist = [x for x in oldlist if x not in ['a', 'c'] ]
This will create a new copy of the list. This is not generally an issue for efficiency unless you really care about memory consumption.
As a happy medium of syntax convenience and laziness ( = efficiency for large lists), you can construct a generator rather than a list by using ( ) instead of [ ]:
interestingelts = (x for x in oldlist if x not in ['a', 'c'])
After this, you can iterate over interestingelts, but you can't index into it:
for y in interestingelts: # ok
print y
print interestingelts[0] # not ok: generator allows sequential access only
You want a list comprehension:
L = [c for c in L if c not in ['a', 'c']]
Or, if you really don't want to create a copy, go backwards:
for i in reversed(range(len(L))):
if L[i] in ['a', 'c']:
L.pop(i) # del L[i] is more efficient
Thanks to ncoghlan for reversed() & phooji for del L[i] suggestions. (I decided to leave it as L.pop(i), since that's how the question was initially formulated.)
Also, as J.S. Sebastian correctly points out, going backwards is space efficient but time inefficient; most of the time a list comprehension or generator (L = (...) instead of L = [...]) is best.
Edit:
Ok, so since people seem to want something less ridiculously slow than the reversed method above (I can't imagine why... :) here's an order-preserving, in-place filter that should differ in speed from a list comprehension only by a constant. (This is akin to what I'd do if I wanted to filter a string in c.)
write_i = 0
for read_i in range(len(L)):
L[write_i] = L[read_i]
if L[read_i] not in ['a', 'c']:
write_i += 1
del L[write_i:]
print L
# output: ['b', 'd']