Python
67557
Lecture 2
[Link]
Fall 2014 - "
Dr. Arie Schlesinger
Containers of data
Motivation: keep data and processing
tools close by,
11/8/2014 [Link] PM
Some classifications
Simple objects, :
int, float, bool (non iterable)
Containers of objects : (iterable)
str, list, tuple, range, set, frozenset, dict
11/8/2014 [Link] 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 [Link] 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 [Link] 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 [Link] PM
What about the titles of the
non containers ?
No Sequence, Immutable : int,
float, bool
(no order, no freedom to change)
11/8/2014 [Link] PM
sequences
strings, lists, tuples, range
11/8/2014 [Link] 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 [Link] 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 [Link] 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 [Link] PM
11
Sequence indexing
11/8/2014 [Link] 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
[Link] 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 [Link] PM
14
Sequence slicing
11/8/2014 [Link] 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 [Link] 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 [Link] 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 [Link] PM
18
indexing slicing doc
[Link]
sequence-types-list-tuple-range
11/8/2014 [Link] 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 [Link] 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 [Link] 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 [Link] 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 [Link] 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 [Link] PM
24
Mutability:
Tuples vs. Lists
11/8/2014 [Link] 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 [Link] 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 [Link] 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 [Link] 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 [Link] 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 [Link] PM
30
len() works with all sequences
>>> letters = ['a', 'b', 'c', 'd']
>>> len(letters)
4
11/8/2014 [Link] 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 [Link] PM
32
For your lists Only..1
>>> liz1 = [1, 1, 3, 4, 5]
>>> [Link](x) # a method of lists
>>> liz1
[1, 1, 3, 4, 5, x]
>>> [Link](2, y)
>>>liz1 [1, 1, y, 3, 4, 5, x]
11/8/2014 [Link] PM
33
The extend method vs the
operator +
+ creates a fresh list (with a new memory
reference)
extend operates on liz1 in place.
>>> [Link]([9, 8, 7])
>>> liz1
[1, 2, i, 3, 4, 5, a, 9, 8, 7]
11/8/2014 [Link] PM
34
Append
>>> x = [1, 2, 3]
>>> [Link]([4, 5])
>>> x
# appends its arg packed as it comes
[1, 2, 3, [4, 5]]
11/8/2014 [Link] PM
35
Extend
>>> x = [1, 2, 3]
>>> [Link]([4, 5])
>>> x
# extend unpacks its arg
[1, 2, 3, 4, 5]
11/8/2014 [Link] PM
36
For your lists Only ..2
>>> liz4 = [a, b, c, b]
>>> [Link](b)
1
>>> [Link](b)
2
>>> [Link](b)
>>> liz4
[a, c, b]
11/8/2014 [Link] PM
37
For your lists Only ..3
>>>
>>>
>>>
[8,
li = [5, 2, 6, 8]
[Link]() # reverse the list in place
li
6, 2, 5]
>>> [Link]() # sort the list in place
>>> li
[2, 5, 6, 8]
11/8/2014 [Link] 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 [Link] 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 [Link] 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 [Link] 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 [Link] PM
49
Les Iterables
Iterable: An object(container)
capable of returning its
members one at a time.
11/8/2014 [Link] 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 [Link] 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 [Link] PM
52
Iterator examples
>>>
>>>
>>>
'a'
>>>
'b'
>>>
'c
s='abc'
# s is iterable
its=iter(s) # iter(s) creates an iterator to s
[Link]()
# next(its) returns the next item in s
[Link]()
[Link]()
>>> [Link]() # iterator is exausted - no more elements
ErrorStopIteration
To do it again repeat(refill) its=iter()
11/8/2014 [Link] 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))
>>> [Link]()
1
>>> [Link]()
4
>>> [Link]()
7
>>> [Link]()
StopIteration
11/8/2014 [Link] 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
>>> [Link](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.
[Link]()
The [Link]() function in copy module does
it, example:
>>>
>>>
>>>
>>>
>>>
import copy
a = [1, 2, [3, 4]]
b = [Link](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=[Link](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"] = [Link] # 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 [Link](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 = [Link](',')
>>> 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 [Link] 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 [Link] 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 [Link] 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 [Link] PM
83