It's just a double list comprehension, it's a lot simpler if you think of it like this:
print [a for a in "abc"] # ['a', 'b', 'c']
If you do two for ... in ...
things in there, it's just like a nested loop;
result = [XXX for a in as for b in bs for c in cs...]
where XXX
is a function of the a
, b
, c
, ... elements of the various containers you have used (this parts after the 'in
's) translates to:
result = []
for a in as:
for b in bs:
for c in cs:
...#however much nesting you want
result.append(XXX)
You can see this by swapping the orders around:
print [a+b for a in "ab" for b in "xy"] # ax ay bx by
print [a+b for b in "xy" for a in "ab"] # ax bx ay by
Now for your actual example:
for i in range(length):
result = [str(x)+str(y) for x in alphabet for y in result or ['']]
this just follows the same rules as above, but there is one extra little hitch; the `result or ['']` part. It is possible to have `if ... else ...` style constructs in list comprehensions, though you'll probably want to avoid those for now. That is *not* what's happening here though, the code is a little clearer if you change it to this:
for i in range(length):
result = [str(x)+str(y) for x in alphabet for y in (result or [''])]
Essentially, it's taking advantage of the fact that []
(i.e. empty list) counts as False
when cast to a bool*. So if the list is empty, it will be replaced with ['']
. The reason this is necessary, is that if result is an empty string (or array), no iterations through the for
loop will happen - an array containing an empty string works just fine though, as it has one element (an empty string) in it.
It is case to a bool
because the or
operator is used. If you do something like this:
a = var1 or var2
then afterwards, a
will be var1
- unless it is one of the objects which counts as False
;
print False or "other" # other
print None or "other" # other
print True or "other" # True
print "" or "other" # other
print " " or "other" # ' '
print 0 or "other" # other
print 1 or "other" # 1
print 134513456 or "other" # 134513456
print [] or "other" # other
print [0] or "other" # [0]
...
I'm sure you get the picture.
The other potentially confusing aspect of the code you had was that it setting the variable result
, while using the same variable inside the list comprehension. This is okay, because the variable doesn't get set until the list comprehension has completed.
So to convert it into something using normal loops:
for i in range(length):
result = [str(x)+str(y) for x in alphabet for y in result or ['']]
result = [""]
for i in range(length):
temporary_result = []
for original_sequence in result:
for new_letter in alphabet:
temporary_result.append(original_sequence + new_letter)
result = temporary_result[:]
where the [:]
is a simple way of copying an array.