Download 1, 2, 3 - HUJI moodle

Document related concepts
no text concepts found
Transcript
1
INTRO2CS
Tirgul 4
What we will cover today?
2






Sequences - reminder
Tuples
Mutable and Immutable
Aliasing
Shallow and Deepcopy
Function Variables
README(1)
3




README(s) are simple
They are used everywhere (academy and the
market)
They are there for the future readers of the code
In intro we ask you for quite a simple README
README(2)
4
cs username
ID
real name
Those are my friends that I
consulted with regarding the ex
Edit the name of the ex and its number
This is how to run my program from a terminal
Fill here a general description of your program
- This program computes the expected time of end of the world
- It does it based on the Algorithm developed by the Nostradamus
- I preferred this implementation, since the Hollywood algorithm is
boring and too long
List of submitted files
If needed so (not obligatory)
Reminder - Sequences (1)
5



The most basic data structure in Python is
the sequence.
Each element of a sequence is assigned a number its position or index.
The first index is zero, the second index is one, and
so on.
Sequences (2)
6


Python has several types of sequences, for
example: list, tuple, str, range.
All share the following features:
• Each sequence contains a finite number of elements.
• The elements are arranged in some order in the sequence.
• It is possible to iterate over the elements in the sequence,
according to their order.
• It is also possible to check if an element is in a sequence.
Sequences (3)
7



There are certain things you can do with all
sequence types.
These operations include indexing, slicing, adding,
multiplying, and checking for membership.
In addition, Python has built-in functions for finding
the length of a sequence and for finding its largest
and smallest elements, as we will see later.
Casting empty sequences is always
false
8




bool (0) == False
bool (0.0) == False
bool ("") == False
bool ([]) == False
enumerate
9


Enumerate returns a couple containing a count (from
start which defaults to 0) and the values obtained
from iterating over sequence.
Share the advantages of both:
 for
i in range(len(lst)):
 for item in lst:
Enumerate(2)
10

Enumerate returns a couple containing a count (from
start which defaults to 0) and the values obtained
from iterating over sequence.
>>> seasons = ['Spring', 'Summer ', 'Fall', 'Winter']
>>> for (i, season) in enumerate(seasons):
... print ("index: ", i, ", value: ", season)
index:
index:
index:
index:
0, value:
1, value:
2, value:
3, value:
Spring
Summer
Fall
Winter
Mutable and Immutable
11




The value of some objects can be changed.
Objects whose value can be changed are said to
be mutable;
objects whose value is unchangeable once they are
created are called immutable.
An object’s mutability is determined by its type; for
instance, numbers, strings, ranges and tuples are
immutable, while lists are mutable.
Python Tuples
12


A tuple is a sequence of immutable Python objects.
Tuples are sequences, just like lists.
The only differences are that tuples can't be
changed i.e., tuples are immutable, and tuples use
parentheses instead of square brackets in lists.
Creating a tuple (1)
13


Creating a tuple is as simple as putting different commaseparated values and optionally you can put these commaseparated values between parentheses also.
For example:
>>> tup1 = ('physics', 'chemistry', 1997, 2000)
>>> tup2 = (1,2,3,4,5)
>>> tup3 = "a", "b", "c", "d", "e"
>>> print(tup1)
('physics', 'chemistry', 1997, 2000)
>>> print(tup2)
(1, 2, 3, 4, 5)
>>> print(tup3)
('a', 'b', 'c', 'd', 'e')
Creating a tuple (2)
14

The empty tuple is written as two parentheses containing
nothing:
>>> tup1 = ()
>>> print(tup1)
()

To write a tuple containing a single value you have to include a
comma, even though there is only one value:
>>> tup1 = (50,)
>>> tup1
(50,)
Accessing Values in Tuples
15


Like string indices, tuple indices start at 0, and tuples can be
sliced, concatenated and so on.
To access values in tuple, use the square brackets for slicing
along with the index or indices to obtain value available at
that index.
>>> tup1 = ('physics', 'chemistry', 1997, 2000)
>>> tup2 = (1, 2, 3, 4, 5, 6, 7)
>>> print ("tup1[0]: ",tup1[0])
tup1[0]: physics
>>> print ("tup2[1:5]: ",tup2[1:5])
tup2[1:5]: (2, 3, 4, 5)
Updating Tuples – impossible
16

Tuples are immutable which means you cannot update or
change the values of tuple elements.
>>>tup1 = (12, 34.56)
>>>tup2 = ('abc', 'xyz' )
>>>tup1[0] = 100
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
However,
new assignments are always legal!
17

