Download 1. Introduction to Python Official Python website: http://www.python

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
1. Introduction to Python
Official Python website: http://www.python.org
Python download (most recent version is 3.5.2): https://www.python.org/downloads
Python v3.5 documentation: https://docs.python.org/3
Python v3.5 tutorial: https://docs.python.org/3/tutorial/index.html
Python v3.5 standard library: https://docs.python.org/3/library/index.html#library-index
Python v3.5 language reference: https://docs.python.org/3/reference/index.html#reference-index
Python package index: https://pypi.python.org/pypi
1.1 Versions 2 and 3
There are two major versions of Python, versions 2.7 and 3. There are a few significant differences between these two ver sions and v3 is not backwards-compatible with v2. New development on the v2 branch has effectively terminated, and v3
(the most recent version is 3.6.0) is said to be the future of the Python language. Consequently, my opinion is that if you
are new to Python then you might as well learn v3 because v2 code will eventually be obsoleted. See reference [1] below
for more discussion of the changes.
The major difference between v2 and v3 that impacts the programs we will be writing is that in v2, print was a statement
but in v3 it is a built-in function (built-in functions are commonly used functions that are directly implemented by the
Python interpreter and do not require an import statement to access the function). For example,
# Version 2 Hello World Program
print "Hello world.\n"
# Version 3 Hello World Program
print("Hello world.\n")
By the way, there are a lot of tutorials and discussions about Python on the internet. Much of the published Python code
is v2 and not v3, so be aware of that.
Another v3 change that might impact us is how the division operator works with integer operands. In particular, in v2 ,
print 3/4 prints 0 because invoking / on two integer operands results in an integer quotient. In v3, print(3/4) prints
0.75 (floating point division is performed) and to perform integer division use print(3//4) which prints 0.
Another v3 change concerns rounding. In v2, positive numbers are rounded up, negative numbers are rounded to negative
infinity, i.e., round(1.5) is 2, round(2.5) is 3, round(-1.5) is -2.0, round(-2.5) is -3.0. In v3, numbers ending in .5 are are
rounded to the nearest even number: round(1.5) is 2, round(2.5) is 2, round(-1.5) is -2.0, and round(-2.5) is -2.0.
Other changes in v3 can be found at [1, 2].
References
1. Wiki.Python.Org - Python v2 or v3: https://wiki.python.org/moin/Python2orPython3
2. Python.org - What's new in Python 3.0? https://docs.python.org/3/whatsnew/3.0.html
1.2 Online Development
There are several online development websites which provide IDE's that run from simple to sophisticated. The primary
advantage of using an online IDE is that you do not have to install software on your computer, you just log in and start
coding. I placed links on the course website to several online IDE's. I do not have significant experience with any of these,
but when playing around with them, I liked the looks of Coding Ground (mainly because it looks "clean" and provides a
Linux Bash shell interface). Some of these IDE's require you to create an account to log in. They are all free or commercial
products which also offer a free evaluation environment. The Learn Python environment allows you edit and run your code
online and also provides a number of tutorials to help you learn Python. Be aware that the Learn Python tutorials do not
go deep into each topic. If you are looking for a good Python tutorial, I have listed several in the section named Python
References (Tutorials, Books) on the course webpage. The Python Tutor website is interesting as it permits you to enter
Python code and then execute it, line by line, while the tool displays a visualization of the program variables and their
changing values.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 1
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
1.3 Offline Development
There are numerous IDE's that support Python programming. The page at [1] lists many of them. IDLE is the official
Python IDE which is also installed when you install Python3. IDLE is not as full-featured as many of the other IDE's but
it is more than sufficient and easy to use when writing small programs. It is the IDE that I have been using on my Linux
system. The two other IDE's that I have experience with are Eclipse (with the PyDev plugin) and NetBeans. Both IDE's
are written in Java so they can be easily installed and executed on OS X, Linux, and Windows. The other IDE I have
played around with is PyCharm, which on the surface looks nice and is highly customizable (as are many IDE's). Earlier
this year, I decided that I would start using PyCharm as my Python IDE. After installing it and spending quite a bit of
time configuring it, I concluded that it seems to be very buggy. I have not given up on it yet and time will tell me whether
is it worthwhile to use PyCharm or to throw it in the trash.
References
1. Python.Org Wiki - IDE's: https://wiki.python.org/moin/IntegratedDevelopmentEnvironments
2. The Python Interpreter
Python is an interpreted dynamically-typed language 1. The python interpreter implements a read, evaluate, print loop
(REPL) where it continuously loops reading input, evaluating/executing the input, and printing the result of the evaluation.
The Python interpreter on Linux is invoked with the python or python3 command (when both Python v2 and v3 are
installed; if only Python 3 is installed you would type either python or python3; the version in used can be determined
by invoking python --version). Because Python is interpreted, we do not have to write a complete program to try things
out, e.g.,
>>> print("Hello world.")
Hello world.
>>> 2 + 3
5
>>> x = 5 ; y = 10 ; z = x + y
>>> z
15
The default interpreter prompt is >>>. I read that this can be changed somehow.
Multiple statements on the same line are separated by semicolons.
To display the value of a variable, just type the name of the variable.
Dynamically-typed languages are those in which the type of a variable (or object) can change during execution. Generally,
dynamically-typed programming languages do not require the programmer to specify data types for variables, constants,
and so on. Python does not, so the following code is perfectly legal (note that Python statements on the same line are separated by a semicolon). type(x) is a built-in function that returns the type of x as a string.
#
x
x
x
dynamic.py - dynamic typing example.
= 10 ; print("x =", x, "the type of x is", type(x))
= 3.14159 ; print("x =", x, "the type of x is", type(x))
= "Günther is loose again. Release the hounds." ; print("x =", x, "the type of x is", type(x))
$
x
x
x
python3 dynamic.py
= 10 the type of x is <class 'int'>
= 314159 the type of x is <class 'float'>
= "Günther is loose again. Release the hounds." the type of x is <class 'str'>
A compiler translates high-level language code into low-level machine language code which is directly executed by the
CPU. Most interpreted languages are compiled into an internal "bytecode" format which is then executed (or interpreted)
by a virtual machine. Python source code files generally have a .py extension. If you find .pyc files in a directory, those are
Python files that have been compiled into bytecodes.
1
In programming language terms, static generally refers to something that happens at compile-time. The term dynamic refers to something that happens at
run-time.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 2
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
3. Language Features
There are thousands of Python tutorials and blog posts. A few of what I think are decent Python tutorials are,
1. Think Python: How to think like a computer scientist, 2nd Ed, by Allen Downey
2. Problem Solving using Python by Brad Miller and David Ranum
3. Python Tutorial by TutorialsPoint.com
Note that Python is case-sensitive.
3.1 Comments
A single-line comment begins with # and extends to the end of line (this is similar to how // works in C++ and Java).
Multi-line comments may be written as several lines, each starting with #, or the comment can be embedded within triple
quotes, e.g.,
#
#
#
#
#
SomeFile.py
Description
Blah blah blah yakkity blah blah. Blah blah blah yakkity blah blah.
Blah blah blah yakkity blah blah. Blah blah blah yakkity blah blah.
def main():
"""
This is a multi-line comment embedded within triple
embedded within triple quotes. This is a multi-line
embedded within triple quotes. This is a multi-line
embedded within triple quotes. This is a multi-line
"""
quotes.
comment
comment
comment
This is a multi-line comment
embedded within triple quotes.
embedded within triple quotes.
embedded within triple quotes.
A Python docstring is a string literal """...""" that appears as the first statement in a function. See [1] for more information regarding docstrings. The job of a docstring is to provide a relatively brief description of what the function does. For
example,
# fact()
def fact(n):
""" Return n! """
if n < 2:
return 1
else:
return n * fact(n - 1)
According to Python purists, every function must have a docstring. One reason docstrings are useful is because you can
read the docstring for a function in the interpreter by using the help() built-in function, e.g.,
>>> help(fact)
Help on function fact in module __main__:
fact(n)
return n!
>>> help(print)
Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
... and so on
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 3
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
References
1. Python PEP 257: https://www.python.org/dev/peps/pep-0257/
3.2 The Standard Type Hierarchy
All data in Python are represented by objects. Each object has an identity, a type, and a value. The identity of an object
never changes once the object is created; you may think of it as the object's address in memory. The object's type deter mines the operations that may be performed on the object. The type(object) function returns the type of object as a string.
The value of some objects can change; such objects are called mutable. If the value cannot change, the object is immutable. An object's mutability is determined by its type: int, float, string, set, and tuple objects are immutable. On the
other hand, list and dictionary objects are mutable.
Objects are automatically garbage-collected when no longer in use.
Some objects contain references to other objects; these types of objects are called containers. For example, the set, list,
string, and tuple types are all container types. An immutable container, e.g., tuple, may contain references to mutable
objects. In this case, the values of the mutable objects within the container may be changed, but the container itself may
not be changed, i.e., we cannot change a reference to a object, e.g.,
>>> t = ([1, 2, 3],[4, 5, 6],[7, 8, 9])
t is a 3-tuple; each element of t is a list.
>>> t[0]
To print the value of variable var in the interpreter, type var.
[1, 2, 3]
>>> t[1]
[4, 5, 6]
>>> t[0][1] = 7
t[0] is [1, 2, 3]; t[0][1] is 2; this statement changes t[0] to [1, 7, 3].
>>> t[0]
Note: the above is legal because lists are mutable, i.e., we change the value
[1, 7, 3]
of list elements.
>>>t[0] = [100, 200, 300]
Try to change the tuple t by making t[0] refer to a different list; blows up
Traceback (most recent call last):
with TypeError exception because t is immutable.
...
TypeError: 'tuple' object does not support item assignment
The other three possibilities are: a mutable container that contains a mutable object (both the object's value and the con tainer's reference to the object can be changed); a mutable container that contains an immutable object (the object's
value may not be changed but the container's reference to the object can be changed); and an immutable container that
contains an immutable object (neither the object's value or the container's reference to the object may be changed).
References
1. Python Lang. Ref - §3 Data Model: https://docs.python.org/3/reference/datamodel.html
2. Python Std. Lib - §4 Built-In Types: https://docs.python.org/3/library/stdtypes.html
3.2.1 None
There exists just one object of this type, named None, which signifies the absence of a value in some situations, e.g., it is
similar to null in C++ and Java. Note that when treated as a Boolean value, None is equivalent to False.
3.2.2 Numbers
int
Signed integers of unlimited range, subject to the amount of virtual memory available to the interpreter.
bool
Two objects of type bool: True and False. When treated as an int, True is 1 and False is 0.
float
Real numbers, stored internally in double-precision floating point format, i.e., a double uses 8-bytes of memory.
complex Complex numbers, e.g, z = 2.3 - 3.1j. z.real is 2.3 (a float) and z.imag is -3.1 (also a float).
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 4
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
3.2.3 Sequences
A sequence is a finite ordered set of objects indexed by nonnegative integers (starting at 0). The built-in function len()
returns the number of elements in the sequence. For example,
>>>
>>>
3
>>>
>>>
4
L = [1, 2, 3]
len(L)
L is a list containing 3 objects, all ints.
s = "Fred"
len(s)
s is a string containing four characters.
Sequences support slicing operations. A slice of a sequence S is a subsequence of elements from S. The slice notation s[i:j]
selects all items with index x such that i ≤ x < j, i.e., the element at j is not part of the slice. Slice notation also permits a
third parameter, e.g., s[i:j:k] refers to those elements at index x such that x = i + nk, n ≥ 0 and i ≤ x < j. Examples,
>>> name = "Fred Flintstone"
>>> name[0]
'F'
>>> name[0:5]
"Fred "
>>> name[2] = "X"
>>> name[1:14:3]
"r isn"
Variable name is of type <class 'str'>.
Illegal assignment statement because strings are immutable.
Indices are 1, 4, 7, 10, and 13.
See §3.8 for more information on using slices.
3.2.3.1 Immutable Sequences
Immutable sequences are sequences containing objects whose value cannot be changed after being created.
str
Represents strings. In v3, all strings are encoded in Unicode (this is a major difference from v2).
tuple A sequence of one or more objects, may be homogeneous (all of the same type) or heterogeneous (different types).
bytes An array of 8-bit bytes.
Immutable sequences, such as str and tuple, are hashable. Let me try to explain what that means. The dict data structure type, §3.2.5, is also called a map or an associative array, and is used to map keys to values,
>>> d = { 'fname': 'bart', 'lname': 'simpson'}
>>> d['fname']
bart
>>> d['lname']
simpson
d is a dict; key 'fname' maps to value 'bart' and key 'lname'
maps to value 'simpson'.
A hash function is used in the dict data structure to generate unique numeric keys from the symbolic keys. For examp le,
the symbolic key 'fname' might map to numeric key 2992 and the symbolic key 'lname' might map to numeric key 1002.
Since immutable sequences are hashable, we can use an immutable type such as tuple as a dict key, e.g.,
>>> t1 = (1,
>>> t2 = (4,
>>> d = {t1:
>>> d[t1]
'foo'
>>> d[t2]
'bar'
>>> d[(1, 2,
'foo'
>>> d[(4, 5,
'bar'
2, 3)
5, 6)
"foo", t2: "bar"}
t1 is a 3-tuple
t2 is a different 3-tuple
d is a dict with two keys: tuples t1 and t2.
Print the value to which tuple t1 maps to.
Print the value to which tuple t2 maps to.
3)]
Print the value to which tuple (1, 2, 3) maps to.
6)]
Print the value to which tuple (4, 5, 6) maps to.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 5
CSE294 Algorithmic Problem Solving
>>> d[(1, 3, 2)]
Traceback (most recent call first):
...
KeyError: (1, 3, 2)
Course Notes :: Introduction to Python (Rev 1.4)
Tuples are ordered so (1, 2, 3) and (1, 3, 2) are not the same tuple..
(1, 3, 2) is not a key in d so this operation will raise a KeyError exception.
Mutable sequences, since they can change value, are not hashable because the dict implementation requires constant keys.
3.2.3.2 Mutable Sequences
Mutable sequences are sequences containing objects whose value can be changed after being created.
list
A list of objects. May be homogeneous or heterogeneous, e.g, L = [1, 2, 3] or M = [1, "Fred", 2+3j].
bytearray Like bytes but each object is mutable.
As mentioned in §3.2.3.1, mutable sequences are not hashable and one effect of this is that mutable sequences cannot be
used as keys in a dict.
3.2.4 Sets
A set is an unordered finite collection of unique, immutable objects, i.e., mutable objects such as lists, cannot be stored in
a set. Sets are also nonindexable, e.g., if s is a set then s[0] = somevalue is an invalid assignment statement because we
cannot index the elements of s. Generally, elements are retrieved from a set by iterating over the elements of the set, e.g.,
>>> planets = {"mercury", "venus", "earth", "mars", "jupiter", "saturn", "neptune", "uranus"}
>>> planets[2]
Illegal because set objects are non-indexable.
>>> for p in planets:
Set elements can be retrieved by iterating over the element of the set.
print(p)
Prints "mercury", then "venus", then "earth", and so on.
Sets are also not hashable. Note that set elements may be homogeneous or heterogeneous, e.g., s = {1, 2, 3} or t = {1,
"Fred", 2 + 3j}.
3.2.5 Mapping or Dictionary
A mapping or dictionary is a finite set of objects indexed by index sets.
dict
A mapping of keys and values, e.g., d = {'fname' : 'kevin', 'lname' : 'burger'}. Here, 'fname' (a key) is
mapped to 'kevin' (a value) and 'lname' is mapped to 'burger'. d['fname'] evaluates to 'kevin' and d['lname']
to 'burger'.
If m is a mapping, then m[index] selects the element of m at index index. As discussed in §3.2.3.1 and §3.2.3.2, a key must
be an immutable object, i.e., one that cannot change value. This precludes a list object from being the key.
3.2.6 Callable Types
A callable type is one to which the function call operator () can be applied.
function
instance method
built-in function
class
A user-defined function object is like a function in all other languages.
An instance method is a function within a class definition that belongs to the object.
Functions that are built-in to the language, e.g., len(). See [1] for a list of built-in functions.
A class is callable, generally so as to act like a factory to create new objects of the class.
The definition of a function creates a function object that can be used in the same way that other objects can. For
example, a function may be passed as an argument to a function,
>>> def fact(n):
""" Return n! """
if n < 2:
return 1
else:
return n * fact(n - 1)
Defines the factorial function, returns n!
This is a docstring. Typing help(fact) will display the docstring.
0! = 1! = 1
n! = n * (n - 1)!
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 6
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
>>> def cube(n, funct):
""" Returns the cube of the return value from funct(n). """
x = funct(n)
return x * x * x
g is a function object that refers to cube().
Calls cube(3, fact) which returns (3!)3
>>> g = cube
>>> g(3, fact)
216
References
1. Python Std. Lib. - §2 Built-In Functions: https://docs.python.org/3/library/functions.html
3.2.7 Scripts and Modules
See [1, 2]. A script is a Python source code file that can be executed by the Python interpreter. The convention is that
scripts have a .py extension, e.g.,
# ascript.py
a = 1
b = 2
print(a + b)
This script can be interpreted by running python3 ascript.py from the command line or however your IDE does it. A
module is a file containing Python definitions of functions and statements, e.g.,
# fact.py
def fact(n):
if n < 2:
return 1
else:
return n * fact(n - 1)
# 0! = 1! = 1
# n! = n × (n-1)!
Scripts and modules appear to be the same thing, and in a way, they are, but the primary difference is that a module con tains class and function definitions that can be imported and used in other modules with the import statement while
scripts are like programs that are to be run.
>>> import fact
>>> print(fact.fact(4))
24
The syntax is: import module
We have to write module.function() to access the function.
The import statement imports every class and function definition from the module. To import just one definition,
>>> from fact import fact
>>> print(fact(4))
24
The syntax is: from module import definition
We can now omit the module. part when calling fact.fact().
Multiple definitions can be imported by writing from module import def1, def2, .... Python does not require a script
or module to have a main() function. The first statement that is executed is the one that appears first in the file, e.g.,
# args.py
import sys
# This statement is executed first
def print_args(args_list):
for a in args_list:
print(a)
# Next, this function definition is compiled
print_args(sys.argv)
# Next, this statement is executed
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 7
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
$ python3 args.py one two three
args.py
This value is sys.argv[0].
one
sys.argv[1].
two
sys.argv[2].
three
sys.argv[3].
The first executable statement of args.py is the import statement. After the import statement is executed, the function
definition of print_args() is seen and compiled into bytecode format, then the function call to print_args() takes place.
Scripts and modules have a __name__ attribute. When a module is imported, the __name__ attribute evaluates to
the name of the module sans the filename extension. For example, if we import args.py then __name__ evaluates to
"args". On the other hand, when args.py is executed as a script from the command line, __name__ evaluates to
"__main__" Therefore, it is common to create a Python source code file that can function as both a script and a
module,
# args.py
import sys
# This line is executed first
def main():
print_args(sys.argv)
# I like to provide a main() function, listed first in the file
# When the definition is seen by the interpreter, main() will be compiled
def print_args(args_list):
for a in args_list:
print(a)
# Next, the interpreter sees the definition of print_args(), which is
# now compiled
if __name__ == "__main__":
main()
# Were we invoked as a script? If so, execute main().
Now, when args.py is run from the command line, __name__ will evaluate to "__main__" and the if statement con dition will be true, so main() will be called to execute the program. On the other hand, if args.py is imported as a module,
__name__ will evaluate to "args" so the if statement condition will be false; main() will not be called, but the func tion
definitions of the module will be available for use in other scripts and modules.
References
1. Python Tutorial - §6 Modules: https://docs.python.org/3/tutorial/modules.html
2. Python Lang. Ref. - §5 The import system: https://docs.python.org/3/reference/import.html
3.2.8 Text File I/O, File Objects, Reading from Stdin and Writing to Stdout
The Python io module provides the main facilities for dealing with various types of I/O: text I/O, binary I/O, and raw
I/O. We will only discuss text I/O, which deals with string objects. Calling the built-in function open() and passing a
string argument as the file name will open a text file for reading or writing. open() returns a file object which is used as
a handle to file I/O methods.
>>>
>>>
...
>>>
>>>
fin = open("fileio.py", "r")
fout = open("fileio.out", "w")
Open fileio.py for reading, use fin (file input) as the file handle..
Open fileio.py for writing, use fout (file output) as the handle.
fin.close()
fout.close()
Streams should be closed when done reading or writing.
The base class used for text I/O streams is io.TextIOBase. The more useful methods of TextIOBase are listed in §16.2.3.4
of [3]. Specifically, familiarize yourself with these methods,
read(size)
readline()
write(s)
Read and return at most size characters from the file, returning a string.
Read until end of line or end of file and return the read text as a string. Note the end of line char is included.
Python converts the Windows text file end of line character sequence Carriage Return/Line Feed (ASCII
13/10) into a single Linefeed character, denoted '\n' (ASCII 10). readline() returns the empty string if the
end of file has been reached.
Write string s to an output text file. Returns the number of successfully written characters.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 8
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
A simple for loop can be used to read each line of a text file, one at a time, e.g.,
>>> for line in fin:
print(line)
Iterates over each line of the input file, line is a string object.
In this example, we just print each line.
Three special file objects sys.stdin, sys.stdout, and sys.stderr are automatically opened. Reading from sys.stdin in will read
text from the keyboard or, if stdin has been redirected, will read text from a file or some other Linux program. Writing to
sys.stdout will write text to the terminal or, if stdout has been redirected, to a text file or as input to another Linux program. In Unix systems, stderr is the stream to which error messages should be directed, although error messages are frequently directed to stdout.
The standard built-in function for reading input is the input() function which reads strings from sys.stdin. The input()
function has one argument, an optional string which is a prompt to be displayed on the terminal before reading input.
input() returns a str with the end of line character removed. Note: in Python 2, input is a statement not a function.
The standard built-in function for writing output is the print() function which writes text to sys.stdout. print() can have a
variable number of arguments specifying the text to be displayed. Following the list of objects to be printed are two
optional keyword arguments: sep which is ' ' (space) by default and end which is '\n' by default. sep is a string which
specifies the string to be printed as a separator between each pair of objects. Since it is the space character by default, a
single space is printed between each pair of objects. To specify that nothing is to be printed, pass sep = '' (two single
quote marks; alternatively, use "") as the argument to print(). The second default keyword is end which specifies the
string to be printed after the line of text is printed. The default is to print a newline character. If you want to print two
lines of text on the same line using two print() statements, then specify end = '' (or "") for the argument. Examples,
# print.py
x = input()
age = input("How old are you? ")
print("You are", age, " years old.")
print("You are", age, "years old.", sep=' ')
print("You are", age, "years old.", sep='**', end='')
print("Goodbye")
x = x + age
print(x)
x = int(x) + int(age)
print(x)
x = int(x + age) # an exception will occur because x is an int and age is a string
$ python3 print.py
34
No prompt was displayed, entered 34, so "34" is assigned to x.
How old are you? 31
Prompt is displayed. "31" is assigned to age.
You are 31 years old.
sep is ' ' by default.
You are 31 years old.
Specifying sep = ' ' is the same as not specifying sep.
You are**31**years old.Goodbye
** is printed between each pair of objects.
3431
String concatenation since x and age are both strings
3462
Convert "3431" to int, convert "31" to int, assign 3462 to x.
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'int' and 'str'
One last example. This code snippet simply sends the input read from sys.stdin to sys.stdout.
for line in sys.stdin:
line = line.strip()
print(line)
Removes leading and trailing whitespace from line.
Print line. Since \'n' was removed, all lines will print on the same console window line.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 9
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
References
1. Python Std. Lib. - §2 Built-In Functions - open(): https://docs.python.org/3/library/functions.html#open
2. Python Tutorial - §7 Input and Output: https://docs.python.org/3/tutorial/inputoutput.html
3. Python Std. Lib. - §16.2 io Module: https://docs.python.org/3/library/io.html#io-overview
4. Python Std. Lib. - §2 Built-In Functions - input(): https://docs.python.org/3/library/functions.html#input
5. Python Std. Lib. - §2 Built-In Functions - print(): https://docs.python.org/3/library/functions.html#print
3.3 Expressions and operators
See [1]. An expression is a combination of things (a highly technical term) which evaluates to a value at run-time, for
example, 2 * 3 - 5 evaluates to 11.
Arithmetic Conversions
Implicit arithmetic conversions occur when the operands of an operator are of two different types. If either operand is of
type complex, the other is converted to complex. If either operand is of type float, the other is converted to float. Other wise, both operands must be integers.
Atoms
See [2]. An atom is the most basic element of an expression and is either an identifier, a literal, or an enclosure.
Identifiers are names for things, e.g., the name of a variable or function. A literal is an immutable value of a specific data
type, e.g., 123 (int literal), 3.14 (float literal), 2+3j (complex literal), "abc" (string literal), [1, 2, 3] (list literal), (1, 2,
"Fred") (tuple literal), {1, 2, 3} (set literal), {'x': 1, 'y': 2} (dictionary literal). Enclosures consist of,
Parenthesized forms: ( expression_list )
List displays: [ expression_list ]
Set displays: { expression_list }
Dict displays: { key_datam_list }
(1, 2, 3) is a tuple
[1, 2, "Fred"] is a list
{ 'a', '1', 2+3j } is a set
{ 'x': 1, 'y': 2, 'z': (3, 4), 'a': [1, 2, 3] } is a dictionary
Operators
A list of the Python operators is shown below in order of decreasing precedence; note that a couple of the lesser-used
operators are omitted. Like most programming languages, any expressions inside parentheses are evaluated before expressions outside parentheses. Those expressions at the innermost level of parentheses are evaluated before those at the outer most level. Operators at the same precedence level are evaluated left to right. Unlike C/C++/Java, Python has an
exponentiation operator. Python, rather stupidly in my opinion, does not implement the increment/decrement operators.
Operator Precedence Table, see [3].
0. (expr), [expr], {expr}, {key:val}
Construct tuple (), construct list [], construct set {}, construct dict {}.
1. [idx], [idx1:idx2], expr(), .
Sequence subscript, sequence slicing, function call, access attribute, e.g., x.name
2. **
Power (exponentiation); right-associative: 2**3**4 is 2**(3**4), not (2**3)**4.
3. -, +, ~
Unary negation, unary plus, one's complement or binary NOT.
4. *, /, //, %
Mult, real division, floor division (integer division), modulus (works on reals).
5. +, Addition, subtraction.
6. <<, >>
Shift left, shift right.
7. &
Bitwise AND.
8. ^
Bitwise XOR.
9. |
Bitwise OR.
10. <, >, <=, >=, ==, !=
Relational comparisons. Note: a < b <= c is equiv to a < b and b <= c
in, not in, is, is not
Membership test.
11. not expr
Boolean/logical NOT.
12. and
Boolean/logical AND.
13. or
Boolean/logical OR.
14. if cond else expr
If-else conditional; equivalent to the C ternary operator ?:
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 10
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
An expression list containing at least one comma yields a tuple, e.g., in print(1, 2, 3), (1, 2, 3) is a tuple of len 3.
Similarly, return a, b, c causes the 3-tuple (a, b, c) to be created and returned. Weird syntax alert: to create a tuple
containing one value, one might expect that tuple-var = (value) would suffice, but since () can be used in expressions to
alter the default precedence, this statement will be interpreted as "assign value to variable tuple-var." Rather, write
tuple-var = (value), where the trailing comma tells the interpreter to treat value as a 1-tuple, e.g., a = 5, creates the 1tuple (5).
Assignment = and combined assignment (+=, -=, *=, etc) are not operators as they are in C++ and Java, rather they
are statements (more later). The symbol * can be used for repetition, e.g.,
"abc"*3 evaluates to "abcabcabc"
[1, 2, 3]*2 evaluates to [1, 2, 3, 1, 2, 3].
Note that 2 * 4 is 16 and not 2222; in this context * is interpreted as multiplication; use "2"*4 to generate "2222.
int("1" + "0"*100) is the integer 1 followed by 100 zeros, i.e., 10 100.
References
1. Python Lang. Ref. - §6 Expressions: https://docs.python.org/3/reference/expressions.html
2. Python Lang. Ref. - §6 Atoms: https://docs.python.org/3/reference/expressions.html#atoms
3. Python Lang. Ref. - §6 Operator Prec.: https://docs.python.org/3/reference/expressions.html#operator-precedence
3.4 Simple Statements
A simple statement is comprised of a single line of code; the different types of statements are discussed in [1] and in the
remainder of this section. By convention, Python programmers place one statement per line, but that is a convention I do
not always agree with so in some situations I like to write multiple statements on the same line; this can be done by sepa rating each pair of statements with a semicolon. In the remainder of this section, we will discuss the more useful statements. More information can be found at [1].
References
1. Python Lang. Ref. - §7 Simple Statements: https://docs.python.org/3/reference/simple_stmts.html
3.4.1 Expression Statement
Evaluates to a value, e.g., writing a ** b - 2 % c as a statement will cause the expression to be evaluated.
3.4.2 Assignment Statement
The assignment statement using = is used to bind or rebind a name to a value. Examples,
>>>
>>>
>>>
>>>
a = 3
b = 2 ** a - 5
a, b = 1, 2
a, b, c = foo(x, y, z)
Variable a is bound to the int 3.
The expression is evaluated to 3 and b is bound to 3.
Variable a is bound to 1 and b is bound to the 2.
Function foo() is called, returning a 3-tuple; a, b, c are bound to the tuple elements.
3.4.3 Augmented Assignment Statement
These statements function like the equivalent operators in C, C++ and Java,
+=
-=
*=
/=
augmented assignment
subtraction
multiplication
floating point division
//=
%=
<<=
>>=
floored division
modulus
shift left
shift right
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
&=
^=
|=
augmented bitwise AND
augmented bitwise exclusive-OR
augmented bitwise OR
Page 11
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
3.4.4 Pass Statement
The pass statement does nothing and is used in places where a statement is required but no code needs to be executed.
Example,
def sqr(n):
pass
# will implement later
# pass for now
3.4.5 Del Statement
The del identifier statement deletes the identifier named identifier from either the local or global namespace, e.g.,
# del.py
age = input("How old are you? ")
print("Your age is", age)
L = [age, age, age]
print(L)
del age
print(age)
del L
print(L)
$ python3 del.py
How old are you? 22
Your age is 22
['22', '22', '22']
Traceback (most recent call last):
...
NameError: name 'age' is not defined
Traceback (most recent call last):
...
NameError: name 'L' is not defined
3.4.6 Return Statement
The return statement is used to return an expression list from a function, e.g.,
def sqr(n):
return n * n
def foo(x, y):
x += 1
y -= 1
return x, y, z
# The interpreter packs x, y, z into the 3-tuple (x, y, z) and returns the tuple
3.4.7 Break and Continue Statements
The break and continue statements operate just as they do in C, C++, and Java.
3.4.8 Import Statement
Also see §3.2.8. There are several different forms of the import statement which is used to access definitions in other
modules. The two forms we will use are,
import module
from module import def1 [, def2, ...]
# imports all definitions from module module into this module
# imports only the definitions of def1, def2, ... from module
Note that import module is the same as from module import *. In the first form, all definitions in module are imported but in the second, only the listed definitions are imported. Example,
>>> import math
>>> print(math.log10(1000))
>>> from sys import argv
Imports all definitions from the math module.
Must refer to definitions by writing modname.defname
Imports only the definition of argv from the sys module.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 12
CSE294 Algorithmic Problem Solving
>>> if argv[1] == "-t": foo()
Course Notes :: Introduction to Python (Rev 1.4)
Must refer to definition of sys.argv as simply argv
When a module is imported, its __name__ attribute will be set to the name of the module; remember, with scripts, the
__name__ attribute will be set to the script filename.
3.5 Compound Statements
A compound statement is a statement which contains groups of other statements (compound statements are frequently
called blocks by C, C++, and Java programmers). In general, a compound statement spans multiple lines of code. A
compound statement consists of one or more clauses, where a clause consists of a header and a suite. A clause header is
an identifying keyword and ends with a colon. A suite is a group of statements controlled by a clause. For example, an if
statement is one type of compound statement,
if a < b:
c = d - e
x += 1
if a > 0: b -= 1
#
#
#
#
the header of this compound stmt is if a < b which is followed by a required colon
these two assignment stmts form a suite
note that the suite is indented one tab level beneath the header
a short compound stmt can be written on one line although this bothers some people
Be aware that Python does not use delimiting symbols, such as braces { ... }, to specify the beginning and end of a suite.
The suite ends with the first line of text that is not at the same indentation level as the suite. In the remainder of this
section, we will discuss the more useful compound statements. More information can be found at [1].
References
1. Python Lang. Ref. - §8 Compound Statements: https://docs.python.org/3/reference/compound_stmts.html
3.5.1 If Statement
The Python if statement is very similar in form and function to if statements in C, C++, and Java. Examples,
if a > b:
c = 1
x = 0
# this line is the clause header
# this line is the suite; notice the suite is indented
# this line is the next statement following the if statement; it is not part of the suite
if a > b:
c = 1
else:
d = 2
#
#
#
#
first clause header
first suite
second clause header
second suite
if gpa > 3.8:
print("Summa cum laude")
elif gpa > 3.6:
# elif is use rather than else if
print("Magna cum laude")
elif gpa > 3.4:
print("Cum laude")
else:
print("Well, at least you graduated)
3.5.2 While Statement
The Python while statement is very similar to its C, C++, and Java counterpart.
while a > b:
c -= 1 ; d = 2 + c
x = foo(c, d)
while
z
r
else:
z
# clause header
# these three statements are the suite
x - 1 != 4:
-= 1
+= 1
= r = 0
# if the conditional expression is false when first evaluated, then the statements
# in the else: suite are executed. Otherwise, they are not executed.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 13
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
3.5.3 For Statement
The for statement is used to iterate over the elements of a sequence or some other iterable object. To iterate means
to access each element of the sequence, one after the other, in order. The syntax is,
for target_list in expression_list:
suite
[ else:
suite ]
The expression_list is evaluated once and must evaluate to an object that can be iterated over. The suite is then executed
once for each object in expression_list. The else clause is optional; if present, it is executed once after the final iteration.
A common for loop that iterates over the integers in a range is created using the built-in range() function to generate the
expression_list. The syntax of range() is,
range(stop)
or
range(start, stop, [step])
The arguments to range() must be integers. start defaults to 0 if omitted and step defaults to 1. It is important to note
that [start, stop) is the interval that range() generates, i.e., [start, stop - 1] is the generated range. Examples,
range(10)
range(2, 9)
range(2, 101, 2)
range(10, 0, -1)
range(10, -3, -3)
when
when
when
when
when
iterated
iterated
iterated
iterated
iterated
over
over
over
over
over
yields:
yields:
yields:
yields:
yields:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Note range(10) is equivalent to range(1, 10, 1).
2, 3, 4, 5, 6, 7, 8. Equivalent to range(2, 9, 1).
2, 4, 6, 8, ..., 96, 98, 100.
10, 9, 8, 7, 6, 5, 4, 3, 2, 1.
10, 7, 4, 1, -2.
for i in range(10):
print(i)
# prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
for n in range(0, 101, 2):
print(n)
# prints 2, 4, 6, 8, ..., 96, 98, 100
for n in range(10, -3, -3):
print(n)
# prints 10, 7, 4, 1, -2
List = [2, 3, 5, 7, 11, 13, 17, 19]
for item in List:
print(item)
# define L as a list
# prints 2, 3, 5, 6, 11, 13, 17, 19
s = "Fred Flintstone"
for char in s:
print(char)
# define s as a str
# prints 'F', 'r', 'e', 'd', ..., 'n', 'e'
3.5.4 Function Definitions
A function definition is a compound statement. Functions operate the same as in C, C++, and Java. The function must
be defined before it can be called or executed. When calling the function, we may pass arguments to the function, in
sqrt(n), we refer to n as the function argument or simply argument. When defining a function that has arguments, we refer
to the variable names in the function definition header as parameters (some people and books use the terms actual
parameters and formal parameters in place of arguments and parameter). A function returns an expression list, see
§3.3, which means that a function can return as many values as it needs to. Parameters and variables that are created in
the function have local scope, meaning that the parameter or local variable becomes undefined when the function returns. Examples,
def sqr(n):
return n * n
# A function is a type. Q? What does print(type(sqr)) display?
# n is a parameter with local scope; we return 1 value
def cube(n):
return sqr(n) * n
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 14
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
def fact(n):
if n < 2:
return 1
else:
return n * fact(n - 1)
See §3.2.7. Note that Python does not require a main() function as in C, C++, and Java. For example, here is the standard Hello World program in Python.
# hello.py
print("Hello world.")
To create a module containing one or more functions and to designate one of those function as the main function,
# module-foo.py
def main():
# main() could be called anything, such as start() or begin()
n = input("Enter an integer > 0? ")
m = input("Enter an integer > 0? ")
print(foo(n, m))
def foo(x, y):
return x ** y / y ** x
if __name__ == "__main__":
main()
# if this module was executed as script, then call main()
__name__ is a module attribute (accessible as just __name__ within the module) that equates to the name of a
module when the module is imported into another module. When a module is executed as a script, __name__ equates to
the name of the script file sans the filename extension. Example,
# foo.py
print("__name__ in foo.py is", __name__)
def main:
print("Executing main() in foo.py")
if __name__ == "__main__":
main()
# bar.py
print("__name__ in bar.py is", __name__)
def main():
print("Executing main() in bar.py")
if __name__ == "__main__":
main()
# baz.py
import foo ; import bar
print("__name__ in baz.py is", __name__)
def main():
print("Executing main() in baz.py")
if __name__ == "__main__":
main()
$ python foo.py
__name__ in foo.py is __main__
Executing main() in foo.py
Run foo.py as a script. __name__ will be "__main__".
$ python bar.py
__name__ in bar.py is __main__
Executing main() in bar.py
Run bar.py as a script. __name__ will be "__main__".
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 15
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
$ python baz.py
__name__ in foo.py is foo
__name__ in bar.py is bar
__name__ in baz.py is __main__
Executing main() in baz.py
Run baz.py as a script. foo.py and bar.py are imported modules;
their __name__ attributes will be "foo" and "bar". Since baz.py is
run as a script, __name__ baz.py will be "__main__".
A convenient use for __name__ is to implement code that is only executed when the module is executed as a script;
common practice in Python is to implement code that will test the module. Example,
# baz.py
import foo
import bar
def main():
...
def test():
run_test_case1()
run_test_case2()
run_test_case3()
...
if __name__ == "__main__":
test()
else:
main()
#
#
#
#
When baz.py is executed as a script, __name__ will be "__main__" so
test() will be called to test the script. On the other hand, if the
module baz is imported into another module, __name__ will be "baz" so
main() will be called to initialize the module, if necessary.
3.6 Built-in Functions
Python has a number of built-in functions, see [1]. You should familiarize yourself with some of the more useful ones,
including the following (try these out in the interpreter): abs(), bin(), chr(), float(), hex(), input(), int(), len(), list(), max(),
min(), ord(), print(), range(), reversed(), round(), set(), sorted(), str(), sum(), tuple(), and type().
References
1. Python Std. Lib. - §2 Built-In Functions: https://docs.python.org/3/library/functions.html
3.7 Mathematical Functions
See [1]. The math module contains common mathematical functions that operate on integers and floats. Import the cmath
module for complex numbers functions. Example,
>>> import math
>>> from math import log
>>> print(math.sqrt(13))
3.605551275463989
>>> print(log(10)
Imports all definitions from the math module. Write math.funct() to call funct().
Import just the definition of log() from the math module. Write funct() to call funct().
Call sqrt() function. Note that we specify the module name.
Call log() function. Note that the module name must be omitted.
References
1. Python Std. Lib. - §9.2 math Module and Mathematical Functions: https://docs.python.org/3/library/math.html
3.8 Strings and the str Data Type
A Python string is a sequence of zero or more Unicode codepoints (characters). Python uses the built-in str data type to
represent strings. A string literal is a string which is enclosed in either double quotation marks, e.g., "Fred", or single
quotation marks, e.g., 'Fred'. If "" are used as the string delimiting characters then embedded ' marks are treated as
ordinary characters, e.g., "Fred said, 'Hello'" is the string literal Fred said, 'Hello'. The converse is also true. It is also
permissible to use \" or \' within a string literal to represent the literal " and ' characters, e.g., "Fred said, \"Hello\"" is
the string Fred said, "Hello".
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 16
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
See [2] for a list of string escape sequences. Since Python is based on C, many of the C, C++, and Java escape
sequences are the same in Python. More specifically, the reader should be comfortable using \n (newline or linefeed es cape
sequence), \\ (becomes literal \ char), \" (becomes literal " char), and \' (becomes literal ' char).
Python also supports raw strings which are string literals preceded by either r or R and within the string literals, no
escape sequences are recognized, e.g., in "C:\foo\bar", \f and \b will be interpreted as escape sequences. \f is the form
feed escape sequence (in the old days of teleprinters sending \f to the teleprinter would cause the paper to scroll up up to
the top of the next page) and \b represents the backspace character. However, if the programmer means to write a string
literal that represents a DOS pathname (go to drive C, go the foo subdirectory, and then go to the bar subdirectory) then
he or she has to either use \\ in place of the \ characters, e.g., "C:\\foo\\bar", or he or she can define the string literal as
a raw string, e.g., r"C:\foo\bar" is the string C:\foo\bar.
If, for some reason, a string literal needs to space several line of code, then a multi-line string literal can be written inside
a pair of """ characters.
String concatenation is performed using the + operator, e.g., "Fred" + " " + "Flintstone" results in "Fred Flintstone".
String repetition uses the * symbol to create a string literal contains two or more occurrences of the base string, e.g.,
"abc"*3 evaluates to "abcabcabc"; I am referring to "abc" as the base string. One use of this might be to create a large
integer value, e.g., "1" + "0"*100 becomes the string literal "1000...000" where there are one hundred 0 characters in the
string. This string can be turned into an int by calling int("1" + "0"*100); the return value is the integer 10100.
String objects are immutable, indexable, sequences. Indexable means we can access individual characters using indices (or
subscripts), e.g.,
"abcdef"[0] is "a"
"abcdef"[-1] is "f"
"abcdef"[-3] is "d"
Note: strings indices are numbered starting at 0.
A negative subscript means to start from the end of the string (EOL is at index 0).
If the EOL character is at index 0, then "abcdef"[-3] is the third char moving bw from the end.
String subsequences can be accessed using slice notation [i:j] and [i:j:k], see §3.2.3. Examples,
'abcdef'[2:4] is 'cd'
'abcdef'[:4] is 'abcd'
'abcdef'[3:] is 'def'
'abcdef'[2:99] is 'cdef'
'abcdef'[:] is 'abcdef'
Note that the characters at indices 2 and 3 are accessed, the char at index 4 is not included.
When i is omitted and k > 0, i defaults to the index of the first element; indices are 0 .. 3.
j is the index of the last element of the sequence plus 1 when omitted.
It is not an error to specify an index that is greater than the index of the last element.
i is 0 by default, and j is the index of the last element+1, consequently [:] is the entire string.
A third slice argument may be present [i:j:k]. In this case, the selected subsequence consists of those elements at indices i
+ 0·k, i + 1·k, i + 2·k, ..., and we stop when i+n·k ≥ j becomes true (remember, the element at index j is not included in
the slice). When omitted, k defaults to 1; examples,
'abcdefghij'[1:10:2] is 'bdfhj'
'abcdefghij'[:6:2] is 'ace'
'abcdefghij'[::3] is 'adgj'
Indices are 1, 3, 5, 7, and 9.
k > 0 and i is omitted, so i defaults to the index of the first element; indices are 0, 2, 4.
Indices are 0, 3, 6, 9.
Note that when k > 0 and i ≥ j, the selected subsequence is empty, i.e., "" is the result. When k < 0 the accessed element
indices are also at i + 0·k, i + 1·k, i + 2·k, ..., but we stop when i + n·k ≤ j becomes true. When k < 0 and j > i, the
selected subsequence is empty; examples,
'abcdefghij'[9:1:-1] is 'jihgfedc'
'abcdefghij'[:0:-1] is 'jihgfedcb'
'abcdefghij'[::3] is 'adgj'
Indices are 9, 8, 7, .., 2.
When k < 0, by default i is the index of the last element; indices are 9, , 8, ... 1.
Indices are 0, 3, 6, 9.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 17
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
An interesting "side effect" to the way slices operate is that it is possible to reverse the characters of a string using a slice,
>>> s = "abcdef"[::-1]
>>> s
fedcba
>>> s = s[::-1]
>>> s
abcdef
Assigns the reverse of "abcdef" to s.
Changes s to be the reverse of itself.
Being able to reverse a string in one line leads to a very short is_palindrome() function,
def is_palindrome(s):
""" Return true if s is a palindromic string. """
return s == s[::-1]
Nifty. We mentioned that strings are immutable, which essentially means that we cannot change the contents of the string
after it has been created. Practically, it means s = "abcdef"; s[2] = "x" is an illegal assignment to s[2] because we are
attempting to change the string.
The built-in len() function accepts any argument which is a sequence, including strings: len("abcdef") returns 6. The
Python Standard Library has several useful string methods, see [3]. You might familiarize yourself with the following:
capitalize(), find(), lower(), replace(), rfind(), split(), strip(), upper().
Finally, to convert a number into a string, call the built-in str() function, e.g., str(123) is "123", str(3.14) is "3.14", and
str(2.1 - 3.5j) is "3.1 - 3.5j". Conversely, to convert a string representing an integer into an int, use int(), e.g., int("123") is
123; to convert a string representing a floating point number into a float, use float(), e.g., float("3.14") is 3.14; and to
convert a string representing a complex number into a complex, use complex(), e.g., complex("2.1 - 5.2j") is 2.1 - 5j.
References
1. Python Std. Lib. - §7.1 Common String Operations: https://docs.python.org/3.1/library/string.html
2. Python Lang. Ref. - §2.4.1 String and Byte Literals: https://docs.python.org/3/reference/lexical_analysis.html
3. Python Std. Lib - §4.7.1 String Methods: https://docs.python.org/3/library/stdtypes.html#string-methods
3.8.1 C printf()-Style Formatting
The method discussed in this section is not the recommended Python3 way to print formatted output, but it will work for
us. See [2] for more information about the newer, recommended method for formatting output.
Python permits formatting of the output from a print() function call using a notation which is very similar to the method
used in C and C++ with the printf() function. First, string objects have a unique built-in operator, % which is the string
formatting operator. Given an expression of the format format-string % values, the string formatting operator will
replace conversion specifications in format-string with values from values. As mentioned, format-string is a string and
values must be a tuple, enclosed in (), unless a single value is being printed. Useful conversion specifications,
%d
%f
%x
%X
%e
%E
%c
%s
%%
int
float
hex with lowercase hex digits, e.g., 12bc
hex with uppercase hex digits, e.g., 12BC
exponential notation with lowercase e, e.g., 1.32e+23
exponential notation with uppercase E, e.g., 1.32E+23
single character
string
prints a single %
To print a value in a field of a specific width, use %wc where w is the field width and c is the conversion specification; the
value will be printed right-justified in the field with spaces as padding characters. To print the value in a left-justified field,
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 18
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
use %-wc, where the - sign indicates left-justification. The number of digits after the decimal point for a floating point
number is controlled by %.nf, where n is the number and f is the conversion specification. Examples,
a = 190
b = 3.14159265828
print("a = %d" % a)
#
print("a = %d, b = %f" % (a, b))
#
print("a = %d, b = %.3f" % (a, b))
#
print("%0x" % a)
#
print("0x%0x" % a)
#
print("0x%0X" % a)
#
print("a = %10d, b = %-10.3f." % (a, b))
prints a·=·190 (where · is a space char)
prints a·=·190,·b·=·3.141593 (6 digits after . are the default)
prints a·=·190,·b·=·3.142 (round to 3 digits after .)
prints be (190 base 10 = 0xBE)
prints 0xbe
prints 0xBE
# prints a·=········190, b·=·3.142····· (- left justifies)
References
1. Python Std. Lib. - §4.7: https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting
2. Python Std. Lib. - §6.1.3: https://docs.python.org/3/library/string.html#formatstrings
3.9 More on Lists
See [1-3]. A list is a mutable, indexable, sequence data type used to group values. The elements of the list may be homogeneous (all of the same type) or heterogeneous (of different types). Since lists are indexable, listvar[i] specifies the value in
listvar at index i. List indices are numbered starting at 0, so listvar[i] is the (i+1)-st element of the list. Lists are mutable
so it is permissible to assign a value to listvar[i].
A list literal is written as the list of values inside brackets, e.g., [1, 2, 3] is a list of three homogeneous elements. To
create an empty list, write listvar = list() or listvar = [], e.g., L1 = list() and L2 = [].
To add an element to the end of a list, call the append() method on the list variable, e.g., L1.append(2) changes L1 from []
to [2]. The same effect can be obtained using the += operator, e.g., L1 += [2] would also change L1 from [] to [2].
To append each of the elements of a list L3 to list L4, call the extend() method on L4, e.g., L4.extend(L3) or L4.extend([5,
6, 7]). In the second example, if L4 were [1, 2, 3, 4] before the call to extend(), then upon return L4 will be [1, 2, 3, 4, 5, 6,
7].
There is a subtle difference between append() and extend() which is important to understand: append() has a single
argument, which is appended to the list. The type of this argument may be just about anything. Consider,
>>>
>>>
>>>
>>>
>>>
>>>
L1 = [1, 2, 3]
L2 = [4, 5, 6]
t = (7, 8, 9)
L1.append('a')
L1.append(L2)
L1.append(t)
L1 is a list of length 3.
L2 is a list of length 3.
t is a 3-tuple.
L1 is now [1, 2, 3, 'a'] and is of length 4.
L1 is now [1, 2, 3, 'a', [4, 5, 6]] and is of length 5.
L1 is now [1, 2, 3, 'a', [4, 5, 6], (7, 8, 9)] and is of length 6.
Note that when L2 was appended to L1 that the list L2 = [4, 5, 6] was appended to L1 and not the elements of L2.
Similarly, when t was appended to L1 the tuple t = (7, 8, 9) was appended to L1 and not the elements of t. Now, consider
extend(),
>>>
>>>
>>>
>>>
>>>
>>>
L1 = [1, 2, 3]
L2 = [4, 5, 6]
t = (7, 8, 9)
L1.extend('a')
L1.extend(L2)
L1.extend(t)
L1 is a list of length 3.
L2 is a list of length 3.
t is a 3-tuple.
L1 is now [1, 2, 3, 'a'] and is of length 4.
L1 is now [1, 2, 3, 'a', 4, 5, 6] and is of length 7.
L1 is now [1, 2, 3, 'a', 4, 5, 6, 7, 8, 9] and is of length 10.
Note that when L1 was extended with L2 that the elements of L2 were appended to L1. Similarly, when L1 was extended
with tuple t, the elements of t were appended to L1.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 19
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
Being a sequence type, lists are sliceable, e.g., if L is [1, 2, 3, 4, 5] then L[1:3] consist of the elements of L at indices 1 and
2, which results in the sublist [1, 2]. L[:4] evaluates to [1, 2, 3, 4]. L[2:] evaluates to [3, 4, 5]. L[::-1] evaluates to [5, 4, 3, 2,
1] and L[3:1:-1] evaluates to [4, 3]. L[1:3] = ['a', 'b', 'c'] would change L from [1, 2, 3, 4, 5] to [1, 'a', 'b', 'c', 4, 5]. L = L[::1] makes L the reverse of L, i.e., the new value of L would be [5, 4, 3, 2, 1] after the assignment.
Two lists may be concatenated using either extend() or the + concatenation operator, e.g., if M is [6, 7, 8, 9, 10] then
L.extend(M) changes L to be [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and L = L + M also changes L to the same value.
The len() function—applicable to any sequence data type—can be applied to lists. If L is [1, 2, 3, 4, 6] then len(L) is 6.
The elements of a list may be just about any data type, including lists, which leads us to lists of sublists, e.g., L = [[1, 2],
[3, 4], [5], 6] is a list of length 4, where the first three elements are all lists themselves. To access the individual ele ments of
a sublist, we specify two subscripts, e.g., L[0][1] refers to the second element of the sublist at index 0 of L: this value is 2.
L[2][0] is the first element of the sublist at index 2 of L: this value is 5.
Two-, three-, and multidimensional arrays are created in Python as lists of sublists, e.g., consider this C array A which is a
two-dimensional array with three rows and three columns. The Python list equivalent is shown to the right,
int A[][] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Note:
A[0][0] is 1; A[0][1] is 2; A[0][2] is 3
A[1][0] is 4; A[1][1] is 5; A[1, 2] is 6
A[2][0] is 7; A[2][1] is 8; A[2][2] is 9
A list may be unpacked to separate the list elements, e.g., if L is [1, 2, 3] then a, b, c = L results in a being assigned 1, b
is assigned 2, and c is assigned 3. A ValueError exception is raised if the length of L does not match the number of variables on the left-hand side of the assignment statement. However, a, b = L[0:2] legally assigns 1 to a and 2 to b.
Reference [3] documents the list class methods. The more common methods that we are likely to use in our programs are
listed below. You should familiarize yourself with these,
L.append(x)
L.extend(x)
L.insert(i, x)
L.remove(x)
L.pop([i])
L.clear()
L.index(x)
L.count(x)
L.sort()
L.reverse()
L.copy()
copy.deepcopy(L)
Adds x to the end of L. x should be a single value.
Unpacks x and adds each individual value to L.
Inserts x into L before the element at index i. Note that insert() does not unpack x.
Removes the first occurrence of x from L. Raises a ValueError exception if x is not in L.
With no arg, removes and returns the last element of L. Otherwise, removes and returns the elem at i.
Makes L empty. Note this is equivalent to del L[:] (what does del L do?)
Returns the index in L of the first occurrence of x. Raises a ValueError exception if x is not in L.
Returns the number of occurrences of x in L.
Sorts the elements of L in-place into ascending or order. Set arg reverse to True for descending sort.
Reverses the elements of L in-place. Note this is equivalent to L[:] = L[::-1].
Returns a shallow copy of L. Note this is equivalent to L[:].
Returns a deep copy of L. To call copy.deepcopy() the copy module must be imported.
References
1. Python Tutorial - §3.1.3 Lists: https://docs.python.org/3/tutorial/introduction.html#lists
2. Python Tutorial - §5.1 More on Lists: https://docs.python.org/3/tutorial/datastructures.html
3. Python Std. Lib. - §4.6 https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range
3.9.1 List Example: Implementing a Stack Data Structure Type
A list may be used as a stack data structure, e.g.,
>>> stack = list()
>>> stack.append(1)
Creates an empty stack.
Push 1.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 20
CSE294 Algorithmic Problem Solving
>>>
[1]
>>>
>>>
[1,
>>>
>>>
[1,
>>>
>>>
3
>>>
[1,
>>>
>>>
3
>>>
[1,
Course Notes :: Introduction to Python (Rev 1.4)
stack
stack.append(2)
stack
2]
stack.append(3)
stack
2, 3]
top = stack[len(stack)-1]
top
Push 2.
stack
2, 3]
n = stack.pop()
n
When performing the peek operation, the top element was not removed.
Push 3.
Returns the element on top of the stack, i.e., a peek operation.
Returns the element on top of the stack, also removing it.
stack
2]
A stack is a commonly used data structure (remember, it is a LIFO structure) and because having to remember that
stack[len(stack)-1] is the peek operation, it may be helpful to implement a stack data type, which we shall do by creating a
class named Stack. Our Stack data type shall implement the following operations,
clear()
is_empty()
peek()
pop(n=1)
push(elem)
push_iterable(i)
size()
str()
Stack()
Remove all of the elements from the stack, making it empty.
Return True if the stack is empty.
Return the element on the top of the stack, without removing it.
Return the top element on the stack when n = 1; when n > 1, return a list of the top n elements
Push element elem onto the stack.
Iterate over the elements of i, pushing each element onto the stack.
Return the number of elements on the stack, as an int.
Return a string representation of the stack.
Create and return a new, empty stack.
See the stack.py source code file on the course website for the Stack class implementation, also shown below,
#***********************************************************************************************************************
# FILE: stack.py
#
# DESCRIPTION
# Illustrates how to write a class that implements a Stack data structure using a list to store the elements. Uses
# object composition, i.e., the list object is a data member of the Stack object. An alternative way to define the
# Stack class is to make Stack inherit from List.
#
# AUTHOR
# Kevin Burger ([email protected])
# Computer Science & Engineering
# Arizona State University, Tempe, AZ 85287-8809
# Web: www.devlang.com
#***********************************************************************************************************************
from copy import deepcopy
#=======================================================================================================================
# CLASS: Stack (note that Python convention is to capitalize class names)
#=======================================================================================================================
class Stack(object):
def __init__(self):
""" Create a new empty stack. """
self.clear()
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 21
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
def clear(self):
""" Remove all the elements of the stack, making the stack empty. """
self.__stack = list()
self.__size = 0
def is_empty(self):
""" Return true if the stack is empty. """
return self.__size == 0
def peek(self):
""" Return the top element on the stack, without removing it. """
return self.__stack[self.__size - 1]
def pop(self, n = 1):
"""
When n is 1, return the top element of the stack. When n is > 1, return the top n elements of the stack as
a list.
"""
popped = self.__stack[self.__size-1:self.__size-1-n:-1]
self.__stack = self.__stack[:self.__size-n]
self.__size -= n
return popped[0] if n == 1 else popped
def push(self, elem):
""" Push elem onto the top of the stack. """
self.__stack.append(elem)
self.__size += 1
return self
def push_iterable(self, iterable):
""" Push all of the elements of iterable into the stack. """
for elem in iterable:
self.__stack.append(elem)
self.__size += 1
return self
def size(self):
""" Returns the number of elements on the stack. """
return self.__size
def __str__(self):
""" Return a string representation of the stack. """
return "<Stack: __stack = " + str(self.__stack) + ", __size = " + str(self.__size) + ">"
def test_cmp(actual, expected, end_="\n"):
if actual == expected: print("pass", end=end_)
else: print("fail", end=end_)
def test():
# Testing constructor function Stack().
print("Testing constructor function Stack()... ", end="")
stack1 = Stack()
test_cmp(stack1.__str__(), "<Stack: __stack = [], __size = 0>")
# Testing push(int).
print("Testing push(int)... ", end="")
stack1.push(1).push(2).push(3).push(4)
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4], __size = 4>")
# Testing push(list).
print("Testing push(list)... ", end="")
stack1.push([1, 2, 3, 4])
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4, [1, 2, 3, 4]], __size = 5>")
# Testing push(tuple).
print("Testing push(tuple)... ", end="")
stack1.push((1, 2, 3, 4))
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4, [1, 2, 3, 4], (1, 2, 3, 4)], __size = 6>")
# Testing push(string).
print("Testing push(string)... ", end="")
stack1.push("abc")
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4, [1, 2, 3, 4], (1, 2, 3, 4), 'abc'], __size = 7>")
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 22
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
# Testing push_iterable(list). Reset __stack to [1, 2, 3, 4].
stack1 = Stack(); stack1.push_iterable([1, 2, 3, 4])
print("Testing push_iterable(list)... ", end="")
stack1.push_iterable(['a', 'b', 'c', 'd'])
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4, 'a', 'b', 'c', 'd'], __size = 8>")
# Testing push_iterable(tuple). Reset __stack to [1, 2, 3, 4].
stack1 = Stack(); stack1.push_iterable([1, 2, 3, 4])
print("Testing push_iterable(tuple)... ", end="")
stack1.push_iterable(('a', 'b', 'c', 'd'))
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4, 'a', 'b', 'c', 'd'], __size = 8>")
# Test push_iterable(string). Reset __stack to [1, 2, 3, 4].
# Should print "<Stack: __stack = [1, 2, 3, 4, 'F', 'r', 'e', 'd', "Wilma"]>"
stack1 = Stack(); stack1.push_iterable([1, 2, 3, 4])
print("Testing push_iterable(string)... ", end="")
stack1.push_iterable("Fred")
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4, 'F', 'r', 'e', 'd'], __size = 8>")
# Testing peek() -> element
print("Testing peek() -> element... ", end="")
x = stack1.peek()
test_cmp("x = {}".format(x), "x = d")
# Testing peek() -> sequence
stack1 = Stack(); stack1.push([1, 2, 3, 4])
print("Testing peek() -> sequence... ", end="")
x = stack1.peek()
test_cmp("x = {}".format(x), "x = [1, 2, 3, 4]")
# Testing pop(n = 1).
stack1 = Stack(); stack1.push_iterable([1, 2, 3, 4])
print("Testing pop(n=1)... ", end="")
x = stack1.pop()
test_cmp("x = {}".format(x), "x = 4", end_=", ");
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3], __size = 3>")
# Testing pop(n = 3).
stack1 = Stack(); stack1.push_iterable([1, 2, 3, 4, 5, 6, 7, 8])
print("Testing pop(n=3)... ", end="")
x = stack1.pop(3)
test_cmp("x = {}".format(x), "x = [8, 7, 6]", end_=", ");
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4, 5], __size = 5>")
# Testing size() on a non-empty stack.
print("Testing size() on a non-empty stack... ", end="")
length = stack1.size()
test_cmp("length = {}".format(length), "length = 5")
# Testing size() on an empty stack.
print("Testing size() on an empty stack... ", end="")
stack1.clear()
length = stack1.size()
test_cmp("length = {}".format(length), "length = 0")
# Testing shallow copy by assignment.
print("Testing shallow copy by assignment... ", end="")
stack1 = Stack(); stack1.push_iterable([1, 2, 3, 4, 5])
stack2 = stack1
stack2.push(6)
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4, 5, 6], __size = 6>", end_=", ")
test_cmp(stack2.__str__(), "<Stack: __stack = [1, 2, 3, 4, 5, 6], __size = 6>")
# Testing deep copy by calling copy.deepcopy().
print("Testing deep copy by calling copy.deepcopy()... ", end="")
stack1 = Stack(); stack1.push_iterable([1, 2, 3, 4, 5])
stack2 = deepcopy(stack1)
stack2.push(6)
test_cmp(stack1.__str__(), "<Stack: __stack = [1, 2, 3, 4, 5], __size = 5>", end_=", ")
test_cmp(stack2.__str__(), "<Stack: __stack = [1, 2, 3, 4, 5, 6], __size = 6>")
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 23
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
# Testing that is_empty() returns false on a non-empty stack.
print("Testing that is_empty() returns false on a non-empty stack... ", end="")
test_cmp("is_empty() returned {}".format(stack1.is_empty()), "is_empty() returned False")
# Testing that is_empty() returns true on an empty stack.
print("Testing that is_empty() returns true on an empty stack... ", end="")
stack1.clear()
test_cmp("is_empty() returned {}".format(stack1.is_empty()), "is_empty() returned True")
# Testing that clear() empties the stack.
print("Testing that clear() empties the stack... ", end="")
test_cmp(stack2.__str__(), "<Stack: __stack = [1, 2, 3, 4, 5, 6], __size = 6>", end_=", ")
stack2.clear()
test_cmp(stack2.__str__(), "<Stack: __stack = [], __size = 0>")
# If we are invoked as a script, call test() to perform testing. If we are invoked as a module, do nothing.
if __name__ == "__main__":
test()
When stack.py is executed as a script, the __name__ attribute will be "__main__" so test() will be called to perform
testing of the Stack class, e.g.,
$ python3 stack.py
Testing constructor function Stack()... pass
Testing push(int)... pass
Testing push(list)... pass
Testing push(tuple)... pass
Testing push(string)... pass
Testing push_iterable(list)... pass
Testing push_iterable(tuple)... pass
Testing push_iterable(string)... pass
Testing peek() -> element... pass
Testing peek() -> sequence... pass
Testing pop(n=1)... pass, pass
Testing pop(n=3)... pass, pass
Testing size() on a non-empty stack... pass
Testing size() on an empty stack... pass
Testing shallow copy by assignment... pass, pass
Testing deep copy by calling copy.deepcopy()... pass, pass
Testing that is_empty() returns false on a non-empty stack... pass
Testing that is_empty() returns true on an empty stack... pass
Testing that clear() empties the stack... pass, pass
On the other hand, when the Stack module is imported into another module, the __name__ attribute will be "Stack" so
test() will not be called but the Stack class and its instance methods will be available.
3.10 A Queue Data Structure
See [1]. A queue is a FIFO data structure and queues are commonly used in programming. The two standard queue opera tions for adding an element to the queue and removing an element from the queue are called enqueue and dequeue. The
Python list type is not suitable for implementing a queue because while list.pop()—aka enqueue—is O(1), list.insert()—
aka dequeue—is O(n), which is too slow. Fortunately, the Python Standard Library has class named deque (pronounced
"deck") which is in the collections module. The name deque is short for double-ended queue. The deque type permits
enqueue and dequeue operations from either queue end in O(1) time. To use deque as a standard single-ended queue, we
can choose to enqueue at the left end and dequeue from the right end. Examples,
>>>
>>>
>>>
>>>
1
>>>
from collections import deque
q = deque()
q.appendleft(1)
len(q)
q is empty.
q is [1].
q.appendleft(2)
q is [2, 1] where 1 is at the front of the queue.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 24
CSE294 Algorithmic Problem Solving
>>>
>>>
3
>>>
>>>
2
>>>
>>>
>>>
0
Course Notes :: Introduction to Python (Rev 1.4)
q.appendleft(3)
len(q)
q is [3, 2, 1] where 1 is at the front of the queue.
n = q.pop()
len(q)
n is 1, q is [3, 2] where 2 is at the front of the queue.
n = q.pop()
n = q.pop()
len(q)
n is 2, q is [3] where 3 is at the front of the queue.
n is 3, q is [] and is now empty
Familiarize yourself with these deque class methods,
append(x)
appendleft(x)
clear()
copy()
count(x)
extend(iter)
extendleft(iter)
pop()
popleft()
remove(x)
reverse(x)
Add element x to the right side of the deque.
Add element x to the left side of the deque.
Removes all elements from the queue so it becomes empty.
Create a shall copy of the deque.
Return the number of occurrences of x.
Iterates over the elements of iter, adding each element to the right end of the deque.
Iterates over the elements of iter, adding each element to the left end of the deque.
Remove and return the element from the right side of the deque.
Remove and return the element from the left side of the deque.
Remove the first occurrence of x starting from the left end.
Reverse the elements of the deque in-place.
A deque is a sequence data type, so len(d) will return the number of elements in d. Deque assignment, e.g., deque1 =
deque2 will perform a shallow copy. Use copy.deepcopy() to perform a deep copy. A deque is iterable, so for i in d: ...
would iterate over each element i of deque d.
References
1. Python Std. Lib. - §8.3.3 Deque: https://docs.python.org/3/library/collections.html#collections.deque
3.11 More on Tuples
See [1, 2]. The tuple data type is an immutable, indexable, sequence type consisting of one or more objects (often hetero geneous) separated by commas, with tuple literals being written as a pair of parentheses surrounding the tuple objects,
e.g., t = (1, 2, 3), makes t a 3-tuple consisting of elements 1, 2, and 3. Tuple examples,
>>> t = tuple()
>>> t = ()
>>> t = (1, 2, 3)
>>> type(t)
<class 'tuple'>
>>> t = (1)
>>> type(t)
<class 'int'>
>>> t = (1,)
>>> type(t)
<class 'tuple'>
>>> t = 1,
>>> type(t)
<class 'tuple'>
>>> t = 1, 2, 3
t is a new, empty tuple.
t is also a new, empty tuple.
t is a 3-tuple, the elements are 1, 2, and 3.
Prints the type of t.
You might think this would create a 1-tuple containing 1, but it does not, rather
(1) evaluates to the integer 1.
To create a 1-tuple, write a comma following the element.
() can be eliminated, the interpreter still knows we want to create a tuple so it
packs 1 forming the tuple: (1)
Again, () can be eliminated and the interpreter will pack 1, 2, and 3
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 25
CSE294 Algorithmic Problem Solving
>>> type(t)
<class 'tuple'>
>>> t
(1, 2, 3)
>>> a, b, c = t
>>> a, b = t
Traceback...
...
ValueError: ...
>>> len(t)
3
>>> t[0]
1
>>> t[2]
3
>>> t = ((1, 2), (3, 4))
>>> t[0]
(1, 2)
>>> t[0][0]
1
>>> t[0][1]
2
>>> t[1][1]
4
>>> t = ([1, 2], [3, 4])
>>> t[1][0]
3
>>> for item in t:
print(item)
[1, 2]
[3, 4]
>>> t[0] = [5, 6]
Traceback...
...
TypeError:...
>>> t = ([1, 2], [3, 4], [5,
>>> t[1:3]
([3, 4], [5, 6])
Course Notes :: Introduction to Python (Rev 1.4)
forming the tuple: (1, 2, 3).
Unpacks t and assigns the 3 elems of t to a, b, and c.
If there are fewer variables than tuple elements, a ValueError exception occurs.
tuple is a sequence type, so the built-in len() function returns the number of elems of t.
tuple is an indexable sequence type so we can access the individual elements.
using subscripts
Creates nested tuples, t is a 2-tuple with two elements: (1, 2) and (3, 4).
Use two subscripts to access the individual ints in the nested tuples.
t is a 2-tuple containing two lists as elements.
Since lists and tuples are both indexable, we can access the list elements this way.
tuple is an iterable data type so we can iterate over the elements of t.
tuples are immutable, a TypeError exception will occur if an attempt to change t is made.
6], [7, 8])
Since tuple is a sequence type, elements may be accessed using slices.
References
1. Python Tutorial - §5.3 Tuples and Sequences: https://docs.python.org/3/tutorial/datastructures.html
2. Python Std. Lib. - §4.6.5 Tuples: https://docs.python.org/3/library/stdtypes.html
3.12 More on Sets
A set is an unordered, mutable, nonindexable, iterable collection type, in which the elements of the set must be unique.
Set examples,
>>>
>>>
>>>
{1,
>>>
>>>
{1,
s = set()
s = {1, 2, 3}
s
2, 3}
s = {1, 2, 3, 3, 2, 1}
s
2, 3}
s is a new, empty set.
s is a homogeneous set containing three elements, all ints.
Print the value of s.
s is a still a set containing three elements because only unique values are stored.
Print the value of s.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 26
CSE294 Algorithmic Problem Solving
>>> s = {}
>>> t = {1, 3.1, "Fred"}
>>> s[0] = 22
Traceback
...
TypeError: ...
>>> 1 in s
True
>>> 99 in s
False
>>> 2 not in s
False
>>> for x in s: print(x)
1
2
>>> len(s)
3
>>> s.isdisjoint(t)
False
>>> s <= t
False
>>> t = {1, 2, 3, 4, 5}
>>> s <= t
True
>>> s < t
True
>>> s = {1, 2, 3, 4, 5}
>>> s <= t
True
>>> s < t
False
>>> s >= t
True
>>> s > t
False
>>> s == t
True
>>> s != t
False
>>> s = {1, 2, 3}
>>> s & t
{1, 2, 3}
>>> s = {'a', 'b'}
>>> t = {1, 2, 3}
>>> s | t
{'a', 1, 2, 3, 'b', 'c'}
>>> s = {1, 2, 3}
>>> t = {1, 2, 3, 4, 5}
>>> s - t
set()
>>> t - s
{4, 5}
>>> x = s
Course Notes :: Introduction to Python (Rev 1.4)
You might think that this creates a set named s but it actually creates a dict named s.
t is a heterogeneous set containing three elements, an int, a float, and a string.
sets are nonindexable so using the subscript operator will cause a TypeError exception.
The in and not in membership operators may be used to determine if a value is in a set.
set is iterable; elements are commonly accessed in an iterator loop.
set is a collection type, so the length of the set can be found using len().
isdisjoint() returns true if s and t have no elements in common.
False since {1, 2, 3} and {1, 3.1, "Fred"} have 1 in common so s and t are not disjoint.
True if s is a subset of t, i.e., if all of the elements in s are also in t.
False since 2 and 3 are in s but not in t.
Change t so s is subset of t.
True now since {1, 2, 3} is a subset of {1, 2, 3, 4, 5}.
True if s is a proper subset of t, i.e, if s is a subset of t but s does not equal t.
True since {1, 2, 3} is a subset of {1, 2, 3, 4, 5} and s and t are not equal.
Change s so s equals t.
True since s = {1, 2, 3, 4, 5} is a subset of t = {1, 2, 3, 4, 5}.
False since s is a subset of t but s equals t.
True since s = {1, 2, 3, 4, 5} is a superset of t = {1, 2, 3, 4, 5}, i.e., t is a subset of s.
False since s = {1, 2, 3, 4, 5} is a superset of t but s and t are equal.
True since s = {1, 2, 3, 4, 5} equals t = {1, 2, 3, 4, 5}
False since s = {1, 2, 3, 4, 5} equals t = {1, 2, 3, 4, 5}
Change s.
Forms the intersection of s and t, i.e., the set that consists of common elements.
{1, 2, 3} ∩ {1, 2, 3, 4, 5} is {1, 2, 3}
Change s.
Change t.
Forms the union of s and t, i.e., the set that consists of all elements from s and t.
{'a', 'b', 'c'} ∪ {1, 2, 3} is {'1', '2', '3', 'a', 'b', 'c'}. Note that sets are unordered.
Change s.
Change t.
Forms the difference of s and t, i.e., the set that consists of all elements from s
minus the common elements of s and t. Interpreter prints set() when the set is empty.
Forms the difference of t and s, i.e., the set that consists of all elements from t
minus the common elements of s and t.
x and s now refer to the same set {1, 2, 3}.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 27
CSE294 Algorithmic Problem Solving
>>> x.add(4)
>>> s
{1, 2, 3, 4}
>>> x
{1, 2, 3, 4}
>>> x.remove(4)
>>> s
{1, 2, 3}
>>> x
{1, 2, 3}
>>> s.remove(99)
Traceback: ...
...
KeyError: 99
>>> s.update(t)
>>> s
{1, 2, 3, 4, 5}
>>> s = {1, 2, 3}
>>> t = {2, 3, 4, 5}
>>> s.intersection_update(t)
>>> s
{2, 3}
>>> s = {1, 2, 3}
>>> s.difference_update(t)
>>> s
{1}
>>> s.discard(1)
>>> s
set()
>>> t
{2, 3, 4, 5}
>>> t.clear()
>>> t
set()
>>> s = {1, 2, 3}
>>> x = copy.deepcopy(s)
>>> x.add(4)
>>> s
{1, 2, 3}
>>> x
{1, 2, 3, 4}
Course Notes :: Introduction to Python (Rev 1.4)
Add 4 to set x. Since x and s refer to the same set, s = x = {1, 2, 3, 4}
Remove 4 from x. x and s still refer to the same set, so s = x = {1, 2, 3}.
A KeyError exception occurs if the set element does not exist.
update() modifies s to include all of the non-common elements of t.
Note that s |= t is equivalent to s.update(t).
intersection_update() modifies s to include only the elements common to s and t.
Note that s &= t is equivalent to s.intersection_update(t).
difference_update() modifies s to remove elements found in t.
Note that s -= t is equivalent to s.difference_update(t)
discard() is like remove(), but it does not raise an exception if the element does not exist.
Removed 1 from {1} so s is now empty.
Print t.
clear() removes all elements from the set, making it empty.
Initialize s.
Make x a deep copy of s, i.e., s and x refer to different set objects.
Adding 4 to x does not modify s.
Notice that s was unchanged when 4 was added to x.
x was, of course, changed.
References
1. Python Tutorial - §5.4 Sets: https://docs.python.org/3/tutorial/datastructures.html#sets
2. Python Std. Lib. - §4.9 Set Types: https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset
3.13 C-Like Structures
Suppose in C we wish to represent Cartesian coordinates using a structure to store the x and y coordinates,
typedef struct {
int x;
int y;
} point;
// point is equivalent to struct { int x; int y}
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 28
CSE294 Algorithmic Problem Solving
point p1;
p1.x = 10;
p1.y = 20;
printf("%d\n", p1.x + p1.y);
p1.x = p1.y;
printf("%d\n", p1.x + p1.y);
Course Notes :: Introduction to Python (Rev 1.4)
//
//
//
//
//
//
Define a point variable named p1.
Set p1's x data member to 10.
Set p1's y data member to 20.
Displays 30.
Change p1's x data member to be the same as y.
Displays 40.
Python does not have a built-in structure type, nor does it have a class in the library for creating structures. According to
the Stack Overflow page [1], there are various ways of simulating C-like structures. To me, the easiest and cleanest way is
to simply create a class that has instance variables corresponding to the data members of the C struct.
class Point(object):
def __init__(self):
self.x = 0
self.y = 0
# Point is a new class derived from object (Python convention caps class name)
p1 = Point()
print(p1.x, p1.y)
p1.x = 10
p1.y = 20
print(p1.x, p1.y)
#
#
#
#
#
# Create a data member named x initialized to 0.
# Create a data member named y initialized to 0.
Create a new point object named p1.
Displays 0 0
Change the value of the x data member
Change the value of the y data member
Displays 10 20
Later, if we need to augment our Point class to represent 3D points, we just modify the class,
class Point(object):
def __init__(self):
self.x = 0
self.y = 0
self.z = 0
p1 = Point()
print(p1.x, p1.y, p1.z)
p1.x = 10
p1.y = 20
p1.z = p1.x + p1.y
print(p1.x, p1.y, p1.z)
# Add a new member.
# Displays 0 0 0
# Displays 10 20 30
Alternatively, if one wants to require the structure data members to be initialized when the Point object is created, we can
write the __init__() function so it essentially acts as a constructor,
class Point(object):
def __init__(self, p_x, p_y):
self.x = p_x
self.y = p_y
#
#
#
#
Define a new class named Point.
__init__ is like a ctor (self is like this in C++/Java).
self.x is a data member initialized to parameter p_x.
self.y is a data member initialized to parameter p_y.
p = Point()
p = Point(10, 20)
print(p.x, p.y)
p.x = p.y
print(p.x, p.y)
#
#
#
#
#
Error: must pass initial values for x and i.
Create a Point object named p with p.x = 10, p.y = 20.
Displays 10 20
Change p.x to 20
Displays 20 20
Others on the Stack Overflow webpage go on to discuss alternative ways. Suggestions include the namedtuple class from
the collections module, which creates a standard tuple where the values can be referenced by names, e.g.,
from collections import namedtuple
Point = namedtuple("Point", "x y")
p = Point(x = 10, y = 20)
print(p.x, p.y, p[0], p[1])
#
#
#
#
Import collections.namedtuple class.
Create a namedtuple class named Point with x, y data members.
Create a new Point object initializing x and y.
Displays 10 20 10 20
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 29
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
Note that one advantage of namedtuple objects is that the data members can be accessed by name or by an index; they
can also be iterated over,
for q in p:
print(q)
# Displays 10 on the first pass (q is p.x) and 20 on the second pass (q is p.y).
You cannot index or iterate over the elements of the Point class defined above. The major problem I see with namedtuple
(and there may be an elegant workaround with which I am unfamiliar) is that the syntax for changing the value of a data
member is nasty—because tuples and namedtuples are immutable,
# Change x to 20? No, AttributeError exception: "can't set attribute".
# Creates a new Point namedtuple object with x = y = 20.
# Displays 10 20 10 20 rather than 20 20 20 20
p.x = 20
p._replace(x = 20)
print(p.x, p.y, p[0], p[1])
The above code does not work because _replace() does not modify p, it returns a new namedtuple object. Thus we have to
resort to,
p = p._replace(x = 20)
Now that is beyond ugly and there is no way I am going to write code like that. The next Stack Overflow suggestion is to
create a Point class and add the data members and their values to the default dictionary that every object contains,
class Point(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
# Create a new class named Point derived from object.
# __init__() is like a ctor
# Add the keyword args passed to __init__() to the default dict.
p = Point(x = 10, y = 20)
print(p.x, p.y)
p.x = p.y
print(p.x, p.y)
#
#
#
#
Create a Point object named p initializing p.x and p.y.
Displays 10 20
Changes p.x to 20
Displays 20 20
Hmm, that syntax is not too bad (other than the complete ugliness that is required to create the point class but just copyand-paste it). One downside is that unlike the namedtuple method, we cannot index the data members of the point object,
p[0] = 20 # Change x to 20? No, this is syntactically incorrect
nor can we iterate over them. But then again, with C structs, you cannot index the data members either. One advantage
of this "update the default dictionary" method is that we can easily add new data members,
print(p.x, p.y, p.z)
p.z = 30
print(p.x, p.y, p.z)
# AttributeError: 'point' object has not attribute 'z'
# Displays 20 20 30
That's pretty cool and does exactly what I would like a structure object to do. Finally, some on Stack Overflow advocate
using a dictionary,
p = {'x': 10, 'y': 20}
print(p.x, p.y)
print(p['x'], p['y'])
p['x'] = p['y']
print(p['x'], p['y'])
#
#
#
#
#
Create a Point object with 'x' and 'y' as data member names.
Nope, syntactically incorrect.
Displays 10 20 but this code is not pretty.
Change 'x' to 20.
Displays 20 20 but the code is still horrendously ugly.
What I dislike most about this method is that the data members (the keys of the dictionary) cannot simply be x and y,
they have to be the strings 'x' and 'y'. This leads to nasty syntax for accessing the data members. Python dictionaries
seem to me to be a bad choice for implementing a C-like struct. Out of all of my choices, I prefer the "update the default
dictionary" method.
References
1. Stack Overflow: http://stackoverflow.com/questions/35988/c-like-structures-in-python
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 30
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
3.14 Classes
To create a class we must write a class definition statement, with this syntax,
class class-name(superclass-name):
statement1
statement2
...
statement
The statements are commonly function definition statements, but can include other types of statements as well, e.g.,
# Fraction.py
class Fraction(object):
def __init__(self, num, den):
self._num = num # _varname is Python-speak for protected. _varname can be accessed in subclasses.
self._den = den # __varname is Python-speak for private. __varname cannot be accessed in subclasses.
def add(self, f2):
num = self._num * f2._den + self._den * f2._num
den = self._den * f2._den
return Fraction(num, den)
# Not all statements in a class definition have to be function definitions. However, these statements
# are only executed once: when the class definition is compiled to create the Fraction class object.
class_var = -1
# Simulates a class variable which is shared among all objects.
print(class_var) # Note: this statement is also only executed once when Fraction is compiled.
Classes are created (compiled) at run-time when the class definition statement of a module is reached as the interpreter is reading the module or script. The result from compiling a class is a class object, e.g.,
# At this time, Fraction is a class object, i.e., in Python classes are objects. An instance object is
# like a regular object in C++ and Java. Create three Fraction instance objects: f1, f2, and sum.
f1 = Fraction(1, 3)
f2 = Fraction(3, 5)
sum = f1.add(f2)
# Creates a Fraction instance object with f1.num = 1 and f1.den = 3.
# Creates another Fraction instance object with f2.num = 3 and f2.den = 5.
# Calls f1.add() passing f2 as the argument. A Fraction object is returned.
Attributes are identifiers following the dot operator, e.g., f1._num is an attribute reference to a data attribute
named _num (which is an integer). Data attributes are the same as instance variables in Java and data members in
C++. The other type of attribute is a method. A method is a function definition that "belongs" to the object. The term
"method" is used with other object types, i.e., objects that are not class instance objects. Consequently, f1.add() is an
attribute reference to a (class) method object. To confuse things more, Fraction.add is a function object and acts like
a function pointer in C and C++.
A method attribute reference, e.g., sum = f1.add(f2) is equivalent to sum = Fraction.add(f1, f2).
Class operations: class objects (essentially, the class definition) support two kinds of operations: attribute references
and instantiation. The syntax of an attribute reference (whether to a data attribute or to a function object) is,
obj-name.attribute-name
For example, f1._num, f1._den, Fraction.__init__, and Fraction.add are all valid attribute references. The first two are
attribute references to data attributes of f1. The latter two do not call the functions, but rather return function objects
(more on function objects in a bit).
Class instantiation takes place by calling a class object and uses function notation, e.g., f1 = Fraction(10, 20) creates a
new instance of Fraction, and as mentioned above, f1 is an instance object.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 31
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
The special instance method __init__() (you should never write a function in Python that starts and ends with __; this
notation is reserved for special language-specific functions) is called after an instance object is instantiated. The job of
__init__() is to initialize the instance object, generally by creating and initializing the object's data attributes. The first
argument to __init__() is a reference to the instance object being initiated, and conventionally, this argument is named
self (self is like this in C++ and Java). As shown in Fraction.__init__(), __init__() can have additional arguments,
but self must be the first one. Note: we never explicitly pass self as an argument to __init__() and the other class
methods: the Python interpreter will automatically include self in the call.
Instance objects: the only operation understood by instance objects are attribute references which are either references
to data attributes, e.g., f1._num, or methods, e.g., f1.add(f2).
Method objects: a method is "bound" by writing something like obj-name.method-name(...) and is usually called
directly thereafter. However, in x = Fraction.add (note the missing parentheses), x is bound to method object Fraction.
add() but it not directly called. For example,
def main():
f1 = Fraction(1, 3)
f2 = Fraction(3, 5)
ref_add = Fraction.add
sum = foo(f1, f2, ref_add)
def foo(a, b, f):
return f(a, b)
#
#
#
#
f1 is a Fraction instance object.
f2 is a Fraction instance object.
ref_add is a function object, referring to Fraction.add.
Illustrates that function objects can be passed as args.
# Since f refers to Function.add this is essentially performing return a.add(b)
Class and instance variables: An instance variable (properly, an instance data attribute) is created in the instance
object for each instance object that is instantiated. A class variable (properly, a class data attribute) "belongs" to the
class and is shared among all instance objects of the class. For example, in Fraction, class_var is a class data attribute
since it is defined within the Fraction class definition but outside the function definition statements of the Fraction class.
All Fraction instance objects share class_var, e.g.,
import Fraction
def main:
f1 = Fraction(1, 3)
print(f1, sep=" ", end="")
print(" class_var = ", f1.class_var)
Fraction.class_var = 99
print("class var = ", f1.class_var)
f2 = Fraction(3, 5)
print("f1.class var = %d, f2.class_var
# f1 is a Fraction instance object.
# Invokes print(f1.__str__()).
# Prints -1 since Fraction.class_var was initialized to -1.
# Change Fraction.class_var from -1 to 99.
# Prints 99 since Fraction.class_var has changed.
# f2 is a different Fraction instance object.
= %d" % (f1.class_var, f2.class_var)) # Prints 99 99
Note that class data attributes must be changed by writing class-name.class-attrib = new-value and not by instanceobj.class-attrib = new-value. Continuing from above,
def main:
...
print("f1.class var = %d, f2.class_var = %d" % (f1.class_var, f2.class_var)) # Prints 99 99
f1.class_var = 100
print("f1.class var = %d, f2.class_var = %d" % (f1.class_var, f2.class_var)) # Prints 100 99
print("Fraction.class_var = %d" % (Fraction.class_var))
# Prints 99 99
When f1.class_var was assigned 100, this created a new instance data attribute named class_var within the f1 instance
object, so now f1.class_var is 100 but Fraction.class_var is still -1. Furthermore, f2.class_var still refers to the same value
as Fraction.class_var, so printing f2.class_var will still print 99.
Random remarks: Data attributes override methods with the same name, e.g., a data attribute named num might
conflict with a class function named num(). There are a couple of acceptable solutions to solve this problem: (1) do not
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 32
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
define a method with the same name as a data attribute, or vice versa; or (2) prefix data attributes or method names with
a unique identifier, for example m_num, and m_den for data attributes for the numerator and denominator and method
names num() and den() for accessor functions for the data members.
The reference to the object self is named "self" by convention. We could name it this, or something else, if we felt more
comfortable doing that. However, self is well-engrained in the Python community, so don't do that.
Each value (integer, real number, list, etc) in Python is an instance object and therefore has a class (also called its type).
The type of the object can be determined by calling the type() built-in function. For example, type(7) is <class 'int'>. The
type is stored in a special class variable named __class__, e.g., if f1 is a Fraction instance object, then type(f1) is <class
'__main__.Fraction'> and f1.__class__ is also <class '__main__.Fraction'>.
References
1. Python Tutorial - §9 Classes: https://docs.python.org/3/tutorial/classes.html
4 The Python Standard Library
Like many other high-level programming languages, Python has a fairly large Standard Library, see [1].
References
1. Python Standard Library: https://docs.python.org/3/library/index.html
4.1 Shallow and Deep Copies: The copy Module
Assignment statements do not copy objects; rather, they create a binding between an identifier and the object. Example,
>>>
>>>
>>>
[1,
[4,
>>>
>>>
[1,
[1,
>>>
>>>
[9,
[9,
L1 = [1, 2, 3]
L2 = [4, 5, 6]
print(L1, L2)
2, 3]
5, 6]
L2 = L1
print(L1, L2)
2, 3]
2, 3]
L2[0] = 9
print(L1, L2)
2, 3]
2, 3]
L2 and L1 refer to the same list, so L2 is a shallow copy of L1.
Any changes to L2 will also change L1 since they refer to the the same object.
Making a deep copy of an object, will cause a new object to be created so the original object and the new object will
refer to different values. To make a deep copy, we use the copy.deepcopy() function of the copy module.
>>>
>>>
>>>
>>>
[1,
[4,
>>>
>>>
[1,
[1,
>>>
>>>
[1,
[9,
from copy import deepcopy
L1 = [1, 2 ,3]
L2 = [4, 5, 6]
print(L1, L2)
2, 3]
5, 6]
L2 = deepcopy(L1)
print(L1, L2)
2, 3]
2, 3]
L2[0] = 9
print(L1, L2)
2, 3]
2, 3]
We can refer to copy.deepcopy() as just deepcopy().
L2 becomes a deep copy of L1 so they refer to different lists.
Changes to L2 do not affect L1 since they refer to different lists.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 33
CSE294 Algorithmic Problem Solving
Course Notes :: Introduction to Python (Rev 1.4)
References
1. Python Std. Lib. - §8.10 The copy Module: https://docs.python.org/3/library/copy.html
4.2 The decimal Module
The decimal module provides support for exact real numbers with an arbitrary number of digits after the decimal point.
Examples,
>>> import decimal
>>> getcontext().prec = 30
>>> print(Decimal(1) / Decimal(7))
0.142857142857142857142857142857
>>> getcontext().prec = 50
>>> print(Decimal(13).sqrt())
3.6055512754639892931192212674704959462512965738452
Prints 1 / 7 with 30 digits of precision.
Prints sqrt(13) with 50 digits of precision.
References
1. Python Std. Lib. - §9.4 The decimal Module: https://docs.python.org/3/library/decimal.html
Revision Information
Rev 1.0 - 16 Jan 2016
Original release.
Rev 1.1 - 20 Jan 2016.
Corrected minor types on pp. 5, 6.
Added "Dict displays" to the list of atoms on p. 5.
Explained how to create a tuple with one value on p. 5.
Added a discussion of the global variable __name__ on p. 9.
Rev 1.2 - 17 Feb 2016
Added a discussion of C-like structures in Sect 3.12.
Rev 1.3 - 12 Sep 2016
Rewrote the entire document, adding new material and editing existing material to make it more readable.
Rev 1.4 - 22 Jan 2017
Minors edits to improve clarity or correct mistakes.
(c) Kevin R. Burger :: Computer Science & Engineering :: Arizona State University
Page 34