Adapted from the original online tutorial.
The material will give you an idea of the Python programming language.
Besides numbers, Python can also manipulate strings.
A string is another type of the Python programming language.
Strings can be expressed in several ways.
They can be enclosed in single quotes ('...'
) or double quotes ("..."
) with the same result.
The character \
can be used to escape quotes.
'spam eggs'
'spam eggs'
And this is a string enclosed in single quotes where we want to include a single quote.
We can use \
to escape the single quote.
'doesn\'t'
"doesn't"
"doesn't"
"doesn't"
'"Yes," he said.'
'"Yes," he said.'
\
."\"Yes,\" he said."
'"Yes," he said.'
'"Isn\'t," she said.'
'"Isn\'t," she said.'
In the interactive interpreter, the output string is always enclosed in quotes and special characters are escaped with backslashes.
In particular, the string is enclosed in double quotes if the string contains a single quote and no double quotes, otherwise it is enclosed in single quotes.
The print()
function produces a more readable output, by omitting the enclosing quotes and by printing escaped and special characters.
print('"Isn\'t," she said.')
"Isn't," she said.
The character \n
embeds a newline character in a string.
When the print()
function encounters \n
in a string, it will start a new line.
s = 'First line.\nSecond line.'
print(s)
First line. Second line.
s
'First line.\nSecond line.'
Apart from newlines, there are other special characters prefaced by \
; for example, \t
is a tab character.
If you don’t want characters prefaced by \
to be interpreted as special characters, you can use raw strings by adding an r
before the first quote.
print('C:\some\name') # here \n means newline!
C:\some ame
print(r'C:\some\name') # note the r before the quote
C:\some\name
String literals can span multiple lines.
One way is using triple-quotes: """..."""
or '''...'''
.
End of lines are automatically included in the string, but it’s possible to prevent this by adding a \
at the end of the line.
print("""\
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
""")
Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to
Strings can be concatenated (glued together) with the + operator, and repeated with *.
# 3 times 'un', followed by 'ium'
3 * 'un' + 'ium'
'unununium'
'Py' 'thon'
'Python'
prefix = 'Py'
prefix 'thon' # can't concatenate a variable and a string literal
prefix 'thon' # can't concatenate a variable and a string literal
^
SyntaxError: invalid syntax
+
:prefix = 'Py'
prefix + 'thon'
'Python'
text = ('Put several strings within parentheses '
'to have them joined together.')
text
'Put several strings within parentheses to have them joined together.'
Strings can be indexed (subscripted), with the first character having index 0.
There is no separate character type; a character is simply a string of size one.
word = 'Python'
word[0] # character in position 0
'P'
word[5] # character in position 5
'n'
Indices may also be negative numbers, to start counting from the right.
Note that since -0 is the same as 0, negative indices start from -1.
word[-1] # last character
'n'
word[-2] # second-last character
'o'
word[-6]
'P'
In addition to indexing, slicing is also supported.
While indexing is used to obtain individual characters, slicing allows you to obtain substrings.
word[0:2] # characters from position 0 (included) to 2 (excluded)
'Py'
word[2:5] # characters from position 2 (included) to 5 (excluded)
'tho'
Note how the start is always included, and the end always excluded.
This makes sure that s[:i] + s[i:]
is always equal to s
.
word[:2] + word[2:]
'Python'
word[:4] + word[4:]
'Python'
Slice indices have useful defaults.
An omitted first index defaults to zero.
An omitted second index defaults to the size of the string being sliced.
word[:2] # character from the beginning to position 2 (excluded)
'Py'
word[4:] # characters from position 4 (included) to the end
'on'
word[-2:] # characters from the second-last (included) to the end
'on'
word[::2]
'Pto'
word[::-1]
'nohtyP'
word[:1:-2]
'nh'
One way to remember how slices work is to think of the indices as pointing between characters.
The left edge of the first character is numbered 0.
Then the right edge of the last character of a string of n characters has index n.
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
The first row of numbers gives the position of the indices 0...6 in the string.
The second row gives the corresponding negative indices.
The slice from i
to j
consists of all characters between the edges labeled i
and j
, respectively.
For non-negative indices, the length of a slice is the difference of the indices, if both are within bounds. For example, the length of word[1:3]
is 2.
word[42]
IndexError: string index out of range
word[4:42]
'on'
word[42:]
''
Python strings cannot be changed — they are immutable.
Therefore, assigning to an indexed position in the string results in an error.
word[0] = 'J'
TypeError: 'str' object does not support item assignment
word[2:] = 'py'
TypeError: 'str' object does not support item assignment
'J' + word[1:]
'Jython'
word[:2] + 'py'
'Pypy'
len()
returns the length of a string.s = 'supercalifragilisticexpialidocious'
len(s)
34
s = 'Hello, World'
print(s)
for x in s:
print(ord(x), end=":")
print()
Hello, World 72:101:108:108:111:44:32:87:111:114:108:100:
Note that uppercase English characters are numbered consecutively.
The same goes for lowercase English characters.
In what follows, ASCII (American Standard Code for Information Interchange) is an older character encoding, the original encoding for English, which is now a subset of Unicode.
import string
for char in string.ascii_uppercase:
print(char, "=", ord(char), end=" ")
print()
for char in string.ascii_lowercase:
print(char, "=", ord(char), end=" ")
A = 65 B = 66 C = 67 D = 68 E = 69 F = 70 G = 71 H = 72 I = 73 J = 74 K = 75 L = 76 M = 77 N = 78 O = 79 P = 80 Q = 81 R = 82 S = 83 T = 84 U = 85 V = 86 W = 87 X = 88 Y = 89 Z = 90 a = 97 b = 98 c = 99 d = 100 e = 101 f = 102 g = 103 h = 104 i = 105 j = 106 k = 107 l = 108 m = 109 n = 110 o = 111 p = 112 q = 113 r = 114 s = 115 t = 116 u = 117 v = 118 w = 119 x = 120 y = 121 z = 122
s = "Καλημέρα, Κόσμε"
print(s)
for x in s:
print(ord(x), end=":")
Καλημέρα, Κόσμε 922:945:955:951:956:941:961:945:44:32:922:972:963:956:949:
s = "你好,世界"
print(s)
for x in s:
print(ord(x), end=":")
你好,世界 20320:22909:65292:19990:30028:
s = "こんにちは世界"
print(s)
for x in s:
print(ord(x), end=":")
こんにちは世界 12371:12435:12395:12385:12399:19990:30028:
s = "안녕하세요 세계"
print(s)
for x in s:
print(ord(x), end=":")
안녕하세요 세계 50504:45397:54616:49464:50836:32:49464:44228:
s = '12345'
print(s)
for x in s:
print(ord(x), end=":")
12345 49:50:51:52:53:
chr()
function.for x in [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100]:
print(chr(x), end="")
Hello, World
We can split a string on a specific character using the split()
method.
split()
is a method, because it is a function that belongs to an object (in this case, a string).
If we give the maxsplit
argument, we will get that number of elements in the result.
If we do not specify a character to split, we split on whitespace.
'1,2,3'.split(',')
['1', '2', '3']
'1,2,3'.split(',', maxsplit=1)
['1', '2,3']
'1,2,,3,'.split(',')
['1', '2', '', '3', '']
'1 2 3 4'.split()
['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]
squares[0] # indexing returns the item
1
squares[-1]
25
squares[-3:] # slicing returns a new list
[49, 64, 81]
squares[1:6:2]
[1, 9, 25]
squares[4:1:-1]
[16, 9, 4]
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.
"Shallow" means that if the elements of the list are themselves compound data types, references to them are created, and not complete copies.
squares[:]
[1, 4, 9, 16, 25]
squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
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]
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]
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
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'
The list data type offers plenty of methods.
list.append(x)
: Add an item to the end of the list. Equivalent to a[len(a):] = [x]
.
list.extend(L)
: Extend the list by appending all the items in the given list. Equivalent to a[len(a):] = L
.
list.insert(i, x)
: Insert an item at a given position. The first argument is the index of the element before which to insert, so a.insert(0, x)
inserts at the front of the list, and a.insert(len(a), x)
is equivalent to a.append(x)
.
list.remove(x)
: Remove the first item from the list whose value is x
. It is an error if there is no such item.
list.pop([i])
: Remove the item at the given position in the list, and return it. If no index is specified, a.pop()
removes and returns the last item in the list. (The square brackets around the i
in the method signature denote that the parameter is optional, not that you should type square brackets at that position. You will see this notation frequently in the Python Library Reference.)
list.clear()
: Remove all items from the list. Equivalent to del a[:]
.
list.index(x)
: Return the index in the list of the first item whose value is x
. It is an error if there is no such item.
list.count(x)
: Return the number of times x
appears in the list.
list.sort(key=None, reverse=False)
: Sort the items of the list in place (the arguments can be used for sort customization, see sorted()
for their explanation).
list.reverse()
: Reverse the elements of the list in place.
list.copy()
: Return a shallow copy of the list. Equivalent to a[:]
.
a = [66.25, 333, 333, 1, 1234.5]
print(a.count(333), a.count(66.25), a.count('x'))
2 1 0
a.insert(2, -1)
a.append(333)
a
[66.25, 333, -1, 333, 1, 1234.5, 333]
a.index(333)
1
a.remove(333)
a
[66.25, -1, 333, 1, 1234.5, 333]
a.reverse()
a
[333, 1234.5, 1, 333, -1, 66.25]
a.sort()
a
[-1, 1, 66.25, 333, 333, 1234.5]
[-1, 1, 66.25, 333, 333, 1234.5]
a.pop()
1234.5
1234.5
a
[-1, 1, 66.25, 333, 333]
The list methods make it very easy to use a list as a stack, where the last element added is the first element retrieved (“last-in, first-out”).
To add an item to the top of the stack, use append()
.
To retrieve an item from the top of the stack, use pop()
without an explicit index.
stack = [3, 4, 5]
stack.append(6)
stack.append(7)
stack
[3, 4, 5, 6, 7]
stack.pop()
7
stack
[3, 4, 5, 6]
stack.pop()
6
stack.pop()
5
stack
[3, 4]
List comprehensions provide a concise way to create lists.
Common applications are to make new lists where each element is the result of some operations applied to each member of another sequence or iterable, or to create a subsequence of those elements that satisfy a certain condition.
For example, assume we want to create a list of squares.
squares = []
for x in range(10):
squares.append(x**2)
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
x
that still exists after the loop completes. We can calculate the list of squares without any side effects using a different approach.squares = [x**2 for x in range(10)]
A list comprehension consists of brackets containing an expression followed by a for
clause, then zero or more for
or if
clauses.
The result will be a new list resulting from evaluating the expression in the context of the for
and if
clauses which follow it.
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
combs = []
for x in [1,2,3]:
for y in [3,1,4]:
if x != y:
combs.append((x, y))
combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
Note how the order of the for and if statements is the same in both these snippets.
If the expression is a tuple (e.g. the (x, y)
in the previous example), it must be parenthesized.
vec = [-4, -2, 0, 2, 4]
# create a new list with the values doubled
[x*2 for x in vec]
[-8, -4, 0, 4, 8]
# filter the list to exclude negative numbers
[x for x in vec if x >= 0]
[0, 2, 4]
# apply a function to all the elements
[abs(x) for x in vec]
[4, 2, 0, 2, 4]
# call a method on each element
freshfruit = [' banana', ' loganberry ', 'passion fruit ']
[weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
# create a list of 2-tuples like (number, square)
[(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
[x, x**2 for x in range(6)]
[x, x**2 for x in range(6)]
^
SyntaxError: invalid syntax
# flatten a list using a listcomp with two 'for'
vec = [[1,2,3], [4,5,6], [7,8,9]]
[num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
from math import pi
[str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
The initial expression in a list comprehension can be any arbitrary expression, including another list comprehension.
Consider the following example of a 3x4 matrix implemented as a list of 3 lists of length 4.
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
]
[[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
for
that follows it, so this example is equivalent to the following.transposed = []
for i in range(4):
transposed.append([row[i] for row in matrix])
transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
transposed = []
for i in range(4):
# the following 3 lines implement the nested listcomp
transposed_row = []
for row in matrix:
transposed_row.append(row[i])
transposed.append(transposed_row)
transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
In the real world, you should prefer built-in functions to complex flow statements.
The zip()
function would do a great job for this use case.
list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
del
statement¶There is a way to remove an item from a list given its index instead of its value: the del
statement.
This differs from the pop()
method which returns a value.
The del
statement can also be used to remove slices from a list or clear the entire list (which we did earlier by assignment of an empty list to the slice).
a = [-1, 1, 66.25, 333, 333, 1234.5]
del a[0]
a
[1, 66.25, 333, 333, 1234.5]
del a[2:4]
a
[1, 66.25, 1234.5]
del a[:]
a
[]
del
can also be used to delete entire variables.del a
a
hereafter is an error (at least until another value is assigned to it). if
Statements¶if
statement.x = int(input("Please enter an integer: "))
Please enter an integer: 10
if x < 0:
x = 0
print('Negative changed to zero')
elif x == 0:
print('Zero')
elif x == 1:
print('Single')
else:
print('More')
More
There can be zero or more elif
parts, and the else
part is optional.
The keyword elif
is short for else if
, and is useful to avoid excessive indentation.
An if
... elif
... elif
... sequence is a substitute for the switch
or case
statements found in other languages.
There are no switch
or case
statements in Python.
In Python the following values are considered false:
None
False
zero of any numeric type, for example, 0
, 0.0
, 0j
.
any empty sequence, for example, ''
, ()
, []
.
any empty mapping, for example, {}
.
instances of user-defined classes, if the class defines a __bool__()
or __len__()
method, when that method returns the integer zero or bool value False
.
Everything else is considered true.
Operation | Result | Notes |
---|---|---|
not x |
if x is false, then True , else False |
lower priority than non-boolean operators |
x or y |
if x is false, then y, else x | short-circuit |
x and y |
if x is false, then x, else y | short-circuit |
not a == b
means not (a == b)
; a == not b
is a syntax error.The keyword is
is used for identity testing.
The negation is not is
.
Identity testing means checking that two objects are the same, not that they are equal.
A frequent use of is
is against None
: x is None
, x is not None
, not x is None
.
a = "a"
b = "b"
c = a + b
d = "ab"
print("c == d:", c == d)
print ("c is d:", c is d)
c == d: True c is d: False
ra = range(10)
rb = range(10)
print("ra == rb:", ra == rb)
print("ra is rb:", ra is rb)
ra == rb: True ra is rb: False
if
expressions¶Apart from if
statements, we also have if
expressions.
These evaluate an expression depending on a condition.
import datetime # use the datetime library
now = datetime.datetime.now().time()
message = "good morning" if now < datetime.time(12) else "good evening"
print(message)
good evening
for
Statements¶The for
statement in Python differs a bit from what you may be used to in C or Pascal.
It does not always iterate over an arithmetic progression of numbers (like in Pascal).
It does not give 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.
# Measure some strings:
words = ['cat', 'window', 'defenestrate']
for w in words:
print(w, len(w))
cat 3 window 6 defenestrate 12
Do not modify a sequence when you are iterating over it.
If you do need to do that, do that on a copy of the sequence.
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.append(w)
print(words)
['cat', 'window', 'defenestrate', 'defenestrate']
Note that if we were appending instead of inserting, then if we were not using a copy we would end up with a disaster.
We would enter an infinite loop.
The following code will never end.
for w in words: # Loop over the actual list.
if len(w) > 6:
words.append(w)
print(words)
range()
Function¶If 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’).
for i in range(5, 10):
print(i, end=' ')
print()
for i in range(0, 10, 3):
print(i, end=' ')
print()
for i in range(-10, -100, -30):
print(i, end=' ')
print()
for i in range(10, -1, -1):
print(i, end=' ')
5 6 7 8 9 0 3 6 9 -10 -40 -70 10 9 8 7 6 5 4 3 2 1 0
range()
and len()
.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
enumerate()
function.for i, v in enumerate(a):
print(i, v)
0 Mary 1 had 2 a 3 little 4 lamb
print(range(10))
range(0, 10)
range()
returns something that 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 an iterator. The function list()
is another; it creates lists from iterables.
list(range(5))
[0, 1, 2, 3, 4]
break
statements¶break
statement, borrowed from C, stops the execution of the nearest enclosing for
or while
loop. for name in ["Alice", "Bob", "Carol", "Dan", "Eve"]:
if name[0] == "C":
print("Found a name starting with C:", name)
break
Found a name starting with C: Carol
continue
statements¶continue
statement, also borrowed from C, continues with the next iteration of the loop.for num in range(2, 10):
if num % 2 == 0:
print("Found an even number", num)
continue
print("Found a number", num)
Found an even number 2 Found a number 3 Found an even number 4 Found a number 5 Found an even number 6 Found a number 7 Found an even number 8 Found a number 9
pass
statements¶if some_condition:
pass # Don't know what to do yet, will fill in later
def fib(n): # write Fibonacci series up to n
"""Print a Fibonacci series up to n."""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
# Now call the function we just defined:
fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
Coming from other languages, you might object that fib
is not a function but a procedure since it doesn’t return a value.
In fact, even functions without a return
statement do return a value, albeit a rather boring one.
This value is called None
(it’s a built-in name).
Writing the value None
is normally suppressed by the interpreter if it would be the only value written.
You can see it if you really want to using print()
.
fib(0)
print(fib(0))
None
def fib2(n): # return Fibonacci series up to n
"""Return a list containing the Fibonacci series up to n."""
result = []
a, b = 0, 1
while a < n:
result.append(a) # see below
a, b = b, a+b
return result
f100 = fib2(100) # call it
f100 # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
The return
statement returns with a value from a function.
return
without an expression argument returns None
.
Falling off the end of a function also returns None
.
The statement result.append(a)
calls a method of the list object result
.
A method is a function that ‘belongs’ to an object and is named obj.methodname
, where obj
is some object (this may be an expression), and methodname
is the name of a method that is defined by the object’s type.
The method append()
shown in the example is defined for list objects; it adds a new element at the end of the list. In this example it is equivalent to result = result + [a]
, but more efficient.
def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
while True:
ok = input(prompt)
if ok in ('y', 'ye', 'yes'):
return True
if ok in ('n', 'no', 'nop', 'nope'):
return False
retries = retries - 1
if retries < 0:
raise OSError('uncooperative user')
print(complaint)
This function can be called in several ways.
giving only the mandatory argument: ask_ok('Do you really want to quit?')
giving one of the optional arguments: ask_ok('OK to overwrite the file?', 2)
or even giving all arguments: ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')
This example also introduces the in
keyword. This tests whether or not a sequence contains a certain value.
kwarg=value
. def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")
parrot(1000) # 1 positional argument
parrot(voltage=1000) # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump') # 3 positional arguments
parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword
-- This parrot wouldn't voom if you put 1000 volts through it. -- Lovely plumage, the Norwegian Blue -- It's a stiff ! -- This parrot wouldn't voom if you put 1000 volts through it. -- Lovely plumage, the Norwegian Blue -- It's a stiff ! -- This parrot wouldn't VOOOOOM if you put 1000000 volts through it. -- Lovely plumage, the Norwegian Blue -- It's a stiff ! -- This parrot wouldn't VOOOOOM if you put 1000000 volts through it. -- Lovely plumage, the Norwegian Blue -- It's a stiff ! -- This parrot wouldn't jump if you put a million volts through it. -- Lovely plumage, the Norwegian Blue -- It's bereft of life ! -- This parrot wouldn't voom if you put a thousand volts through it. -- Lovely plumage, the Norwegian Blue -- It's pushing up the daisies !
parrot() # required argument missing
parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
parrot(110, voltage=220) # duplicate value for the same argument
parrot(actor='John Cleese') # unknown keyword argument
How do we define the factorial of a number?
The factorial $n!$ of a nunber $n$ is defined as follows: $$n!={\begin{cases}1&{\text{if }}n=0,\\(n-1)!\times n&{\text{if }}n>0\end{cases}}$$
This is a recursive definition: a function that is defined in terms of itself.
Recursive functions are an integral part of computation in general.
They are straightforward to define in Python.
For instance, here is a definition of the factorial function in Python.
def factorial(n):
if n == 0:
return 1
else:
return factorial(n-1) * n
print(factorial(10))
3628800
Another recursive function is the one we can use for calculating the greatest common divisor (GCD) of two numbers.
According to Euclid's algorithm, the gcd of two numbers $a$ and $b$ is $a$ if $b = 0$ or the gcd of $b$ and $a \bmod b$ otherwise.
This leads to the following function in Python.
def gcd(a, b):
if b == 0:
return a
else:
return gcd(b, a % b)
gcd(135, 25)
5
def gcd(a, b):
return gcd(b, a % b) if b else abs(a)
gcd(135, 25)
5
Small anonymous functions can be created with the lambda
keyword.
This function returns the sum of its two arguments: lambda a, b: a+b
.
Lambda functions can be used wherever function objects are required.
They are syntactically restricted to a single expression. Semantically, they are just syntactic sugar for a normal function definition.
Like nested function definitions, lambda functions can reference variables from the containing scope.
sq = lambda x: x*x
sq(4)
16
list(filter(lambda x: x%2 == 0, range(10)))
[0, 2, 4, 6, 8]
pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
pairs.sort(key=lambda pair: pair[1])
pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
A module is a file containing function definitions and statements.
You can think of a module as a library in other programming languages.
Python has a rich library, containing modules for all sorts of things:
import
statement allows us to use a module in our codeimport math
math
prefix.for x in range(0, 11):
y = x * (math.pi / 10)
print(y, math.cos(y))
0.0 1.0 0.3141592653589793 0.9510565162951535 0.6283185307179586 0.8090169943749475 0.9424777960769379 0.5877852522924732 1.2566370614359172 0.30901699437494745 1.5707963267948966 6.123233995736766e-17 1.8849555921538759 -0.30901699437494734 2.199114857512855 -0.587785252292473 2.5132741228718345 -0.8090169943749473 2.827433388230814 -0.9510565162951535 3.141592653589793 -1.0
import
statement allows us to give shorter names to imported modules.import itertools as iter
for comb in iter.combinations('ABCD', 2):
print(comb)
('A', 'B') ('A', 'C') ('A', 'D') ('B', 'C') ('B', 'D') ('C', 'D')
There is also a variant of the import
statement that allows us to use the definitions in the module without a prefix at all.
Of course we must be careful to avoid any conflicts with other names defined in our program.
from collections import Counter
Counter('abracadabra').most_common(3)
[('a', 5), ('b', 2), ('r', 2)]
We saw that lists and strings have many common properties, such as indexing and slicing operations.
They are two examples of sequence data types (such as a list
and a range
).
Since Python is an evolving language, other sequence data types may be added.
There is also another standard sequence data type: the tuple.
A tuple consists of a number of values separated by commas.
t = 12345, 54321, 'hello!'
t[0]
12345
t
(12345, 54321, 'hello!')
# Tuples may be nested:
u = t, (1, 2, 3, 4, 5)
u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
t[0] = 88888
----> 1 t[0] = 88888
TypeError: 'tuple' object does not support item assignment
# but they can contain mutable objects:
v = ([1, 2, 3], [3, 2, 1])
v
([1, 2, 3], [3, 2, 1])
v[0].append(4)
v
([1, 2, 3, 4], [3, 2, 1])
On output tuples are always enclosed in parentheses, so that nested tuples are interpreted correctly.
They may be input with or without surrounding parentheses, although often parentheses are necessary anyway (if the tuple is part of a larger expression).
It is not possible to assign to the individual items of a tuple, however it is possible to create tuples which contain mutable objects, such as lists.
Though tuples may seem similar to lists, they are often used in different situations and for different purposes.
Tuples are immutable, and usually contain an heterogeneous sequence of elements that are accessed via unpacking (as we'll see shortly) or indexing (or even by attribute in the case of a special kind of tuple called a namedtuple
).
Lists are mutable, and their elements are usually homogeneous and are accessed by iterating over the list.
A special problem is the construction of tuples containing 0 or 1 items.
The syntax has some extra quirks to accommodate these.
Empty tuples are constructed by an empty pair of parentheses.
A tuple with one item is constructed by following a value with a comma (it is not sufficient to enclose a single value in parentheses). Ugly, but effective.
empty = ()
singleton = 'hello', # <-- note trailing comma
len(empty)
0
len(singleton)
1
singleton
('hello',)
The statement t = 12345, 54321, 'hello!'
is an example of tuple packing.
The values 12345
, 54321
and 'hello!'
are packed together in a tuple.
t = 12345, 54321, 'hello!'
t
(12345, 54321, 'hello!')
x, y, z = t
x
12345
y
54321
z
'hello!'
This is called, appropriately enough, sequence unpacking.
It works for any sequence on the right-hand side.
Sequence unpacking requires that there are as many variables on the left side of the equals sign as there are elements in the sequence.
Note that multiple assignment is really just a combination of tuple packing and sequence unpacking.
Python also includes a data type for sets.
A set is an unordered collection with no duplicate elements.
Basic uses include membership testing and eliminating duplicate entries.
Set objects also support mathematical operations like union, intersection, difference, and symmetric difference.
Curly braces or the set()
function can be used to create sets.
To create an empty set you have to use set()
, not {}
; the latter creates an empty dictionary, a data structure that we discuss latter.
basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
print(basket) # show that duplicates have been removed
{'pear', 'apple', 'orange', 'banana'}
'orange' in basket # fast membership testing
True
'crabgrass' in basket
False
# Demonstrate set operations on unique letters from two words
a = set('abracadabra')
b = set('alacazam')
print(a) # unique letters in a
print(b) # unique letters in b
{'d', 'c', 'b', 'a', 'r'} {'l', 'm', 'c', 'a', 'z'}
-
.a - b # letters in a but not in b
{'b', 'd', 'r'}
|
.a | b # letters in either a or b
{'a', 'b', 'c', 'd', 'l', 'm', 'r', 'z'}
&
.a & b # letters in both a and b
{'a', 'c'}
a ^ b # letters in a or b but not both
{'b', 'd', 'l', 'm', 'r', 'z'}
a = {x for x in 'abracadabra' if x not in 'abc'}
a
{'d', 'r'}
Another useful data type built into Python is the dictionary.
Dictionaries are sometimes found in other languages as “associative memories” or “associative arrays”.
Unlike sequences, which are indexed by a range of numbers, dictionaries are indexed by keys, which can be any immutable type; strings and numbers can always be keys.
Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key.
You can’t use lists as keys, since lists can be modified in place using index assignments, slice assignments, or methods like append()
and extend()
.
It is best to think of a dictionary as an unordered set of key: value pairs, with the requirement that the keys are unique (within one dictionary).
A pair of braces creates an empty dictionary: {}
.
Placing a comma-separated list of key:value
pairs within the braces adds initial key:value
pairs to the dictionary; this is also the way dictionaries are written on output.
The main operations on a dictionary are storing a value with some key and extracting the value given the key.
It is also possible to delete a key:value
pair with del
.
If you store using a key that is already in use, the old value associated with that key is forgotten.
It is an error to extract a value using a non-existent key.
Performing list(d.keys())
on a dictionary returns a list of all the keys used in the dictionary, in arbitrary order.
If you want it sorted, just use sorted(d.keys())
.
To check whether a single key is in the dictionary, use the in
keyword.
Dictionary creation is similar to set creation, but we use key: value
pairs.
We can also add items in an existing dictionary with mydict[key] = value
.
An empty dictionary is simply {}
(that's why an empty set must be defined with set()
.
tel = {'jack': 4098, 'sape': 4139}
tel['guido'] = 4127
tel
{'guido': 4127, 'jack': 4098, 'sape': 4139}
tel['jack']
4098
We can delete an item from a dictionary with del
.
Re-assigning to an existing key overwrites the previous value.
del tel['sape']
tel['irv'] = 4127
tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
To get all the keys in a dictionary we use the keys()
method.
If we want to put them in a list, we use the list()
function on its results.
list(tel.keys())
['guido', 'jack', 'irv']
Dictionaries are unsorted.
If we want access them in an ordered way, we have to sort the keys.
sorted(tel.keys())
['guido', 'irv', 'jack']
'guido' in tel
True
'jack' not in tel
False
items()
method.knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
print(k, v)
robin the brave gallahad the pure
enumerate()
function.for i, v in enumerate(['tic', 'tac', 'toe']):
print(i, v)
0 tic 1 tac 2 toe
zip()
function.questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print('What is your {0}? It is {1}.'.format(q, a))
What is your name? It is lancelot. What is your quest? It is the holy grail. What is your favorite color? It is blue.
reversed()
function.for i in reversed(range(1, 10, 2)):
print(i)
9 7 5 3 1
sorted()
function which returns a new sorted list while leaving the source unaltered.basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
print(f)
apple banana orange pear
It is sometimes tempting to change a list while you are looping over it.
However, it is often simpler and safer to create a new list instead.
import math
raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
filtered_data = []
for value in raw_data:
if not math.isnan(value):
filtered_data.append(value)
filtered_data
[56.2, 51.7, 55.3, 52.5, 47.8]
raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
for value in raw_data[:]:
if math.isnan(value):
raw_data.remove(value)
raw_data
[56.2, 51.7, 55.3, 52.5, 47.8]
The Greek Tax Identification Number (TIN) consists of 9 digits. The last digit is a check digit. It is calculated as follows:
For example, let us say we have the TIN 090034337. The check digit is 7. The other digits are 09003433. We have: $$3\times 2^1 + 3\times 2^2 + 4\times 2^3 + 3\times 2^4 + 9\times 2^7 =$$ $$3\times 2 + 3\times 4 + 4\times 8 + 3 \times 16 + 9\times 128 =$$ $$6 + 12 + 32 + 48 + 1152 = 1250$$
Then, $1250 \bmod 11 = 7$ και $7 \bmod 10 = 7$.
Write a program that will ask the user for TIN and will respond whether it is correct or not. For example:
Enter Tax Identification Number: 090034337
Tax Identification Number valid.
Enter Tax Identification Number: 090034336
Tax Identification Number not valid.
A simple way to check binary data is the so-called parity bit. A byte consists of 8 bits, so that we can use the last bit to check whether the previous 7 are OK. We can do that by checking that the sum of the 1 bits is an even number (this is actually called even parity; we might require that the sum of 1 bits is odd, which is called odd parity). For example, see the following table where we see the first 7 bits of some numbers, the number of 1 bits in them, the full 8-bit number (including the parity) and the number of 1 bits in the byte.
First 7 bits | Number of 1s | 8 bits (with parity) | Number of 1s |
---|---|---|---|
0000000 | 0 | 00000000 | 0 |
1010001 | 3 | 10100011 | 4 |
1101001 | 4 | 11010010 | 4 |
1111111 | 7 | 11111111 | 8 |
Write a program that asks the user for an 8-bit binary number and replies whether the parity bit checks OK. For example:
Enter binary number: 01010101
Parity check OK.
Enter binary number: 11010101
Parity check not OK.
Write a program that asks the user for a 10-digit number and will then print it in two lines. The first line will contain the numbers in the odd positions and the second line the numbers in the even positions. For example:
Enter 10 digit number: 1234567890
1 3 5 7 9
2 4 6 8 0
Take care so that the numbers line up in columns exactly as in the above example: each number must be in a column by itself.
Write a program that asks the user for a 9-digit number and then prints it in three lines. Each line must contain three digits. For example:
Enter 9 digit number: 123456789
1 4 7
2 5 8
3 6 9
Take care so that the numbers line up in columns exactly as in the above example: each number must be in a column by itself.
To calculate Orthodox Easter Sunday for any year between 1900 and 2099, we can use the following algorithm. Suppose that $y$ is the year.
math.floor()
function, in the math
module. But you may not need it, because //
implements integer division in Python.Write a program that asks the user for a year and then displays the month and the day of Orthodox Easter in the Gregorian calendar. For example:
Enter year: 2011
Day: 24 Month: 4
You may check your program for 2012 (15/4), 2013 (5/5), 2014 (20/4), 2015 (12/4), 2016 (1/5), 2017 (16/4).
Write a program that asks the user for 9 numbers: 1 with 1 digit, 1 with 2 digits, 1 with 3 digits, then again 1 with 1 digit, 1 with 2 digits, 1 with 3 digits, and then again 1 with 1 digit, 1 with 2 digits, 1 with 3 digits. Then the program will print them in columns, where each column will contain 1 single digit number, 1 double digit number, and 1 triple digit number. The columns will be 3 characters wide and will be separated from each other with the character +
. The numbers inside the columns will be right justified. For example:
Enter numbers: 1 10 100 2 20 200 3 30 300
1| 2| 3
10| 20| 30
100|200|300
To calculate the number of days between two days we can use the following algorithm. Let's say that the first date is given by $y_1$, $m_1$, $d_1$ and the second date is given by $y_2$, $m_2$, $d_1$ ($d_i$ are days, $m_i$ are months, $y_i$ are years).
Write a program that asks the user to enter two dates in the form dd/mm/yyyy
and will then display the number of days that have elapsed between the two days. Be careful, the result must not be negative, no matter the order in which the user enters the dates. For example (15/3/-44 was the day Julius Caesar was murdered):
Enter dates: 15/3/-44 4/11/2016
752596 days.
Another example (17/12/1903 was the first flight by the Wright brothers).
Enter dates: 28/09/2016 17/12/1903
41193 days.
Consider a sequence of numbers that describes another sequence, as follows. The sequence in read by pairs. The first part of a pair indicates how many times we should take the second part. If the length of the sequence is an odd number, then we just take the last number by itself. So, the sequence 1234567 means "1 times 2 and 3 times 4 and 5 times 6 and 7", which is: $$ 1 \times 2 + 3 \times 4 + 5 \times 6 + 7$$
Write a program that asks a user to enter a sequence of digits and then calculates the value of the sequence, as defined above. For example:
Enter number sequence: 123456
44
Enter number sequence: 1234567
51
Enter number sequence: 1230123
7
Enter number sequence: 001234
The Caesar cipher works by substituting each character in a message with a character that occurs $x$ places later on the alphabet, wrapping around from the beginning, if neeeded. So, if $x = 3$ then "ABIGΖΟΟ" will become "DELJCRR".
Write a program that will ask for the number of positions to shift each character and a phrase; then it will output the phrase encrypted with the Caesar cipher. You can assume that the phrase consists only of uppercase English letters (without punctuation or spaces). For example:
Enter shift: 20
Enter phrase: FAILBETTER
ZUCFVYNNYL
Enter shift: 10
Enter phrase: TOBEORNOTTOBETHATISTHEQUESTION
DYLOYBXYDDYLODRKDSCDROAEOCDSYX
Note: this method may have been adequate in Caesar's time, but it is completely useless today.
To be sure that your encoding is correct, write also the decryption program that takes a shift and an encrypted phrase and then produces the original plaintext.
Write a program that asks a user to enter a sequence of 0s and 1s. Following that, it will identify the longest run of 0s or 1s of the sequence and will print an appropriate message. Examples:
Enter binary sequence: 1111000
Longest run was ones with length: 4
Enter binary sequence: 1010100000
Longest run was zeros with length: 5
Enter binary sequence: 11110000111000
Equal longest run of ones and zeros with length: 4
The positive integer numbers that can be written as the sum of two or more consecutive positive integers are called polite numbers. The rest are called impolite numbers. The first polite numbers are: 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, ....
It can be proven that the impolite numbers are the powers of 2. Write a program that asks the user for an upper limit and then prints out the polite numbers up to and including the limit. The program should not use logarithms. The numbers should be written in rows of 10 (expect possibly for the last line). Examples:
Enter limit: 10
3 5 6 7 9 10
Enter limit: 16
3 5 6 7 9 10 11 12 13 14
15
Enter limit: 25
3 5 6 7 9 10 11 12 13 14
15 17 18 19 20 21 22 23 24 25
Enter limit: 30
3 5 6 7 9 10 11 12 13 14
15 17 18 19 20 21 22 23 24 25
26 27 28 29 30
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.