Creating a new tuple (or any new mutable item) is
always legal:
>>>tup1 = (12, 34.56)
>>>tup2 = ('abc', 'xyz')
>>>tup3 = tup1 + tup2
>>>tup3
(12, 34.56, 'abc', 'xyz')
Delete Tuple Elements (1)
18
Removing individual tuple elements is not possible. There is,
of course, nothing wrong with putting together another
tuple with the undesired elements discarded.
 To explicitly remove an entire tuple, just use
the del statement.

>>>tup1 = (12, 34.56, 'abc', 'xyz')
>>> del tup1[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object doesn't support item deletion
>>> del tup1
>>>tup1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'tup1' is not defined
Basic Tuples Operations
19
Tuples respond to the + and * operators much like strings; they
mean concatenation and repetition here too.
 In fact, tuples respond to all of the general sequence
operations we used on strings.

Python Expression
Results
len((1, 2, 3))
3
(1, 2, 3) + (4, 5, 6)
(1, 2, 3, 4, 5, 6)
Description
Length
Concatenation
('Hi!',) * 4
('Hi!', 'Hi!', 'Hi!', 'Hi!')
Repetition
3 in (1, 2, 3)
True
Membership
for x in (1, 2, 3):
print x,
123
Iteration
Indexing and Slicing
20
Because tuples are sequences, indexing and slicing work
the same way for tuples as they do for strings.
 Assuming following input:

Python Expression
Results
Explanation
L[2]
'SPAM!'
Offsets start at zero
L[-2]
'Spam'
Negative: count from
the right
L[1:]
['Spam', 'SPAM!']
Slicing fetches sections
Built-in Tuple Functions
21




len(tuple)
Gives the total length of the tuple.
max(tuple)
Returns item from the tuple with max value.
min(tuple)
Returns item from the tuple with min value.
tuple(seq)
Converts a list into tuple.
No Enclosing Delimiters (1)
22


Any set of multiple objects, comma-separated,
written without identifying symbols (i.e., brackets for
lists, parentheses for tuples, etc.), default to tuples.
x, y == 1, 2 is exactly the same as x, y = (1, 2)
>>> a = 'abc', -4.2322e37, 18+6.6j, 'xyz'
>>> print(a)
('abc', -4.2322e+37, (18+6.6j), 'xyz')
>>> type(a)
<class 'tuple'>
No Enclosing Delimiters (2)
23

An example in python shell:
>>> x, y = 1, 2
>>> x, y
(1, 2)
>>> type(_)
<class 'tuple'>
Underscore (‘_’) gets the last
answer in the python shell
Function returns multiple variables?
Also a tuple
24


We saw previously that we may return few variables from a
functions
Actually python returns only one variable - A tuple!
>>> def foo():
... return 3, 4
>>> type(foo)
<class ‘function'>
>>> type(foo())
<class 'tuple'>
>>> type(foo()[0])
<class 'int'>
Mutable and Immutable types
25
object
Mutable or Immutable?
numbers
Immutable
string
Immutable
range
Immutable
tuple
Immutable
lists
mutable
Immutable/Mutable containers –
a comment
26


Objects within an immutable object can be mutable
And vice versa!
>>> tup1 = (1, 2, [3, 4, 5])
>>> tup1[0] = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> tup1[2][0] = 6
>>> tup1
(1, 2, [6, 4, 5])
Immutable/Mutable containers – a
comment
27

Are those legal in python?
>>> tup1 = (1, 2, [3, 4, 5])
>>> L1 = ['a', 'b', ('c', 'd', 'e')]
>>> tup1[0] = 3
>>> tup1[2][0] = 6
>>> tup1[2] = 3
>>> L1[0] = 'g'
>>> L1[2][0] = ‘g'
>>> L1[2] = 'g'
Immutable/Mutable containers – a
comment
28

Are those legal in python?
>>> tup1 = (1, 2, [3, 4, 5])
>>> L1 = ['a', 'b', ('c', 'd', 'e')]
>>> tup1[0] = 3
>>> tup1[2][0] = 6
>>> tup1[2] = 3
>>> L1[0] = 'g'
>>> L1[2][0] = 'g'
>>> L1[2] = 'g'
Aliases
29



An alias is a second name for a piece of data.
Often easier (and more useful) than making a
second copy
If the data is immutable, aliases don't matter
because the data can't change
But if data can change, aliases can result in a lot
of hard-to-find bugs
Aliases
30

Aliasing happens whenever one variable's value is
assigned to another variable
>>> first = 'isaac'
>>> second = first
variable
value
first
'isaac'
second
id function
31



Id(object)
Return the “identity” of an object. This is an integer
which is guaranteed to be unique and constant for
this object during its lifetime.
In most of the computers id function return the
address of the object in memory.
Aliasing immutable items – same identity
32

When we copy immutable items, the two items have the
same id:
>>> first = 'isaac'
>>> second = first
>>> id(first)
4314103120
>>> id(second)
4314103120
variable
first
second
value
'isaac'
Any new assignment will result in a different
identity
33

But new assignment will always result in a new identity
>>> first = 'isaac'
>>> second = first
>>> id(first)
4314103120
>>> id(second)
4314103120
>>> first = first + ' newton'
>>> id(first)
4314315376
>>> id(second)
4314103120
variable
value
first
'isaac'
second
'isaac newton'
Aliasing mutable items is a completely
different story!
34


As mutable items are allowed to change, they
behave very differently in aliasing
For example:
>>> L1 = [1, 2, 3]
>>> L2 = L1
>>> print(L2)
[1, 2, 3]
>>> id(L1)
4314314696
>>> id(L2)
4314314696
>>> L3 = L1[:]
>>> print(L3)
[1, 2, 3]
>>> id(L3)
4314313992 # != id (L1)
Huh?!
Copying with the equal sign
copying a reference
35

Assign a list to another - Both point to the same
place in memory!
>>> colours1 = ["red", "green"]
>>> colours2 = colours1
variable
value
colours1
colours2
'red'
'green'
Copying with the equal sign
copying a reference
36

Assign a list to another - Both point to the same
place in memory!
>>> colours1 = ["red", "green"]
>>> colours2 = colours1
>>> colours2[1] = "blue"
>>> print(colours2)
['red', 'blue']
>>> print(colours1)
['red', ‘blue']
variable
value
colours1
colours2
'red'
'blue'
New assignments are new references
37

On the other hand – any new assignment will
always lead to a new identity
variable
>>> colours1 = ["red", "green"]
>>> colours2 = colours1
colours1
colours2
>>> colours2 = ["pink", "yellow"]
>>> colours1
["red", "green"]
value
variable
'red'
'green'
value
colours1
colours2
'red'
'pink'
'green'
'yellow'
Copy with the equal operator
Same identity!
38
>>> nums1 = [1, 2]
>>> nums2 = nums1
>>> id(nums1) == id(nums2)
True
>>> nums2.append(3)
>>> print(nums2)
[1, 2, 3]
>>> print(nums1)
[1, 2, 3]
>>> id(nums1) == id(nums2)
True
variable
value
nums1
nums2
1 2
3
Shallow and Deep Copy
39
Shallow copy
 In the process of shallow copying A, B will copy all of A's field
values. If the field value is a memory address it copies the
memory address, and if the field value is a object that is not
containers: int, float, bool (primitive type) - it copies the value of
it.
Deep copy
 In deep copy the data is actually copied over. The result is
different from the result a shallow copy gives. The advantage is
that A and B do not depend on each other, but at the cost of
a slower and more expensive copy.
Copy with the slice operator
40

Simple data types
>>> list1 = ['a', 'b', 'c', 'd']
>>> list3 = list1[:]
>>> id(list1) == id(list3)
False
>>> list3[1] = 'x'
>>> print(list3)
['a', 'x', 'c', 'd']
>>> print(list1)
['a', 'b', 'c', 'd']
Copy with the slice operator –
shallow copy
41

Compound data types - copy the reference!
>>> lst1 = ['a', 'b', ['ab', 'ba']]
>>> lst2 = lst1[:]
>>> lst2[0] = 'c'
>>> lst2[2][1] = ‘d’
>>> print(lst1)
['a', 'b', ['ab', 'd']]
>>> id(lst1)==id(lst2)
False
>>> id(lst1[0])==id(lst2[0])
False
>>> id(lst1[2])==id(lst2[2])
True
deepcopy from the Module copy
42

Create a new version of the same values but
with new references!
>>> from copy import deepcopy
>>> lst1 = ['a', 'b', ['ab', 'ba']]
>>> lst2 = deepcopy(lst1)
>>> lst2[2][1] = 'd'
>>> lst1[0] = "c"
>>> print(lst1)
['c', 'b', ['ab', 'ba']]
>>> print(lst2)
['a', 'b', ['ab', 'd']]
>>> id(lst1) == id(lst2)
False
>>> id(lst1[2]) == id(lst2[2])
False
Quick Summary - immutable items
43
An alias is a second name for the same piece of data
In immutable items every copy is an alias
>>> a = (1,2,[3,4])
>>> b = a
>>> id(a) == id(b)
True
>>> c = a[:]
>>> id(a) == id(c)
True
Quick Summary - Mutable items
44
In mutable items we distinguish between three
cases:
 Assignment (=):

 Assign

a second name to the same identity
Shallow copy ([:]):
 Copy
all the fields (values for simple types and
references for memory addresses )

Deepcopy (copy.deepcopy)
 Copy
(recursively) all the values in one list to another
is Vs. ==
45




In python we have two functions to compare objects:
is and the equal operator
is test for identity and is similar for all types
Equal is a function that may be implemented
differently (wait for the cool stuff in OOP)
In Lists == works similar to deepcopy and compare
the values of two lists
is Vs. == example(1)
46
>>> L1 = [1, 2, 3]
>>> L2 = [1, 2, 3]
>>> L1 == L2
True
>>> L1 is L2 # similar to id(L1) == id(L2)
False
is Vs. == example(2)
47
>>> tup1 = (3, 4)
>>> tup2 = (3, 4)
>>> tup1 is tup2
False
>>> tup1 == tup2
True
>>> L1 = [1, 2, tup1]
>>> L1 = [1, 2, tup1]
>>> L2 = [1, 2, tup2]
>>> L2
[1, 2, (3, 4)]
>>> L1
[1, 2, (3, 4)]
>>> L1 == L2
True
>>> L1 is L2
False
Function scopes
48




How can we determine what belongs to a function and
what to the module? Scopes
Function Scope – Everything between the function
definition and the end of the function.
Python functions have no explicit begin or end, and no
curly braces to mark where the function code starts and
stops. The only delimiter is a colon (:) and the
indentation of the code itself.
Everything inside the scope of a function “belongs”
to it – local variables, local functions and more
Functions have their own variables
49

Reminder:
>>> a = 3
>>> def print_func():
... a = 12
... print('inside the func: a = ', a)
...
>>> print_func()
inside the func: a = 12
>>> print('outside the func: a = ', a)
outside the func: a = 3
Local variables
50




Functions have a special type of variable called
local variables
These variables only exist while the function is
running.
Local variables are not accessible from outside the
function
When a local variable has the same name as
another variable (such as a global variable), the
local variable hides the other.
Local variables - example(1)
51
>>> def func_a():
... a = 3
>>> def func_b():
... b = a -2
>>> func_b()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in func_b
NameError: name 'a' is not defined
Local variables – example(2)
52
a =
b =
e =
def
5
3
4
print_func():
a = 3
print('in the
b = a + 100
print('in the
d = 2 * a
print('in the
print('in the
return b + 10
c = print_func()
func a =', a)
func b =', b)
func d =', d)
func e =', e)
Local variables – example(2)
53
a =
b =
e =
def
5
3
4
print_func():
a = 3
print('in the
b = a + 100
print('in the
d = 2 * a
print('in the
print('in the
return b + 10
# output:
in the func a = 3
in the func b = 103
in the func d = 6
in the func e = 4
func a =', a)
func b =', b)
func d =', d)
func e =', e)
print('a =',a)
a = 5
print('b =',b)
b = 3
print('c =',c)
c = 113
print('d =',d)
c = print_func()
NameError: name 'd' is not
defined
The global variable
54
a = 3
def print_func():
global a
a = 12
print('inside the func: a = ', a)
print_func()
print('outside the func: a = ', a)
inside the func: a = 12
outside the func: a = 12

When possible, avoid the use of global variables – global
variable can potentially be modified from anywhere, and any
part of the program may depend on it.
Mutable items as variables
55
>>> def func_a(L):
... L[1] = 2
>>> L1 = [4,5,6]
>>> func_a(L1)
>>> L1
[4, 2, 6]
Huh?!?!
What happened to local variables?
Mutable items are passed as
references!
56
>>> def func_a(L):
... L[1] = 2
>>> L1 = [4,5,6]
>>> func_a(L1)
>>> L1
[4, 2, 6]
Let’s test you (1)
57
L = (1,2,3)
def foo(L):
L[2] = 4
>>>L
What will happen?
Let’s test you (1)
58
L = (1, 2, 3)
def foo(L):
L[2] = 4
What will happen?
>>>foo(L)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
TypeError: 'tuple' object does not support item assignment
Let’s test you (2)
59
L = [1, 2, 3]
def foo(L):
L[2] = 4
>>>foo(L)
>>>L
What will happen?
Let’s test you (2)
60
L = [1, 2, 3]
def foo(L):
L[2] = 4
>>>foo(L)
>>>L
[1, 2, 4]
What will happen?
Let’s test you (3)
61
L = [1, 2, 3]
def foo(L):
L = [1, 2, 4]
>>>foo(L)
>>>L
What will happen?
Let’s test you (3)
62
L = [1, 2, 3]
def foo(L):
L = [1, 2, 4]
>>>foo(L)
>>>L
L = [1, 2, 3]
What will happen?
Let’s test you (4)
63
def foo(L):
L2 = [1, 2]
L[2] = L2
L = [1, 2, 3]
>>>foo(L)
>>>L
What will happen?
Let’s test you (4)
64
def foo(L):
L2 = [1, 2]
L[2] = L2
L = [1, 2, 3]
>>>foo(L)
>>>L
L = [1, 2, [1, 2]]
What will happen?