Week 1
Week 1
In [ ]: l = [1, 2, 3]
l[0] = 99 # New type of assignment: not just a name on the left
print(l)
Mutable and immutable types
Some Python types, like lists, can be modified after creation. Others cannot.
In [ ]: s = "hello"
s[0] = "H" # ERROR - strings are immutable
u = (1, 2, 3) # u is a "tuple"
u[0] = 99 # ERROR - tuples are immutable
In [ ]: s = [1, 2, 3]
t = s
t[0] = 99
print(s) # ??
Names s and t point to the same structure in memory, so mutations to t are visible in
s.
What really happens in a function call
Suppose you have a function f with one formal parameter x , and that a is a variable.
When f(a) is called
In [ ]: a = [1, 2, 3]
def f(x):
x[0] = 99
f(a)
print(a) # what will it print?
Example/Recap
In [ ]: a = [1, 2, 3]
def g(x):
x = [99, 99, 99]
g(a)
print(a) # what will it print?
[1, 2]
List and string slicing
l[a : b] is the list [l[a], l[a+1], ..., l[b-1]] .
This is called a slice of l .
You can use the same syntax to slice strings, too.
In [ ]: def string_sum(s):
# return the sum of the digits in a string consisting of digits
total = 0
for digit in s:
total = total + int(digit)
return total
In [ ]: string_sum("1234")
In [ ]: def maximum_slice_sum(s, k):
# return the maximum sum of k consecutive digits in s, where k <= l
Try test cases where you know the answer, and special cases that might reveal errors.
In [ ]: maximum_slice_sum("991299993456", 3)
In [ ]: s = "583531895379853715839105738190537857438567267354974100034734936153
maximum_slice_sum(s, 10)
Classes
Classes let us create our own Python data types
Let's create a class representing a UCL student. Each instance of the UCLStudent
class will have a name and a degree subject. These are called instance variables.
In [ ]: class UCLStudent:
def __init__(self, name, subject):
self.student_name = name # create an instance variable student_
self.degree_subject = subject
Working with our class
In [ ]: class UCLStudent:
def __init__(self, name, subject):
self.student_name = name # create an instance variable student_
self.degree_subject = subject
To create a new instance of this class and access its instance variables:
In [ ]: a = UCLStudent("Zeta", "Mathematics")
In [ ]: print(a.student_name, a.degree_subject)
Class methods
We can write functions inside a class definition for working with objects of that class.
These are called class methods.
In [ ]: class UCLStudent:
...
def speak(self): # a class method
# self refers to the instance of the class on which this method
print("my name is " + self.student_name + " and I study " + sel
In [ ]: a = UCLStudent("Zeta", "Mathematics")
a.speak() # think of this as being like speak(a)
Overriding built-in operators
We can tell Python how to use + , - , * , == , > , < , str ... on our classes by
implementing special class methods.
In [ ]: a = UCLStudent("Zeta", "Mathematics")
b = UCLStudent("Zeta", "Mathematics")
a == b
In [ ]: class UCLStudent:
...
def __eq__(self, other):
# return True if self should be regarded as equal, otherwise Fa
return (self.student_name == other.student_name) and (self.degr
In [ ]: class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
In [ ]: class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
In [ ]: a = Vector(1, 1)
b = Vector(2, -1)
c = a + b
print(c.x, c.y)