for
StatementsThe for
statement in Python differs a bit from what you may be used to in C or Pascal. Rather than always iterating over an arithmetic progression of numbers (like in Pascal), or giving the user the ability to define both the iteration step and halting condition (as C), Python’s for
statement iterates over the items of any sequence (a list or a string), in the order that they appear in the sequence. For example (no pun intended):
>>> # Measure some strings:
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12
If you need to modify the sequence you are iterating over while inside the loop (for example to duplicate selected items), it is recommended that you first make a copy. Iterating over a sequence does not implicitly make a copy. The slice notation makes this especially convenient:
>>> for w in words[:]: # Loop over a slice copy of the entire list.
... if len(w) > 6:
... words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']
With for w in words:
, the example would attempt to create an infinite list, inserting defenestrate over and over again.
range()
FunctionIf you do need to iterate over a sequence of numbers, the built-in function range()
comes in handy. It generates arithmetic progressions:
>>> for i in range(5):
... print(i)
...
0
1
2
3
4
The given end point is never part of the generated sequence; range(10)
generates 10 values, the legal indices for items of a sequence of length 10. It is possible to let the range start at another number, or to specify a different increment (even negative; sometimes this is called the ‘step’):
range(5, 10) # includes 5, 6, 7, 8, 9
range(0, 10, 3) # includes 0, 3, 6, 9
range(-10, -100, -30) # includes -10, -40, -70
To iterate over the indices of a sequence, you can combine range()
and len()
as follows:
>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
... print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb
In most such cases, however, it is convenient to use the enumerate()
function, see Looping Techniques.
A strange thing happens if you just print a range:
>>> print(range(10))
range(0, 10)
In many ways the object returned by range()
behaves as if it is a list, but in fact it isn’t. It is an object which returns the successive items of the desired sequence when you iterate over it, but it doesn’t really make the list, thus saving space.
We say such an object is iterable, that is, suitable as a target for functions and constructs that expect something from which they can obtain successive items until the supply is exhausted. We have seen that the for
statement is such a construct, while an example of a function that takes an iterable is sum()
:
>>> sum(range(4)) # 0 + 1 + 2 + 3
6
We say such an object is iterable, that is, suitable as a target for
functions and constructs that expect something from which they can obtain successive items until the supply is exhausted. We have seen that the for
statement is such an iterator. The function list()
is another; it creates lists from iterables:
>>> list(range(5))
[0, 1, 2, 3, 4]
Python knows a number of compound data types, used to group together other values. The most versatile is the list, which can be written as a list of comma-separated values (items) between square brackets. Lists might contain items of different types, but usually the items all have the same type.
>>> squares = [1, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]
Like strings (and all other built-in sequence types), lists can be indexed and sliced:
>>> squares[0] # indexing returns the item
1
>>> squares[-1]
25
>>> squares[-3:] # slicing returns a new list
[9, 16, 25]
All slice operations return a new list containing the requested elements. This means that the following slice returns a new (shallow) copy of the list:
>>> squares[:]
[1, 4, 9, 16, 25]
Lists also support operations like concatenation:
>>> squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Unlike strings, which are immutable, lists are a mutable type, i.e. it is possible to change their content:
>>> cubes = [1, 8, 27, 65, 125] # something's wrong here
>>> 4 ** 3 # the cube of 4 is 64, not 65!
64
>>> cubes[3] = 64 # replace the wrong value
>>> cubes
[1, 8, 27, 64, 125]
You can also add new items at the end of the list, by using the append() method (we will see more about methods later):
>>> cubes.append(216) # add the cube of 6
>>> cubes.append(7 ** 3) # and the cube of 7
>>> cubes
[1, 8, 27, 64, 125, 216, 343]
Assignment to slices is also possible, and this can even change the size of the list or clear it entirely:
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> # replace some values
>>> letters[2:5] = ['C', 'D', 'E']
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> # now remove them
>>> letters[2:5] = []
>>> letters
['a', 'b', 'f', 'g']
>>> # clear the list by replacing all the elements with an empty list
>>> letters[:] = []
>>> letters
[]
The built-in function len()
also applies to lists:
>>> letters = ['a', 'b', 'c', 'd']
>>> len(letters)
4
It is possible to nest lists (create lists containing other lists), for example:
>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'
Q: It is now known that a = [1, 2, 3, 4, 5, 6] reverses the list ([6, 5, 4, 3, 2, 1]) in a variety of ways and writes out the derivation process.
# method 1
a = [i for i in range(1, 7)]
a = a[::-1]
print(a)
# method 2
a = [i for i in range(1, 7)]
a.reverse()
print(a)
# method 3
a = [i for i in range(1, 7)]
a = [7-i for i in a]
print(a)
# method 4
a = [i for i in range(1, 7)]
a.sort(reverse=True)
print(a)
Q: Give users 9 chances to guess numbers (integers from 1 to 10).
It is correct if the number is consistent with the number entered by the user, and an error if it is inconsistent.
The end result requires users to guess wrong.
import random
b = []
i = 0
while i < 9:
a = input('Please enter a number: ')
if a == '':
break
elif a.isdigit() and 0 < eval(a) < 11:
c = {
i for i in range(1, 11)}
b.append(int(a))
i += 1
if len(b) == 9:
d = set(b)
print('The number is %d'%random.choice(list(c-d)))
else:
print('Guess wrong. Do it again.')
elif not a.isdigit() or eval(a) < 1 or eval(a) > 11:
print('Format error. Please re-enter!')
Q: There are two lists list1=[11, 22, 33], list2=[22, 33, 44], requires that the elements in both lists have the same content.
list1 = [11, 22, 33]
list2 = [22, 33, 44]
# method 1
print(list(set(list1) & set(list2)))
# method 2
print([i for i in list1 if i in list2])
Q: Now there are eight teachers and three offices, requiring that eight teachers be randomly assigned to three offices.
import random
list1 = [(i, random.choice([1, 2, 3])) for i in range(1, 9)]
print(list1)
Q: There are now eight teachers and three offices, requiring that eight teachers be randomly assigned to three offices, requiring at least one teacher in each office.
import random
while True:
list1 = [(i, random.choice([1, 2, 3])) for i in range(1, 9)]
if len(set(list1[i][1] for i in range(8))) == 3:
print(list1)
break
Q: It is required to enter the user name and password from the keyboard, verify whether the format conforms to the rules, if not, print out the reason for the non-compliance, and prompt to re-enter it.
while True:
a = input('Please enter your user name: ')
if a == '':
break
elif 5 < len(a) < 21 and a[0].isalpha:
while True:
b = input('Please enter your password: ')
if b == '':
break
elif len(b) > 5 and not b.isdigit() and b.replace(' ', '') == b:
print('Welcome to login, %s'%a)
break
else:
print('Please re-enter your password.')
break
else:
print('Please re-enter the user name.')