images = [ ] for filename in filenames:
Because otherwise without it, if you either refer to it in the loop, it won't exist so you'll get an error. Or if you define it in the loop, you'll redefine it every iteration, destroying all the progress added to it from every previous iteration.
Why do you need to hold an empty cup before pouring water into it?
Based on the other answers, I think the cleanest solutions are
#Handles None return from get_list
for item in get_list() or []:
pass #do something
or the comprehension equiv
result = [item*item for item in get_list() or []]
Use a list comprehension:
def do_something(x):
return x**2
things = []
result = [do_something(x) for x in things]
print result # []
things = [1, 2, 3]
result = [do_something(x) for x in things]
print result # [1, 4, 9]
Videos
The thing that I think you're missing here is that the StopIteration is what actually makes the for loop stop. This is why you can write custom iterators that work with Python's for loop transparently. It doesn't do any checking to see if the iterator is empty, and the for loop does not keep track of of the iterator's state. This is an effect of the iterator protocol, and was an intentional choice in the language design. You can read more about the iterator protocol on Python's docs site if you want to.
It also makes more sense if you think about the number of items in e.g. your list corresponding directly to the number of times your loop is executed.
-----------------------------------|
| No. of items | No. times executed|
------------------------------------
| 5 | 5 |
| 4 | 4 |
| 3 | 3 |
| 2 | 2 |
| 1 | 1 |
| 0 | 0 |
------------------------------------
If the for loop special-cased an empty iterable, this invariant would be lost.
It would also complicate the protocol on writing custom iterators, because you would have to have an extra method to signal to the for loop that your iterable is empty before the iteration began.
Here's a (stupid) example of a custom iterator that always acts like it's empty:
class EmptyIterator():
def __iter__(self): return self
def __next__(self): raise StopIteration
for blah in EmptyIterator():
print('this is never reached')
try:
next(EmptyIterator())
except StopIteration:
print('Oh hi, I was empty so I raised this Exception for you.')
This is odd to me. Why should an empty collection be treated any differently?
Forcing the programmer to check if the collection is empty before doing things to it would be a widespread, problematic sort of burden. Worse, an empty collection is in no way exceptional.
Personally, I would rather have the occasional bug where a no-op happened because I forgot to check for the rare case where I wanted different behavior on an empty collection rather than the occasional bug where an exception crashes my app because I forgot to say if empty, do nothing everywhere I wanted that common, expected behavior.
I mean, do you think printing empty strings should throw exceptions?
Not my code, but if we look here, we see that time is used to create this "empty list".
% python -mtimeit "l=[]"
10000000 loops, best of 3: 0.0711 usec per loop
% python -mtimeit "l=list()"
1000000 loops, best of 3: 0.297 usec per loop
As far as actually iterating through the list, yes, this costs resources as well. The interpretter has to at least know that the list is empty, so it must go into the memory location to see that it is empty.
If you're asking if the Python interpreter is able to optimize by skipping the loop entirely, I think the answer is no. If you look at bytecode for iteration over an empty list, all the loop setup steps are still done and bytecode is generated for the code inside the loop (although it won't actually be executed):
import dis
def run_empty_loop():
a = []
for item in a:
x = 1 + 1
dis.dis(run_empty_loop)
2 0 BUILD_LIST 0
3 STORE_FAST 0 (a)
3 6 SETUP_LOOP 20 (to 29)
9 LOAD_FAST 0 (a)
12 GET_ITER
>> 13 FOR_ITER 12 (to 28)
16 STORE_FAST 1 (item)
4 19 LOAD_CONST 2 (2)
22 STORE_FAST 2 (x)
25 JUMP_ABSOLUTE 13
>> 28 POP_BLOCK
>> 29 LOAD_CONST 0 (None)
32 RETURN_VALUE
You'll have to stick with the if statement, but it can be simplified:
for x in my_list:
doSomething()
if not my_list:
print "my_list is empty"
since my_list is empty, the for loop never executes the loop portion, and an empty list is False in a boolean context.
if you are sure that the iterator is not returning a specific value, say None or False, then you can
x = False
for x in my_list:
doSomething(x)
if x is False:
print "my_list is empty"
Your output=[] is inside your for loop. So at each iteration, its value is reinitialized, you should try again with output=[] before the for loop
Your output list is empty when you return it because every time the for loop restarts you reset the list.
Your code should look like this:
messages = {
"Placeholder": 0,
"1": 48,
"2": 4,
"3": 31,
"4": 2
}
def pls():
messages_sorted = sorted(messages, key=messages.get, reverse=True)
output = []
for i in range(10):
try:
currp = str(messages_sorted[i])
if currp == "Placeholder":
print("PLACEHOLDER DETECTED")
return output
currpp = messages[currp]
output.append(f"{currp} has {currpp} and is Place {i+1}")
print(output)
except IndexError:
print("Index error")
except:
print("some other error")
return output
output = pls()
output = str(output)
output = output.replace("['", "")
output = output.replace("']", "")
print(output)
The problem is that you are modifying the list czynniki while iterating over it. Try this instead:
print n, ' = ',
for czynnik in sorted(set(czynniki)):
if czynniki.count(czynnik)>1:
print czynnik, '^', czynniki.count(czynnik), '*',
else:
print czynnik, '*',
Here you iterate over a separate list of only unique items of your list czynniki. This is achieved by casting the list to a set (an unsorted list of unique items) and then back to a sorted list.
If you want to get rid of that surplus * at the end, you could try this:
result_list = []
for czynnik in sorted(set(czynniki)):
if czynniki.count(czynnik)>1:
result_list.append(str(czynnik) + '^' + str(czynniki.count(czynnik)))
else:
result_list.append(str(czynnik))
print n, '=', ' * '.join(result_list)
You're starting the for loop over the list that is stored in czynniki, that you're later changing what czynniki references (a totally new list) does not change which list the for loops over. It's not safe to change the actual list a loop is running over either, so you can't really do it like this either way.
You may want to rewrite the loop something like this, just skip the duplicate values instead and not try to change the loop while running;
var lastvalue = -1;
for czynnik in czynniki:
if lastvalue == czynnik:
continue
if czynniki.count(czynnik)>1:
print czynnik, '^', czynniki.count(czynnik), ' *',
lastvalue = czynnik
else:
print czynnik, ' *',
Your end criteria must be formulated a little differently: run the loop while there are items and the bucket is positive. or is not the right operation here.
while unpaid_sales and bucket > 0:
unpaid_sale = unpaid_sales.pop(0)
#do stuff
Do not use separate whileloops. Do as follows :
while unpaid_sales and bucket > 0 :
unpaid_sale = unpaid_sales.pop(0)
...do stuff