4. Strong and Dynamic Typing
●
●
●
●
●
Python is both strongly and dynamically typed
Strong typing means that every object has a specific
type
Variables contain references to objects
Dynamic typing means that types of objects pointed to
by variables are inferred at run time
There is no contradiction b/w strong and dynamic typing:
they describe two different features of programming languages
5. Strong and Dynamic Typing
var = 10
var = 'hello'
●
So hasn't var just changed type ?
●
The answer is NO. var isn't an object at all - it's a name.
6. Duck Typing
●
●
●
●
Sometimes Python is called a duck typing language
The gist of duck typing: real types of objects do not
matter so long as specific operations can be performed on them
Objects themselves “know” whether they can be added,
multiplied, concatenated, etc
If and when objects cannot perform a requested operation,
a run-time error occurs
7. Checking Object Types
●
There are two methods in Python for checking object types:
type(<object>) and isinstance(<object>, <type>)
>>> type([1, 2])
<type 'list'>
>>> isinstance([1, 2], list)
True
>>> type((1, 2))
<type 'tuple'>
>>> isinstance((1, 2), tuple)
True
>>> isinstance((1, 2), type((1, 2)))
True
11. General Facts
●
Lists are mutable type sequences
●
Lists contain 0 or more references to objects
●
Lists can contain references to different types of objects
12. Construction
# lst1 is an empty list
>>> lst1 = []
>>> lst1
[]
# lst2 is a list of integers.
>>> lst2 = [1, 2, 3, -4, 0, -5, 7]
>>> lst2
[1, 2, 3, -4, 0, -5, 7]
13. Construction
# lst3 is a mixed list.
>>> lst3 = [1, 'a', 'rock violin', 3.14, "math"]
>>> lst3
[1, 'a', 'rock violin', 3.14, 'math']
# lst4 is a nested list.
>>> lst4 = [1, [2, 3], 4, 5]
# lst5 is another nested list.
>>> lst5 = [1, lst3]
>>> lst5
[1, [1, 'a', 'rock violin', 3.14, 'math']]
14. Construction
●
list() function can be used as a constructor to
make empty lists or convert other sequences to lists
>>> x = list()
>>> x
[ ]
>>> y = list(“abc”)
>>> y
['a', 'b', 'c']
15. Sequence Operations
●
All sequences support the following operations:
Indexing
Membership
Concatenation
Multiplication
Slicing
Length
Minimum/Maximum element
16. Indexing
●
●
Use the square brackets [ and ] to index into lists
Since lists are sequences, left-to-right indexing starts
at 0
>>> lst = [1, 2, 3]
>>> lst[0]
1
>>> lst[1]
2
>>> lst[2]
3
17. Side Note on Sequence Indexing
●
●
●
In Python sequences, elements can be indexed left to
right and right to left
If s is a sequence, then the leftmost element is s[0] while
the rightmost element is s[-1]
In general, if s is a sequence of n elements, then
s[0] == s[-n], s[1] == s[-n+1], …, s[n-1] == s[-1]
19. Indexing
●
Right-to-left indexing starts with -1 and ends with -n,
where n is the number of elements in the list
>>> lst = [1, 2, 3]
>>> lst[-1] # 1st element from right
3
>>> lst[-2] # 2nd element from right
2
>>> lst[-3] # 3rd element from right
1
20. Out of Range Indexing
●
Both positive and negative indices result in errors if they go off on either side of the list
>>> lst = [1, 2, 3]
>>> lst[3]
out of range error
>>> lst[-4]
out of range error
21. Membership
●
If x is an object and lst is a list, then x in lst returns
True if x is an element of lst, else False is returned
>>> lst = [10, 'eggs', 3]
>>> 10 in lst
True
>>> 'eggs' in lst
True
>>> 'buzz' in lst
False
22. Membership
●
If x is an object and lst is a list, then x not in lst
returns True if x is not an element of lst, else False
>>> lst = [10, 'eggs', 3]
>>> 11 not in lst
True
>>> 'eggs' not in lst
False
>>> 'buzz' not in lst
True
23. Membership
●
Membership can be tested on nested lists
>>> lst = [['one', 1], ['two', 2], ['three', 3]]
>>> ['one', 1] in lst
True
>>> ['two', 2] in lst
True
>>> ['three', 3] in lst
True
24. Side Note On NOT
●
If you want to test if the negation of a boolean expression is true or false, you can use not in front that
expression
>>> not 1 == 2
True
>>> not 1 == 1
False
>>> lst=[1,2,3]
>>> 4 not in lst
True
>>> 1 != 2 ## this works as well
25. Concatenation
●
If x and y are lists, then x + y is their concatenation,
i.e. the list that consists of x's elements followed by
y's elements
>>> x = [10, 'eggs', 3]
>>> y = [12, 'buzz', 5]
>>> z = x + y
>>> z
[10, 'eggs', 3, 12, 'buzz', 5]
26. Multiplication
●
If x is a list and n is an integer, then x * n or n * x
is the list that consists of n copies (copies of references
to x) of x
>>> x = [1, 2]
>>> y = ['a', 'b']
>>> z = [x, y]
>>> z
[[1, 2], ['a', 'b']]
>>> z2 = z * 2
>>> z2
[[1, 2], ['a', 'b'], [1, 2], ['a', 'b']]
27. Slicing
●
●
●
●
Slicing is an operation that accesses a range of elements in a sequence
When the length of the range is 1, slicing is equivalent to indexing
A Slice is defined by two indexes: the start index is
the index of the first element; the end index is the index of the first element that immediately follows the
last element of the slice
The start index is inclusive and the end index is exclusive
29. ●
Omission of both indexes slices the entire list
Slicing
>>> lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> lst[:] ## same as lst[0:7]
['a', 'b', 'c', 'd', 'e', 'f', 'g']
●
Omitted start index defaults to 0
>>> lst[:3] ## same as lst[0:3]
['a', 'b', 'c']
●
Omitted end index defaults to the one right after the
last index in the sequence
>>> lst[3:] ## same as lst[3:7]
['d', 'e', 'f', 'g']
30. Length, Minimum, Maximum
●
These are self explanatory
>>>
>>>
3
>>>
'a'
>>>
'c'
lst = ['a', 'b', 'c']
len(lst)
min(lst)
max(lst)
31. Multi-Dimensional Lists
●
It is possible to construct multi-dimensional lists
●
Here is an example of a 2D list (aka matrix)
>>> matrix = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
>>> matrix[0]
[0, 1, 2]
>>> matrix[1]
[3, 4, 5]
>>> matrix[0][0]
0
>>> matrix[0][2]
2
32. Deleting Elements
●
Delete individual element
>>> lst = [1, 2, 3, 4, 5]
>>> del lst[1] ## deleting 2
>>> lst
[1, 3, 4, 5]
●
Delete a slice
>>> del lst[1:3]
>>> lst
[1, 5]
●
Assign an empty list to a slice to delete it
>>> lst[0:2] = []
33. List Manipulation with Built-In Methods
append(), extend(), reverse(), remove(),
index(), count(), sort()
34. list.append()
●
The method append() adds an object at the end of
the list
>>> lst1 = [1, 2, 3]
>>> lst1.append('a')
>>> lst1
[1, 2, 3, 'a']
>>> lst1.append(['b', 'c'])
>>> lst1
[1, 2, 3, 'a', ['b', 'c']]
35. list.extend()
●
The method extend() also destructively adds to the
end of the list, but, unlike append(), does not work
with non-iterable objects
>>> lst1 = [1, 2, 3]
>>> lst1.extend(4) # error
>>> lst1.extend(“abc”)
>>> lst1
[1, 2, 3, 'a', 'b', 'c']
36. list.append() vs. list.extend()
●
Here is another difference b/w extend() and append():
>>> lst1 = [1, 2, 3]
>>> lst1.append(['a', 'b'])
>>> lst1
[1, 2, 3, ['a', 'b']] ### the last element is a list
>>> lst1 = [1, 2, 3]
>>> lst1.extend(['a', 'b'])
>>> lst1
[1, 2, 3, 'a', 'b'] ### ['a', 'b'] is added at the end of
### lst1 element by element
37. len(), list.count(), list.index()
●
Let lst be a list
●
lst.len() returns the length of lst
●
lst.count(x) returns number of i's such that
s[i] == x
●
●
lst.index(x, [i, [,j]]) returns smallest k for which
s[k] == x and i <= k < j
Python documentation note: the notation [i, [, j]] means
that parameters i and j are optional: they can both be absent,
one of them can be absent, or they can both be present
39. list.remove(), list.reverse()
●
Let lst be a list
●
lst.remove(x) is the same as
del lst[lst.index(x)]
●
lst.reverse() reverses lst in place
●
lst.reverse() does not return a value
42. Types of Parameters
●
●
●
There are two types of parameters in Python:
positional and keyword
Positional parameters are regular parameters in the
function signature: the values they receive are
determined by their position in the signature
Keyword parameters are parameters that can take on
default values and whose position can vary in the
functional signature
43. Positional Parameters: Example
def hw_avail_str(crsn, hwn, hw_loc, due_date, submit_loc):
print "%s Assignment %s is available at %s. It is due by %s in %s." %
(crsn, hwn, hw_loc, due_date, submit_loc)
>>> hw_avail_str('CS3430', '2', 'www.canvas.org', '11:59pm, Jan 25, 2014',
'your canvas')
CS3430 Assignment 2 is available at www.canvas.org. It is due 11:59pm, Jan
25, 2014 in your canvas .
●
Note: You have to remember the position of each parameter in
the signature, i.e., that crsn (course number) comes first, hwn
(homework number) comes second, hw_loc (homework web
location) comes third, etc.
44. Keyword Parameters: Example
def hw_avail_str2(crsn='CS3430', hwn='0', hw_loc='www.myblog.org',
due_date='', submit_loc='your canvas'):
print "%s Assignment %s is available at %s. It is due by %s in %s." %
(crsn, hwn, hw_loc, due_date, submit_loc)
>>> hw_avail_str2(hwn='2', due_date='11:59pm, Jan 25, 2014')
CS3430 Assignment 2 is available at www.myblog.org. It is due by 11:59pm,
Jan 25, 2014 in your canvas.
●
Note: You do not have to remember the position of each
parameter in the signature but you do have to remember the
name of each keyword parameter
45. Combining Positional & Keyword Parameters
●
Positional & keyword parameters can be combined in one
signature: positional parameters must precede keyword
parameters
def combine(x, y=10, z='buzz'):
print 'x=%d y=%d z=%s' % (x, y, z)
>>> combine(5)
x=5 y=10 z=buzz
>>> combine(5, y=50, z='foo')
x=5 y=50 z=foo
46. Positional Parameter Collection
●
●
●
●
What happens if you do not know how many parameter values
you receive on the input?
There are two choices: use a container, e.g., a list or a tuple, or
use *operator
Suppose that we want to write a function that applies three types
of operations: sum, min, and max to sequences
We can use *operator to solve this problem
50. Scope
●
●
●
Scopes (aka namespaces) are dictionaries that map
variables to their values
Builtin function vars() returns the current scope
Python documentation recommends against
modifying the returned value of vars() because the
results are undefined
51. Scope
●
def always introduces a new scope
●
Here is a quick def scoping example:
>>> x = 10
>>> def f(y):
x = y ## changes x to y only inside f
print 'x=%d'%x
>>> f(20)
>>> x ## we are outside the scope of f so x is 10
10
52. Scope
●
It is possible to change the value of a global variable
inside a function: all you have to do is to tell Python
that the variable is global
def change_x_val(z):
global x
x=z
>>> x = 1
>>> change_x_val(10)
>>> x
10
53. Scope Sensitivity of vars()
●
Calls to vars() are scope-sensitive and return the currently
active scopes
def local_vars2(x, y):
def local_vars3(n, m):
n=x+1
m=y+2
print 'vars() inside local_vars3'
print vars()
z = x + 10
w = y + 20
print 'vars() inside local_vars2'
print vars()
local_vars3(3, 4)
55. Global Scope
●
●
Builtin function globals() returns the global scope
regardless of what the current scope is
For example, the following function prints the global
scope
def global_vars(x, y):
z=x+1
w=y+2
print globals()
56. Global Scope
●
This function prints the global scope several times
despite the scope nestings
def global_vars2(x, y):
def global_vars3(n, m):
n=x+1
m=y+2
print 'globals() inside global_vars3', globals()
z = x + 10
w = y + 20
print 'globals() inside global_vars2', globals()
global_vars3(3, 4)
57. Nested Scopes
●
Nested scopes are very useful in functions that return other
functions
def func_factory(oper, lst):
def list_extender(inner_lst):
inner_lst.extend(lst)
def list_remover(inner_lst):
for i in lst: inner_lst.remove(i)
if oper == 'extend':
return list_extender
elif oper == 'remove':
return list_remover
else:
return 'ERROR: Unknown operation'
58. Nested Scopes
●
Nested scopes are very useful in functions that return other
functions
>>> fex = func_factory('extend', ['I', 'am', 'extended'])
>>> frm = func_factory('remove', ['I', 'am', 'extended'])
>>> lst = [1, 2, 3]
>>> fex(lst) ## lst is extended by ['I', 'am', 'extended']
>>> lst
[1, 2, 3, 'I', 'am', 'extended']
>>> frm(lst) ## all elements of ['I', 'am', 'extended'] are removed
from lst
>>> lst
[1, 2, 3]