PIC 16, Fall 2018 Variables, Dynamically-typed, Mutable, Immutable, Functions Michael Andrews Department of Mathematics UCLA October 1, 2018
Office hours reminder M 1:30-2:45pm (Michael) T 1-2pm (Sam), T 3-5pm (Michael) W 11am-12pm (Sam) R 1-2pm (Sam) F 1:30-2:45pm (Michael)
Syntactic Differences: C++ and Python C++ Python ; end line (most frequently) {} indentation for(i=0; i<10; i++) for i in range(10): if/while(x) if/while x: int fun() def fun(): #include import true/false True/False // # &&,,! and, or, not() i++ i=i+1 cout, cin print, input/raw_input const (no equivalent)
Further differences A variable in Python is a pointer to an object. Python is dynamically typed (as opposed to statically typed). Every type in C++ is mutable unless it s const. In Python, some types are immutable. We ll speak about each of these in turn.
Variables in Python are pointers: example x = [] y = x print y x.append(0) print y
Variables in Python are pointers: example annotated x = [] y = x print y # the empty list is created and stored in memory # = "binds" the pointer x to this place in memory # y is a pointer to the same place in memory # prints the list to which x points # prints the list to which y points x.append(0) print y # 0 is appended to the list to which x points # prints the list to which x points # prints the list to which y points
Python is dynamically typed Python variables point to various objects. There is no need to declare a variable or require it to always point to the same type of object. This is the sense in which people say Python is dynamically typed. x = 1 print type(x) x = 'hello' print type(x) x = [1, 2, 3] print type(x) # x points to an int # see! # now x points to a string # see! # now x points to a list # see!
Variant of previous example: more about assignment x = [] y = x print y x = [1] print y
Variant of previous example annotated x = [] y = x print y x = [1] print y # the empty list is created and stored in memory # = binds the pointer x to this place in memory # y is a pointer to the same place in memory # prints the list to which x points # prints the list to which y points # the list [1] is created and stored in memory # = binds the pointer x to this place in memory # prints the list to which x points # prints the list to which y points
Related example about assignment y = [] z = [1] x = y y = z, y, z
Related example annotated y = [] z = [1] x = y y = z # the empty list is created and stored in memory # = binds the pointer y to this place in memory # the list [1] is created and stored in memory # = binds the pointer z to this place in memory # x is binded to where y currently points # y is binded to where z currently points, y, z
Variant of the example before last: lists ints x = 0 y = x print y x = 1 print y # the int 0 is "created" and stored in memory # = binds the pointer x to this place in memory # y is a pointer to the same place in memory # prints the int to which x points # prints the int to which y points # the int 1 is "created" and stored in memory # = binds the pointer x to this place in memory # prints the list which x points to # prints the list which y points to
Mutability The first example on page 6 illustrates a subtlety concerning python variables arising from the fact they are pointers. The variation on page 9 emphasizes thinking about assignment as binding : x = [1] does not change the content of the object to which x points originally; it creates a new object and changes where x points. The variation on page 12 is a simple tweak from lists to ints. We cannot create an example like the first one using ints. While x = 1 means x points to the int 1, there is no way of changing the object 1. The only way to make x point to a different integer is to create a new integer and have x point somewhere else. ints are immutable, whereas lists are mutable. strings are also immutable.
Passing variables to functions Passing a variable to a function is like passing a pointer by value in C++. We create a copy of the pointer insider the function. We do not create a copy of the object being pointed to.
Passing variables to functions: Example 1 def f(l): L = L + [0] x = [] f(x)
Passing variables to functions: Example 1 annotated def f(l): L = L + [0] # a NEW list is stored in memory: # the result of COPYING the list that L points to, # and then APPENDING 0. # = binds L to this new list. # L is disgarded. x = [] f(x) # x points to the empty list. # a new pointer called L is created. # L points to where x points. # the above 4 comments apply. # none of these edit the list to which x points.
Passing variables to functions: Example 2 def g(l): L.append(0) # 0 is appended to the list to which L points. # L is disgarded. x = [] f(x) # x points to the empty list. # a new pointer called L is created. # L points to where x points. # the above 2 comments apply.
Mutable default parameters def f(x, L=[]): L.append(x) return L print f(1) print f(2) print f(3) print f(88,[8,18]) print f(4)
Mutable default parameters annotated def f(x, L=[]): L.append(x) return L # when you define f, # f is added to the global scope, # and L is added to the local scope of f, # L points to memory storing []. # this only happens once. print f(1) # hopefully this makes print f(2) # sense of the first 3 lines. print f(3) print f(88,[8,18]) # this probably feels correct too. print f(4) # this line might still be confusing; # it'll make more sense once # we look at class variables.
Another weird thing: not lectured def create_multipliers(): m = [] for i in range(5): def multiplier_i(x): return i * x m.append(multiplier_i) return m multipliers = create_multipliers() print multipliers[1](11)
Another weird thing: not lectured def create_multipliers(): m = [] for i in range(5): def multiplier_i(x, i=i): # used default parameter return i * x m.append(multiplier_i) return m multipliers = create_multipliers() print multipliers[1](11)