Python
67557
Lecture 2
CS.HUJI
Fall 2014 - "
Dr. Arie Schlesinger
Containers of data
Motivation: keep data and processing
tools close by,
11/8/2014 10:37:29 PM
Some classifications
Simple objects, :
int, float, bool (non iterable)
Containers of objects : (iterable)
str, list, tuple, range, set, frozenset, dict
11/8/2014 10:37:29 PM
Order
Sequences: ordered Containers
A sequence is a container whose elements are ordered
and can be accessed by their position index, starting
from 0. Example, the 1st element in the string:
>>> s=abc
>>> s[0]
a
Containers: strings, lists, tuples, range,..
Not Sequences-unordered Containers
- Can not index their elements: sets, frozensets, dictionaries
11/8/2014 10:37:29 PM
Freedom
Mutable: list,
set, dictionary
- Contents can be changed :
- add , remove, change elements.
Immutable: strings, tuples,
frozenset, range
- No changes can be made
(Not containers: int, float, bool )
11/8/2014 10:37:29 PM
The two titles every container
holds
there are more
Sequence, Mutable: list
Sequence, Immutable: string, tuple, range
Not sequence, Mutable
: set, dictionary
Not sequence, Immutable : frozenset
11/8/2014 10:37:29 PM
What about the titles of the
non containers ?
No Sequence, Immutable : int,
float, bool
(no order, no freedom to change)
11/8/2014 10:37:29 PM
sequences
strings, lists, tuples, range
11/8/2014 10:37:29 PM
Sequences
Tuples
Contain 0 or more items of mixed types, including other
containers Immutable
Strings
Contain a seq of 0 or more single chars Immutable
Lists
Contain a seq of 0 or more items of mixed types, including
other containers Mutable
Ranges
Contain
a seq of 0 or more ordered integers ! - immutable
11/8/2014 10:37:29 PM
Similar Syntax
The three sequences types : tuples, strings, and
lists, have similar syntax and functionality
Therefore most operations on all sequences, can be
demonstrated on one seq, to illustrate the others
11/8/2014 10:37:29 PM
10
Sequences
Tuples : defined using parentheses, and commas.
>>> tup = (12, 'bcd', 3.45, (1,2), 'efg')
Lists : defined using square brackets, and commas.
>>> liz = ["bcd", 23, 3.23, 12]
Strings are defined using quotes (", ', or """).
>>> st = "abc"
>>> st = 'abc'
>>> st = """an example
of a multi-line string that uses triple quotes."""
Empty seq: [], (), ''
11/8/2014 10:37:29 PM
11
Sequence indexing
11/8/2014 10:37:29 PM
12
Indexing
You can access individual elements of a tuple, list, or string
using square bracket indexing notation, ( 0 based)
>>> tup = (12, bcd, 3.45, (1,2), efg)
>>> tup[1] # 2nd element in the tuple.
bcd
>>> liz = [bcd, 23, 3.23, 12]
>>> liz[1] # 2nd element in the list.
23
>>> st = bcd
>>> st[1] # 2nd char in string.
c
The index is an expression that evaluates to
an
int
11/8/2014
10:37:29 PM
13
Positive and negative indices
>>> tup = (12, bcd, 3.45, (1,2), efg)
Positive index: count from the left, starting with 0.
>>> tup[1]
bcd
Negative index:count from right, starting with the last
element, represented by index: -1
>>> tup[-3] # the 3rd from the end
3.45
11/8/2014 10:37:29 PM
14
Sequence slicing
11/8/2014 10:37:29 PM
15
Slicing
>>> tup = (12, bcd, 3.45, (1,2), efg)
>>> t[1:4]
(bcd, 3.45, (1,2))
Return a same-class-container, with a subset of the
original members.
It starts copying from the first index, and stops
copying before the second index.
negative indices can be used :
>>> t[1:-1]
(bcd, 3.45, (1,2))
11/8/2014 10:37:29 PM
16
Slicing defaults
>>> tup = (12, bcd, 3.45, (1,2), efg)
Without a first index, it starts from position 0:
>>> t[:2]
(12, bcd)
Without the second index, it starts at the first index
until end of the container.
>>> t[2:]
(3.45, (1,2), efg)
11/8/2014 10:37:29 PM
17
What indexing, and slicing return
Strings return strings:
Indexing: returns the one-char string at index pos.
Slicing : returns the substring specified (a new string)
Lists, tuples return:
Indexing: returns the element at index position
Slicing : returns a new seq as specified
(element can be simple or compound: int,string, list ,)
11/8/2014 10:37:29 PM
18
indexing slicing doc
http://docs.python.org/2/library/stdtypes.html#
sequence-types-list-tuple-range
11/8/2014 10:37:29 PM
19
Copying the Whole Sequence
[:] makes a copy of an entire sequence.
>>> tup[:]
(12, bcd, 3.45, (1,2), efg)
>>> list1=[1,[2,3],4]
Two diff names of one seq:
>>> list2 = list1 # 2 names refer to 1 ref
# NEW: Changing one affects both
Shallow copy: Two diff names of two diff seq
>>> list3 = list1[:]
(copying will b back..)
11/8/2014 10:37:29 PM
20
The in Operator
membership test, returns True or False :
>>> t
>>> 3
False
>>> 4
True
>>> 4
False
= [1, 2, 4, 5]
in t
in t
not in t
11/8/2014 10:37:29 PM
21
Membership for strings
tests for substrings of 1 or more adjacent chars
>>> a = 'abcde'
>>> 'c' in a
True
>>> 'cd' in a
True
>>> 'ac' in a
False
Careful: the in keyword is also used in the syntax of for loops
and list comprehensions.
11/8/2014 10:37:29 PM
22
The + Operator
The + operator produces a new tuple, list, or
string whose value is the concatenation of its
arguments.
>>> (1, 2, 3) + (4, 5, 6)
(1, 2, 3, 4, 5, 6)
>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> The + + Beatles
The Beatles
11/8/2014 10:37:29 PM
23
The * Operator
The * operator produces a new tuple, list, or
string that repeats the original content.
>>>
(1,
>>>
[1,
(1, 2, 3) *
2, 3, 1, 2,
[1, 2, 3] *
2, 3, 1, 2,
3
3, 1, 2, 3)
3
3, 1, 2, 3]
>>> Hello * 3
HelloHelloHello
Its operands are a seq, and an int
11/8/2014 10:37:29 PM
24
Mutability:
Tuples vs. Lists
11/8/2014 10:37:29 PM
25
Tuples: Immutable
>>> tup = (12, bcd, 3.45, (1,2), efg)
>>> tup[2] = 2
TypeError: object doesn't support item assignment
You cant change a tuple.
You can make a fresh tuple and assign its
reference to a previously used name.
>>> tup = (12, bcd, 2, (1,2), efg)
After the assignment, tup is now the name of the new
tuple
11/8/2014 10:37:29 PM
26
Lists: Mutable
Lists are mutable: it is possible to change their
content (strings are immutable)
Assign to a legal position:
>>> liz = [abc, 12, 4.34, 23]
>>> liz[1] = 35 # assignment
>>> liz
[abc, 35, 4.34, 23]
11/8/2014 10:37:29 PM
27
More examples
>>> myList
[1, 'a', -2.7]
>>> myList[0]='Iosi'
>>> myList
['Iosi', 'a', -2.7]
We can change lists in place.
myList is still the name of the same container
at the same address ,when were done.
11/8/2014 10:37:29 PM
28
Assignment to slices1
Assignment to slices can even change the size of
the list or clear it entirely:
>>> letters =['a,'b,'c,'d,'e,'f,'g']
# replace some values
>>> letters[2:5] = ['C', 'D', 'E']
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
11/8/2014 10:37:29 PM
29
Assignment to slices2
# now remove them
>>> letters[2:5] = []
>>> letters
['a', 'b', 'f', 'g']
# clear the list by replacing all the elements with an
empty list
>>> letters[:] = []
>>> letters
[]
([] is the destroyer tool)
11/8/2014 10:37:29 PM
30
len() works with all sequences
>>> letters = ['a', 'b', 'c', 'd']
>>> len(letters)
4
11/8/2014 10:37:29 PM
31
nesting lists
Create lists containing other lists:
>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c'] # list a
>>> x[0][1]
'b'
11/8/2014 10:37:29 PM
32
For your lists Only..1
>>> liz1 = [1, 1, 3, 4, 5]
>>> liz1.append(x) # a method of lists
>>> liz1
[1, 1, 3, 4, 5, x]
>>> liz1.insert(2, y)
>>>liz1 [1, 1, y, 3, 4, 5, x]
11/8/2014 10:37:29 PM
33
The extend method vs the
operator +
+ creates a fresh list (with a new memory
reference)
extend operates on liz1 in place.
>>> liz1.extend([9, 8, 7])
>>> liz1
[1, 2, i, 3, 4, 5, a, 9, 8, 7]
11/8/2014 10:37:29 PM
34
Append
>>> x = [1, 2, 3]
>>> x.append([4, 5])
>>> x
# appends its arg packed as it comes
[1, 2, 3, [4, 5]]
11/8/2014 10:37:29 PM
35
Extend
>>> x = [1, 2, 3]
>>> x.extend([4, 5])
>>> x
# extend unpacks its arg
[1, 2, 3, 4, 5]
11/8/2014 10:37:29 PM
36
For your lists Only ..2
>>> liz4 = [a, b, c, b]
>>> liz4.index(b)
1
>>> liz4.count(b)
2
>>> liz4.remove(b)
>>> liz4
[a, c, b]
11/8/2014 10:37:29 PM
37
For your lists Only ..3
>>>
>>>
>>>
[8,
li = [5, 2, 6, 8]
li.reverse() # reverse the list in place
li
6, 2, 5]
>>> li.sort() # sort the list in place
>>> li
[2, 5, 6, 8]
11/8/2014 10:37:29 PM
38
Tuples vs. Lists
Lists can be modified, and they have lots of
handy operations we can perform on them.
Tuples are immutable and have fewer
features.
To convert between tuples and lists use the
list() and tuple() functions:
>>> li = list(tu)
>>> tu = tuple(li)
11/8/2014 10:37:29 PM
39
More on list(),tuple()
list(iterable), tuple(iterable) are constructors that
decompose their arg and create a list/tuple from its
elements:
>>> list('abc')
['a', 'b', 'c']
>>> list([1,2])
[1, 2]
>>> list((11,22))
[11, 22]
>>> list(12)
TypeError: 'int' object is not iterable
(other types have similar constructors: set(), dict()
which decompose some iterable and use its elems)
The magic of tuples
The Magic of Tuples
>>> a=(1,2)
>>> b=1,2
# a tuple without
parens
>>> a
(1, 2)
>>> b
(1, 2)
42
From Tuples Unpacking to Swap
>>>
>>>
1
>>>
2
>>>
>>>
11
>>>
22
x,y=(1,2) # tuple unpacking
x
y
x,y=11,22 # also tuple unpacking
x
y
43
Swap
>>> x,y=y,x
>>> x
22
>>> y
11
>>> x,y
(22,11)
# swap is a tuple unpacking !!
# just writing like that, creates a tuple
44
Swap de luxe
Assume:
>>> a=1; b=2
>>> a
1
>>> b
2
# swap de lux made by unpacking
>>> a,b=b,a+b
>>> a
2
>>> b
3
45
From Swap de luxe to .. Fibonacci
>>> a=0; b=1
>>> for i in range(5):
a, b = b, a+b
print b,
1 2 3 5 8
46
The range() Function
11/8/2014 10:37:29 PM
47
range,xrange
The built-in function range([i,]j [,step])
creates an object that represents a range of integers
k such that i <= k < j.
i, step are optional, and have default values of 0
and 1, respectively.
range(10), range(0,10),range(3,21,4)
An xrange() object calculates its values only when accessed, in a for loop
or with a list(), tuple() constructor
although a xrange object looks like a sequence, it is
actually somewhat limited.
For example, slicing is not supported.
11/8/2014 10:37:29 PM
48
xrange: when, what, why
convenient when long sequences of integers are
needed.
xrange does not create a sequence of integers.
It creates a generator function able to produce
each next item of the sequence when needed.
This saves memory, especially for long lists.
11/8/2014 10:37:29 PM
49
Les Iterables
Iterable: An object(container)
capable of returning its
members one at a time.
11/8/2014 10:37:29 PM
50
Who is iterable?
all sequence types (like list, str, tuple, range)
some non-sequence types like set,
frozenset, dict, file objects,
Can be used in a for loop and in other places
where sequences are employed
11/8/2014 10:37:29 PM
51
Iterators
An iterator represents a stream of data
the built-in function iter(),
takes an iterable object as argument
returns an iterator for the object. (')'
to get successive items in the stream.
use the built-in function next()
- is good for one pass over the set of values.
11/8/2014 10:37:29 PM
52
Iterator examples
>>>
>>>
>>>
'a'
>>>
'b'
>>>
'c
s='abc'
# s is iterable
its=iter(s) # iter(s) creates an iterator to s
its.next()
# next(its) returns the next item in s
its.next()
its.next()
>>> its.next() # iterator is exausted - no more elements
ErrorStopIteration
To do it again repeat(refill) its=iter()
11/8/2014 10:37:29 PM
53
xrange show
>>> xrange(1,8,3)
xrange(1, 8, 3)
>>> list(xrange(1,8,3))
[1, 4, 7]
>>> k=iter(xrange(1,8,3))
>>> k.next()
1
>>> k.next()
4
>>> k.next()
7
>>> k.next()
StopIteration
11/8/2014 10:37:29 PM
54
References and Copies
About assignments
Magic integers )) : -5256 (..singletons)
>>> x=256
>>> y=256
>>> print id(x),id(y)
28190492
28190492
No for floats
>>> x=256.0
>>> y=256.0
>>> print id(x),id(y)
36792004 36791924
nor for ints out of
[-5256]
>>> x=257
>>> y=257
>>> print id(x),id(y)
11733080 28387720
Reference, alias
When a program makes an assignment such
as a = b, a new reference to b is created.
>>> b = 257
>>> a = b
>>> print id(a), id(b)
28387672 28387672
>>> a is b # are the ids equal ?
True
>>> a==b # are the values equal ?
True
alias
a is just an alias for b,
changing a will not change b
>>> b = 257
>>> a = b
>>> a = 258
>>> a is b
False
>>> a==b
False
>>> print a, b
258 257
What about for strings?
>>> x='a'
>>> y='a'
>>> print id(x),id(y)
20008472 20008472
>>> x='ojuwriuwrvpiurvpibpihv'
>>> y='ojuwriuwrvpiurvpibpihv'
>>> print id(x),id(y)
32475184 32475184
And what about lists, or tuples
>>> x=[1,2,3]
>>> y=[1,2,3]
>>> print id(x),id(y)
32502248 32489384
>>> x=(1,2,3)
>>> y=(1,2,3)
>>> print id(x),id(y)
32503248 32502368
Mutable objects behaviour
The behavior is different for mutable objects such as lists and
dictionaries. Example:
>>> a = [1,2,3,4]
>>> b = a
>>> b is a
True
>>> a == b
True
# b is a reference to a
Changes in an alias copy
>>> b[2] = -100 # Change an element in b
>>> a
# Notice how a also changed
[1, 2, -100, 4]
>>> b
[1, 2, -100, 4]
>>> a is b
True
>>> a==b
True
What about real copies
Here a and b refer to the same object, so a change
made to the obj thru one of the vars is seen thru the
other.
We need copies that can be changed without changing
the original: not a new reference
shallow , deep copies
There are 2 diff types of copy operations for container
objects, such as lists and dictionaries: shallow copy,
deep copy.
A shallow copy:
- creates a new object
- fills it with references to the items contained in the original
object. Example:
>>> a = [ 1, 2, [3,4] ]
>>> b = list(a) # Create a shallow copy of a.
>>> b is a
False
Shallow copies merits
>>> b.append(100)
>>> b
[1, 2, [3, 4], 100]
# Append element to b.
>>> a
# Notice that a is unchanged
[1, 2, [3, 4]]
>>> b[2][0] = -100 # Modify an element inside b
>>> b
[1, 2, [-100, 4], 100]
>>> a # Notice the change inside a
[1, 2, [-100, 4]]
How it works
In this case, a and b are separate list objects, but
the elements they contain are shared.
Therefore, a modification to one of the elements
of a also modifies an element of b, as shown.
A deep copy creates a new object and recursively
copies all the objects it contains.
There is no built-in operation to create deep
copies of objects.
copy.deepcopy()
The copy.deepcopy() function in copy module does
it, example:
>>>
>>>
>>>
>>>
>>>
import copy
a = [1, 2, [3, 4]]
b = copy.deepcopy(a)
print a is b, a==b # False, True
b[2][0] = -100
>>> b
[1, 2, [-100, 4]]
>>> a
[1, 2, [3, 4]]
# a is not changed
(problems: when some element recursively points to itself)
Three ways to shallow
Each of the follows produces a shallow copy of
iterable x:
y=list(x)
y=x[:]
y=copy.copy(x)
First class objects
First-Class Objects
All objects in Python are first class,
meaning that:
- all objects that can be named by an identifier,
have equal status.
- all objects that can be named, can be treated
as data.
First class Example
A simple dictionary with two values:
items = { 'number' : 42
'text' : "Hello World"
}
Lets add some special items to this dictionary.
items["func"] = abs # Add the abs() function
import math
items["mod"] = math # Add a module
items["error"] = ValueError # Add an exception type
nums = [1,2,3,4]
items["append"] = nums.append # Add a meth of another object
First class example
The items dictionary contains: a function, a module, an
exception, and a method of another object.
Use the keys as the prev items, Example:
>>> items["func"](-5) # Executes abs(-5)
5
>>> items["mod"].sqrt(9) # Executes math.sqrt(9)
3.0
>>>try:
x = int("Iosi")
except items["error"] as e: # Same as except ValueError as e
print "Couldn't convert"
Couldn't convert
First class Example cont.
>>>
items["append"](Ety)
>>> nums
[1, 2, 3, 4, Ety]
Writing very compact code is possible because
everything in Python is first-class.
Another First class example
Given a line of text such as:
"Iosi, 1, 3.14, Malka"
lets convert it into a list of elements with the right
type-conversion.
- create a list of types (which are first-class objects)
- execute a few simple list processing operations:
Cont.
>>> line = "Iosi, 1, 3.14, Malka"
>>> field_types = [str, int, float, str]
>>> raw_fields = line.split(',')
>>> fields = [ty(val) for ty,val in
zip(field_types,raw_fields)]
>>> fields
['Iosi', 1, 3.14, 'Malka']
Aliasing function names
Did you know ?
You can bind a name to a known respectable
function, and use it instead :
>>> Iosi=len
>>> Iosi('abc')
3
>>> Ety = type
>>> Ety(2)
<type 'int'>
(Just dont forget the new names)
11/8/2014 10:37:29 PM
79
Write your functions
>>> def mySquare(x) :
return x*x
# function declaration
>>> mySquare(7)
49
# function call
>>> def mySquarePlusAnything(x,anything):
return x*x+mySquare(anything)
>>> mySquarePlusAnything(6,4)
50
11/8/2014 10:37:29 PM
# function call
80
elseing with the loops
In python
Loops (for,while)may have
an else part
Else and the loops
The else clause of a loop is executed only if :
- the loop ends naturally, or if
- the loop did not start/execute at all.
If the loop is un-naturally terminated by a
break statement (or by some exception),
- the else clause is skipped.
Why: As a simple signal of what happened in the
loop.
11/8/2014 10:37:29 PM
82
else example
while value < limit:
if value == x:
print "Found it!"
break
value+=y
else: # see the else indentation
print x its not there ! "
11/8/2014 10:37:29 PM
83