0% found this document useful (0 votes)
9 views602 pages

Basic Python

The document outlines the first lecture of the 6.100L course, covering course information, computation concepts, and Python basics. It emphasizes the importance of attending lectures for understanding and practicing programming concepts, as well as introduces algorithms and the role of computers in executing them. Additionally, it discusses the structure of programming languages and data types, including scalar and non-scalar objects.

Uploaded by

giakhang1704
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views602 pages

Basic Python

The document outlines the first lecture of the 6.100L course, covering course information, computation concepts, and Python basics. It emphasizes the importance of attending lectures for understanding and practicing programming concepts, as well as introduces algorithms and the role of computers in executing them. Additionally, it discusses the structure of programming languages and data types, including scalar and non-scalar objects.

Uploaded by

giakhang1704
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

WELCOME!

(download slides and .py files from


the class site to follow along)
6.100L Lecture 1
Ana Bell

1
TODAY

 Course info
 What is computation
 Python basics
 Mathematical operations
 Python variables and types
 NOTE: slides and code files up before each lecture
 Highly encourage you to download them before class
 Take notes and run code files when I do
 Do the in-class “You try it” breaks
 Class will not be recorded
 Class will be live-Zoomed for those sick/quarantine

6.100L Lecture 1
WHY COME TO CLASS?

 You get out of this course what you put into it


 Lectures
 Intuition for concept
 Teach you the concept
 Ask me questions!
 Examples of concept
 Opportunity to
practice practice practice
 Repeat

6.100L Lecture 1
OFFICE
PSETS
HOURS
OPTIONAL
PIAZZA (practice)

PROBLEM
SOLVING MANDATORY
FINGER

PRACTICE
EXERCISES

LECTURES
KNOWLEDGE PROGRAMMING
OF CONCEPTS SKILL

RECITATION
EXAMS

February 3, 2016 6.100L Lecture1 1


6.0001 LECTURE
TOPICS

 Solving problems using computation


 Python programming language
 Organizing modular programs
 Some simple but important algorithms
 Algorithmic complexity

6.100L Lecture 1
LET’S GOOOOO!

6
TYPES of KNOWLEDGE

 Declarative knowledge is statements of fact


 Imperative knowledge is a recipe or “how-to”

 Programming is about writing recipes to generate facts

6.100L Lecture 1
NUMERICAL EXAMPLE

 Square root of a number x is y such that y*y = x


 Start with a guess, g
1) If g*g is close enough to x, stop and say g is the answer
2) Otherwise make a new guess by averaging g and x/g
3) Using the new guess, repeat process until close enough
 Let’s try it for x = 16 and an initial guess of 3
g g*g x/g (g+x/g)/2
3 9 16/3 4.17

6.100L Lecture 1
NUMERICAL EXAMPLE

 Square root of a number x is y such that y*y = x


 Start with a guess, g
1) If g*g is close enough to x, stop and say g is the answer
2) Otherwise make a new guess by averaging g and x/g
3) Using the new guess, repeat process until close enough
 Let’s try it for x = 16 and an initial guess of 3
g g*g x/g (g+x/g)/2
3 9 16/3 4.17

4.17 17.36 3.837 4.0035

6.100L Lecture 1
NUMERICAL EXAMPLE

 Square root of a number x is y such that y*y = x


 Start with a guess, g
1) If g*g is close enough to x, stop and say g is the answer
2) Otherwise make a new guess by averaging g and x/g
3) Using the new guess, repeat process until close enough
 Let’s try it for x = 16 and an initial guess of 3
g g*g x/g (g+x/g)/2
3 9 16/3 4.17

4.17 17.36 3.837 4.0035

4.0035 16.0277 3.997 4.000002

10

6.100L Lecture 1
WE HAVE an ALGORITHM

1) Sequence of simple steps


2) Flow of control process that specifies when each step is
executed
3) A means of determining when to stop

11

6.100L Lecture 1
ALGORITHMS are RECIPES /
RECIPES are ALGORITHMS
 Bake cake from a box
 1) Mix dry ingredients
 2) Add eggs and milk
 3) Pour mixture in a pan
 4) Bake at 350F for 5 minutes
 5) Stick a toothpick in the cake
 6a) If toothpick does not come out clean, repeat step 4 and 5
 6b) Otherwise, take pan out of the oven
 7) Eat

12

6.100L Lecture 1
COMPUTERS are MACHINES that
EXECUTE ALGORITHMS
 Two things computers do:
 Performs simple operations
100s of billions per second!
 Remembers results
100s of gigabytes of storage!
 What kinds of calculations?
 Built-in to the machine, e.g., +
 Ones that you define as the programmer
 The BIG IDEA here?

13

6.100L Lecture 1
A COMPUTER WILL ONLY DO
WHAT YOU TELL IT TO DO

14

6.100L Lecture 1
COMPUTERS are MACHINES that
EXECUTE ALGORITHMS
 Fixed program computer
 Fixed set of algorithms
 What we had until 1940’s
 Stored program computer
 Machine stores and executes instructions
 Key insight: Programs are no different from other kinds of data

15

6.100L Lecture 1
STORED PROGRAM COMPUTER

 Sequence of instructions stored inside computer


 Built from predefined set of primitive instructions
1) Arithmetic and logical
2) Simple tests
3) Moving data
 Special program (interpreter) executes each instruction in
order
 Use tests to change flow of control through sequence
 Stops when it runs out of instructions or executes a halt instruction

16

6.100L Lecture 1
MEMORY

CONTROL ARITHMETIC
UNIT LOGIC UNIT
program counter do primitive ops

INPUT OUTPUT
17

6.100L Lecture 1
3456 3 7889 5
3457 4 7890 2
3458
3459 True
7891
7892 MEMORY
3460 7893
3461 False 7894

Add 3456 3457


Store
Add CONTROL
3458
78897890 ARITHMETIC
Store
Compare
UNIT
7891
34587891
LOGIC UNIT
Print

INPUT OUTPUT
18

6.100L Lecture 1
3456 3 7889 5
3457 4 7890 2
3458
3459 True
7891
7892 MEMORY
3460 7893
3461 False 7894

Add 3456 3457


Store
Add CONTROL
3458
78897890 ARITHMETIC
Store
Compare
UNIT
7891
34587891
LOGIC UNIT
Print

INPUT OUTPUT
19

6.100L Lecture 1
3456 3 7889 5
3457 4 7890 2
3458
3459
7
True
7891
7892 MEMORY
3460 7893
3461 False 7894

Add 3456 3457


Store
Add CONTROL
3458
78897890 ARITHMETIC
Store
Compare
UNIT
7891
34587891
LOGIC UNIT
Print

INPUT OUTPUT
20

6.100L Lecture 1
3456 3 7889 5
3457 4 7890 2
3458
3459
7
True
7891
7892 MEMORY
3460 7893
3461 False 7894

Add 3456 3457


Store
Add CONTROL
3458
78897890 ARITHMETIC
Store
Compare
UNIT
7891
34587891
LOGIC UNIT
Print

INPUT OUTPUT
21

6.100L Lecture 1
3456 3 7889 5
3457 4 7890 2
3458
3459
7
True
7891
7892
7
MEMORY
3460 7893
3461 False 7894

Add 3456 3457


Store
Add CONTROL
3458
78897890 ARITHMETIC
Store
Compare
UNIT
7891
34587891
LOGIC UNIT
Print

INPUT OUTPUT
22

6.100L Lecture 1
3456 3 7889 5
3457 4 7890 2
3458
3459
7
True
7891
7892
7
MEMORY
3460 7893
3461 False 7894

Add 3456 3457


Store
Add CONTROL
3458
78897890 ARITHMETIC
Store
Compare
UNIT
7891
34587891
LOGIC UNIT
Print

INPUT OUTPUT
23

6.100L Lecture 1
3456 3 7889 5
3457 4 7890 2
3458
3459
7
True
7891
7892
7
MEMORY
3460 7893
3461 False 7894

Add 3456 3457


Store
Add CONTROL
3458
78897890 ARITHMETIC
Store
Compare
UNIT
7891
34587891
LOGIC UNIT
Print

INPUT OUTPUT
True

24

6.100L Lecture 1
BASIC PRIMITIVES

 Turing showed that you can compute anything with a very


simple machine with only 6 primitives: left, right, print, scan,
erase, no op

© source unknown. All rights reserved. This


content is excluded from our Creative Commons
license. For more information, see
[Link]

 Real programming languages have


 More convenient set of primitives
 Ways to combine primitives to create new primitives
 Anything computable in one language is computable in any
other programming language
25

6.100L Lecture 1
ASPECTS of LANGUAGES

 Primitive constructs
 English: words
 Programming language: numbers, strings, simple operators

26

6.100L Lecture 1
ASPECTS of LANGUAGES

 Syntax
 English: "cat dog boy"  not syntactically valid
"cat hugs boy"  syntactically valid
 Programming language: "hi"5  not syntactically valid
"hi"*5  syntactically valid

27

6.100L Lecture 1
ASPECTS of LANGUAGES

 Static semantics: which syntactically valid strings have meaning


 English: "I are hungry"  syntactically valid
but static semantic error
 PL: "hi"+5  syntactically valid
but static semantic error

28

6.100L Lecture 1
ASPECTS of LANGUAGES

 Semantics: the meaning associated with a syntactically correct


string of symbols with no static semantic errors
 English: can have many meanings "The chicken is
ready to eat."
 Programs have only one meaning
 But the meaning may not be what programmer intended

29

6.100L Lecture 1
WHERE THINGS GO WRONG

 Syntactic errors
 Common and easily caught
 Static semantic errors
 Some languages check for these before running
program
 Can cause unpredictable behavior
 No linguistic errors, but different meaning
than what programmer intended
 Program crashes, stops running
 Program runs forever
 Program gives an answer, but it’s wrong!

30

6.100L Lecture 1
PYTHON PROGRAMS

 A program is a sequence of definitions and commands


 Definitions evaluated
 Commands executed by Python interpreter in a shell
 Commands (statements) instruct interpreter to do something
 Can be typed directly in a shell or stored in a file that is read
into the shell and evaluated
 Problem Set 0 will introduce you to these in Anaconda

31

6.100L Lecture 1
PROGRAMMING ENVIRONMENT:
ANACONDA

Code Editor
Shell / Console

32

6.100L Lecture 1
OBJECTS

 Programs manipulate data objects


 Objects have a type that defines the kinds of things programs
can do to them
 30
 Is a number
 We can add/sub/mult/div/exp/etc
 'Ana'
 Is a sequence of characters (aka a string)
 We can grab substrings, but we can’t divide it by a number

33

6.100L Lecture 1
OBJECTS

 Scalar (cannot be subdivided)


 Numbers: 8.3, 2
 Truth value: True, False

 Non-scalar (have internal structure that can be accessed)


 Lists
 Dictionaries
 Sequence of characters: "abc"

34

6.100L Lecture 1
SCALAR OBJECTS

 int – represent integers, ex. 5, -100


 float – represent real numbers, ex. 3.27, 2.0
 bool – represent Boolean values True and False
 NoneType – special and has one value, None
 Can use type() to see the type of an object

>>> type(5)
int
>>> type(3.0)
float

35

6.100L Lecture 1
int float
0, 1, 2, …
0.0, …, 0.21, …
300, 301 …
1.0, …, 3.14, …
-1, -2, -3, …
-1.22, …, -500.0 , …
-400, -401, …

bool NoneType
True
False None

36

6.100L Lecture 1
YOU TRY IT!
 In your console, find the type of:
 1234
 8.99
 9.0
 True
 False

37

6.100L Lecture 1
TYPE CONVERSIONS (CASTING)

 Can convert object of one type to another


 float(3) casts the int 3 to float 3.0
 int(3.9) casts (note the truncation!) the float 3.9 to int 3
 Some operations perform implicit casts
 round(3.9)returns the int 4

38

6.100L Lecture 1
YOU TRY IT!
 In your console, find the type of:
 float(123)
 round(7.9)
 float(round(7.2))
 int(7.2)
 int(7.9)

39

6.100L Lecture 1
EXPRESSIONS

 Combine objects and operators to form expressions


 3+2
 5/3
 An expression has a value, which has a type
 3+2 has value 5 and type int
 5/3 has value 1.666667 and type float
 Python evaluates expressions and stores the value. It doesn’t
store expressions!

 Syntax for a simple expression


<object> <operator> <object>

40

6.100L Lecture 1
BIG IDEA
Replace complex
expressions by ONE value
Work systematically to evaluate the expression.

41

6.100L Lecture 1
EXAMPLES

 >>> 3+2
5
 >>> (4+2)*6-1
 35
 >>> type((4+2)*6-1)
 int
 >>> float((4+2)*6-1)
 35.0

42

6.100L Lecture 1
YOU TRY IT!
 In your console, find the values of the following expressions:
 (13-4) / (12*12)
 type(4*3)
 type(4.0*3)
 int(1/2)

43

6.100L Lecture 1
OPERATORS on int and float

 i+j  the sum if both are ints, result is int


 i-j  the difference if either or both are floats, result is float

 i*j  the product


 i/j  division result is always a float

 i//j  floor division What is type of output?

 i%j  the remainder when i is divided by j

 i**j  i to the power of j

44

6.100L Lecture 1
SIMPLE OPERATIONS

 Parentheses tell Python to do these operations first


 Like math!
 Operator precedence without parentheses

**

* / % executed left to right, as appear in expression

+ – executed left to right, as appear in expression

45

6.100L Lecture 1
SO MANY OBJECTS, what to do
with them?!
temp = 100.4
a= 2
go = True
b= -0.3
x= 123 flag = False
n= 17
small = 0.001

46

6.100L Lecture 1
VARIABLES

 Computer science variables are different than math variables


 Math variables
 Abstract
a + 2 = b - 1
 Can represent many values
x * x = y

 CS variables
 Is bound to one single value at a given time a = b + 1
 Can be bound to an expression
(but expressions evaluate to one value!) m = 10
F = m*9.98

47

6.100L Lecture 1
BINDING VARIABLES to VALUES

 In CS, the equal sign is an assignment


 One value to one variable name
 Equal sign is not equality, not “solve for x”
 An assignment binds a value to a name

pi = 355/113

 Step 1: Compute the value on the right hand side (the VALUE)
 Value stored in computer memory
 Step 2: Store it (bind it) to the left hand side (the VARIABLE)
 Retrieve value associated with name by invoking the name
(typing it out)
48

6.100L Lecture 1
YOU TRY IT!
 Which of these are allowed in Python? Type them in the
console to check.
 x = 6
 6 = x
 x*y = 3+4
 xy = 3+4

49

6.100L Lecture 1
ABSTRACTING EXPRESSIONS

 Why give names to values of expressions?


 To reuse names instead of values
 Makes code easier to read and modify
 Choose variable names wisely
 Code needs to read
 Today, tomorrow, next year
 By you and others
 You’ll be fine if you stick to letters,
underscores, don’t start with a number
#Compute approximate value for pi
pi = 355/113
radius = 2.2
area = pi*(radius**2)
circumference = pi*(radius*2)
50

6.100L Lecture 1
WHAT IS BEST CODE STYLE?
#do calculations
a = 355/113 *(2.2**2)
c = 355/113 *(2.2*2)

p = 355/113
r = 2.2
#multiply p with r squared
a = p*(r**2)
#multiply p with r times 2
c = p*(r*2)

#calculate area and circumference of a circle


#using an approximation for pi
pi = 355/113
radius = 2.2
area = pi*(radius**2)
circumference = pi*(radius*2)
51

6.100L Lecture 1
CHANGE BINDINGS

 Can re-bind variable names using new


assignment statements
 Previous value may still stored in memory but
lost the handle for it
 Value for area does not change until you tell the
computer to do the calculation again
3.14
pi = 3.14 pi
radius = 2.2 radius
2.2

area = pi*(radius**2) area 3.2


radius = radius+1
15.1976

52

6.100L Lecture 1
BIG IDEA
Lines are evaluated one
after the other
No skipping around, yet.
We’ll see how lines can be skipped/repeated later.

53

6.100L Lecture 1
YOU TRY IT!
 These 3 lines are executed in order. What are the values of
meters and feet variables at each line in the code?
meters = 100
feet = 3.2808 * meters
meters = 200

ANSWER:
Let’s use PythonTutor to figure out what is going on
 Follow along with this Python Tutor LINK
Where did we tell Python to (re)calculate feet?

54

6.100L Lecture 1
YOU TRY IT!
 Swap values of x and y without binding the numbers directly.
Debug (aka fix) this code.

x = 1 1
y = 2 x
2
y
y = x
x = y
 Python Tutor to the rescue?
ANSWER:
1
x
2
y
temp

55

6.100L Lecture 1
SUMMARY

 Objects
 Objects in memory have types.
 Types tell Python what operations you can do with the objects.
 Expressions evaluate to one value and involve objects and operations.
 Variables bind names to objects.
 = sign is an assignment, for ex. var = type(5*4)

 Programs
 Programs only do what you tell them to do.
 Lines of code are executed in order.
 Good variable names and comments help you read code later.

56

6.100L Lecture 1
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

57
STRINGS, INPUT/OUTPUT,
and BRANCHING
(download slides and .py files to follow along)
6.100L Lecture 2
Ana Bell

1
pi = 3.14 3.14
RECAP radius = 2.2
pi
2.2
area = pi*(radius**2)
radius
area 3.2
radius = radius+1

15.1976
var = type(5*4) var int
 Objects
 Objects in memory have types.
 Types tell Python what operations you can do with the objects.
 Expressions evaluate to one value and involve objects and operations.
 Variables bind names to objects.
 = sign is an assignment, for ex. var = type(5*4)

 Programs
 Programs only do what you tell them to do.
 Lines of code are executed in order.
 Good variable names and comments help you read code later.
2

6.100L Lecture 2 2
STRINGS

6.100L Lecture 2 3
STRINGS

 Think of a str as a sequence of case sensitive characters


 Letters, special characters, spaces, digits
 Enclose in quotation marks or single quotes
 Just be consistent about the quotes
a = "me"
z = 'you'
 Concatenate and repeat strings
b = "myself" a "me"
c = a + b
d = a + " " + b b "myself"

silly = a * 3 c "memyself"

d "me myself"

silly "mememe"

6.100L Lecture 2 4
YOU TRY IT!
What’s the value of s1 and s2?
 b = ":"
c = ")"
s1 = b + 2*c
 f = "a"
g = " b"
h = "3"
s2 = (f+g)*int(h)

6.100L Lecture 2 5
STRING OPERATIONS

 len() is a function used to retrieve the length of a string in


the parentheses

s = "abc"
len(s)  evaluates to 3
chars = len(s)

6.100L Lecture 2 7
SLICING to get
ONE CHARACTER IN A STRING
 Square brackets used to perform indexing
into a string to get the value at a certain
index/position
s = "abc"
index:
index:
0 1 2  indexing always starts at 0
-3 -2 -1  index of last element is len(s) - 1 or -1
s[0]  evaluates to "a"
s[1]  evaluates to "b"
s[2]  evaluates to "c"
s[3]  trying to index out of
bounds, error
s[-1]  evaluates to "c"
s[-2]  evaluates to "b"
s[-3]  evaluates to "a"
7

6.100L Lecture 2 8
SLICING to get a SUBSTRING

 Can slice strings using [start:stop:step]


 Get characters at start
up to and including stop-1
taking every step characters

 If give two numbers, [start:stop], step=1 by default


 If give one number, you are back to indexing for the character
at one location (prev slide)
 You can also omit numbers and leave just colons (try this out!)

6.100L Lecture 2 9
SLICING EXAMPLES

 Can slice strings using [start:stop:step]


 Look at step first. +ve means go left-to-right
-ve means go right-to-left

s = "abcdefgh"
index: 0 1 2 3 4 5 6 7
index: -8 -7 -6 -5 -4 -3 -2 -1

s[3:6]  evaluates to "def", same as s[3:6:1]


s[3:6:2]  evaluates to "df"
s[:]  evaluates to "abcdefgh", same as s[0:len(s):1]
s[::-1]  evaluates to "hgfedcba"
s[4:1:-2] evaluates to "ec"

6.100L Lecture 2 10
YOU TRY IT!
s = "ABC d3f ghi"

s[3:len(s)-1]
s[4:0:-1]
s[6:3]

10

6.100L Lecture 2 11
IMMUTABLE STRINGS

 Strings are “immutable” – cannot be modified


 You can create new objects that are versions of the original one
 Variable name can only be bound to one object
s = "car"
s[0] = 'b'  gives an error
s = 'b'+s[1:len(s)]  is allowed,
s bound to new object
"car"

"bar"

s
11

6.100L Lecture 2 12
BIG IDEA
If you are wondering
“what happens if”…
Just try it out in the console!

12

6.100L Lecture 2 13
INPUT/OUTPUT

13

6.100L Lecture 2 14
PRINTING

 Used to output stuff to console


In [11]: 3+2
Out[11]: 5
 Command is print
In [12]: print(3+2)
5
 Printing many objects in the same command
 Separate objects using commas to output them separated by spaces
 Concatenate strings together using + to print as single object
 a = "the"
b = 3
c = "musketeers"
print(a, b, c)
print(a + str(b) + c)
14

6.100L Lecture 2 15
INPUT
 x = input(s)
 Prints the value of the string s
 User types in something and hits enter
 That value is assigned to the variable x
 Binds that value to a variable
text = input("Type anything: ")
print(5*text)

SHELL:

Type anything:

15

6.100L Lecture 2 17
INPUT
 x = input(s)
 Prints the value of the string s
 User types in something and hits enter
 That value is assigned to the variable x
 Binds that value to a variable
text = input("Type anything: ")
print(5*text)

SHELL:

Type anything: howdy

16

6.100L Lecture 2 18
INPUT
 x = input(s)
 Prints the value of the string s
 User types in something and hits enter
 That value is assigned to the variable x
 Binds that value to a variable
text = input("Type anything: ")
print(5*text)

SHELL:

"howdy" Type anything: howdy

17

6.100L Lecture 2 19
INPUT
 x = input(s)
 Prints the value of the string s
 User types in something and hits enter
 That value is assigned to the variable x
 Binds that value to a variable
text = input("Type anything: ")
print(5*text)

SHELL:

text "howdy" Type anything: howdy

18

6.100L Lecture 2 20
INPUT
 x = input(s)
 Prints the value of the string s
 User types in something and hits enter
 That value is assigned to the variable x
 Binds that value to a variable
text = input("Type anything: ")
print(5*text)

SHELL:

text "howdy" Type anything: howdy


howdyhowdyhowdyhowdyhowdy

19

6.100L Lecture 2 21
INPUT
 input always returns an str, must cast if working with numbers
num1 = input("Type a number: ")
print(5*num1)
num2 = int(input("Type a number: "))
print(5*num2)

SHELL:
num1 "3"
Type a number: 3

20

6.100L Lecture 2 22
INPUT
 input always returns an str, must cast if working with numbers
num1 = input("Type a number: ")
print(5*num1)
num2 = int(input("Type a number: "))
print(5*num2)

SHELL:
num1 "3"
Type a number: 3
33333

21

6.100L Lecture 2 23
INPUT
 input always returns an str, must cast if working with numbers
num1 = input("Type a number: ")
print(5*num1)
num2 = int(input("Type a number: "))
print(5*num2)

SHELL:
num1 "3"
Type a number: 3
33333
Type a number: 3

22

6.100L Lecture 2 24
INPUT
 input always returns an str, must cast if working with numbers
num1 = input("Type a number: ")
print(5*num1)
num2 = int(input("Type a number: "))
print(5*num2)

SHELL:
num1 "3"
Type a number: 3
33333
num2 3
Type a number: 3

23

6.100L Lecture 2 25
INPUT
 input always returns an str, must cast if working with numbers
num1 = input("Type a number: ")
print(5*num1)
num2 = int(input("Type a number: "))
print(5*num2)

SHELL:
num1 "3"
Type a number: 3
33333
num2 3
Type a number: 3
15

24

6.100L Lecture 2 26
YOU TRY IT!
 Write a program that
 Asks the user for a verb
 Prints “I can _ better than you” where you replace _ with the verb.
 Then prints the verb 5 times in a row separated by spaces.
 For example, if the user enters run, you print:
I can run better than you!
run run run run run

25

6.100L Lecture 2 27
AN IMPORTANT ALGORITHM:
NEWTON’S METHOD
 Finds roots of a polynomial
 E.g., find g such that f(g, x) = g3 – x = 0
 Algorithm uses successive approximation
𝑓𝑓(𝑔𝑔𝑔𝑔𝑔𝑔𝑔𝑔𝑔𝑔)
 next_guess = guess -
𝑓𝑓′ (𝑔𝑔𝑔𝑔𝑔𝑔𝑔𝑔𝑔𝑔)

 Partial code of algorithm that gets input and finds next guess

#Try Newton Raphson for cube root


x = int(input('What x to find the cube root of? '))
g = int(input('What guess to start with? '))
print('Current estimate cubed = ', g**3)

next_g = g - ((g**3 - x)/(3*g**2))


print('Next guess to try = ', next_g)
26

6.100L Lecture 2 29
F-STRINGS

 Available starting with Python 3.6


 Character f followed by a
formatted string literal
 Anything that can be appear in a
normal string literal
 Expressions bracketed by curly braces { }
 Expressions in curly braces evaluated at runtime, automatically
converted to strings, and concatenated to the string preceding
them
num = 3000
fraction = 1/3
print(num*fraction, 'is', fraction*100, '% of', num)
print(num*fraction, 'is', str(fraction*100) + '% of', num)
print(f'{num*fraction} is {fraction*100}% of {num}')
27

6.100L Lecture 2 30
BIG IDEA
Expressions can be
placed anywhere.
Python evaluates them!

28

6.100L Lecture 2 32
CONDITIONS for
BRANCHING

29

6.100L Lecture 2 33
BINDING VARIABLES and VALUES

 In CS, there are two notions of equal


 Assignment and Equality test

 variable = value
 Change the stored value of variable to value
 Nothing for us to solve, computer just does the action

 some_expression == other_expression
 A test for equality
 No binding is happening
 Expressions are replaced by values and computer just does the
comparison
 Replaces the entire line with True or False
30

6.100L Lecture 2 34
COMPARISON OPERATORS

 i and j are variable names


 They can be of type ints, float, strings, etc.
 Comparisons below evaluate to the type Boolean
 The Boolean type only has 2 values: True and False

i > j
i >= j
i < j
i <= j
i == j  equality test, True if i is the same as j
i != j  inequality test, True if i not the same as j
31

6.100L Lecture 2 35
LOGICAL OPERATORS on bool

 a and b are variable names (with Boolean values)


not a  True if a is False
False if a is True
a and b  True if both are True
a or b  True if either or both are True

A B A and B A or B
True True True True
True False False True
False True False True
False False False False
32

6.100L Lecture 2 36
COMPARISON EXAMPLE

pset_time = 15
sleep_time = 8
print(sleep_time > pset_time)
derive = True
drink = False
both = drink and derive
print(both)
pset_time 15

sleep_time 8

derive True

drink False

both False

33

6.100L Lecture 2 37
YOU TRY IT!
 Write a program that
 Saves a secret number in a variable.
 Asks the user for a number guess.
 Prints a bool False or True depending on whether the guess
matches the secret.

34

6.100L Lecture 2 38
WHY bool?

 When we get to flow of control, i.e. branching to different


expressions based on values, we need a way of knowing if a
condition is true
 E.g., if something is true, do this, otherwise do that

35

6.100L Lecture 2 40
INTERESTING ALGORITHMS
INVOLVE DECISIONS

It’s midnight

Free
food
email

Go get it! Sleep

36

6.100L Lecture 2 41
If right clear, If right blocked, If right and If right , front,
go right go forward front blocked, left blocked,
go left go back

37

6.100L Lecture 2 42
BRANCHING IN PYTHON
if <condition>:
<code>
<code>
...
<rest of program>

sion>
<expression>
...
else:
<expression>
<expression>
...
<rest of program>

 <condition> has a value True or False


 Indentation matters in Python!
 Do code within if block if condition is True
38

6.100L Lecture 2 43
BRANCHING IN PYTHON
if <condition>:
<code>
<code>
...
<rest of program>

if <condition>:
<code>
<code>
...
else:
<code>
<code>
...
<rest of program>

 <condition> has a value True or False


 Indentation matters in Python!
 Do code within if block when condition is True or code within else
block when condition is False. 39

6.100L Lecture 2 44
BRANCHING IN PYTHON
if <condition>: if <condition>:
<code> <code>
<code> <code>
... ...
<rest of program>
elif <condition>:
<code>
if <condition>: <code>
<code> ...
<code> elif <condition>:
... <code>
else: <code>
<code> ...
<code> <rest of program>
...
<rest of program>

 <condition> has a value True or False


 Indentation matters in Python!
 Run the first block whose corresponding <condition> is True
40

6.100L Lecture 2 45
BRANCHING IN PYTHON
if <condition>: if <condition>: if <condition>:
<code> <code> <code>
<code> <code> <code>
... ... ...
<rest of program>
elif <condition>: elif <condition>:
<code> <code>
if <condition>: <code> <code>
<code> ... ...
<code> elif <condition>: else:
... <code> <code>
else: <code> <code>
<code> ... ...
<code> <rest of program> <rest of program>
...
<rest of program>

 <condition> has a value True or False


 Indentation matters in Python!
 Run the first block whose corresponding <condition> is True.
The else block runs when no conditions were True
41

6.100L Lecture 2 46
BRANCHING EXAMPLE

pset_time = ???
sleep_time = ???
if (pset_time + sleep_time) > 24:
print("impossible!")
elif (pset_time + sleep_time) >= 24:
print("full schedule!")
else:
leftover = abs(24-pset_time-sleep_time)
print(leftover,"h of free time!")
print("end of day")

42

6.100L Lecture 2 47
YOU TRY IT!
 Semantic structure matches visual structure
 Fix this buggy code (hint, it has bad indentation)!
x = int(input("Enter a number for x: "))
y = int(input("Enter a different number for y: "))
if x == y:
print(x,"is the same as",y)
print("These are equal!")

43

6.100L Lecture 2 48
INDENTATION and NESTED
BRANCHING
 Matters in Python
 How you denote blocks of code
x = float(input("Enter a number for x: ")) 5 5 0
y = float(input("Enter a number for y: ")) 5 0 0
if x == y: True False True
print("x and y are equal") <- <-
if y != 0: True False
print("therefore, x / y is", x/y) <-
elif x < y: False
print("x is smaller")
else:
print("y is smaller") <-
print("thanks!") <- <- <-
44

6.100L Lecture 2 50
BIG IDEA
Practice will help you
build a mental model of
how to trace the code
Indentation does a lot of the work for you!

45

6.100L Lecture 2 51
YOU TRY IT!
 What does this code print with
 y=2
 y = 20
 y = 11
 What if if x <= y: becomes elif x <= y: ?

answer = ''
x = 11
if x == y:
answer = answer + 'M'
if x >= y:
answer = answer + 'i'
else:
answer = answer + 'T'
print(answer)

46

6.100L Lecture 2 52
YOU TRY IT!
 Write a program that
 Saves a secret number.
 Asks the user for a number guess.
 Prints whether the guess is too low, too high, or the same as the secret.

47

6.100L Lecture 2 53
BIG IDEA
Debug early,
debug often.
Write a little and test a little.
Don’t write a complete program at once. It introduces too many errors.
Use the Python Tutor to step through code when you see something
unexpected!

48

6.100L Lecture 2 55
SUMMARY

 Strings provide a new data type


 They are sequences of characters, the first one at index 0
 They can be indexed and sliced
 Input
 Done with the input command
 Anything the user inputs is read as a string object!
 Output
 Is done with the print command
 Only objects that are printed in a .py code file will be visible in the shell
 Branching
 Programs execute code blocks when conditions are true
 In an if-elif-elif… structure, the first condition that is True will
be executed
 Indentation matters in Python!
49

6.100L Lecture 2 56
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

50
ITERATION
(download slides and .py files to follow along)
6.100L Lecture 3
Ana Bell

1
LAST LECTURE RECAP

 Strings provide a new data type


 They are sequences of characters, the first one at index 0
 They can be indexed and sliced
 Input
 Done with the input command
 Anything the user inputs is read as a string object!
 Output
 Is done with the print command
 Only objects that are printed in a .py code file will be visible in the shell
 Branching
 Programs execute code blocks when conditions are true
 In an if-elif-elif… structure, the first condition that is True will
be executed
 Indentation matters in Python!
2

6.100L Lecture 3
BRANCHING RECAP
if <condition>: if <condition>: if <condition>:
< code > < code > < code >
< code > < code > < code >
... ... ...
elif <condition>: elif <condition>:
if <condition>: < code > < code >
< code > < code > < code >
< code > ... ...
... elif <condition>: else:
else: < code > < code >
< code > < code > < code >
< code > ... ...
...

 <condition> has a value True or False


 Evaluate the first block whose corresponding <condition> is
True
 A block is started by an if statement
 Indentation matters in Python!
3

6.100L Lecture 3
 If you keep going right, you are
stuck in the same spot forever
 To exit, take a chance and go
 Zelda, Lost Woods tricks you the opposite way
© Nintendo. All rights reserved. This content is excluded from our Creative
Commons license. For more information, see [Link]

if <exit right>:
<set background to woods_background>
if <exit right>:
<set background to woods_background>
if <exit right>:
<set background to woods_background>
and so on and on and on...
else:
<set background to exit_background>
else:
<set background to exit_background>
else:
<set background to exit_background>
4

6.100L Lecture 3
 If you keep going right, you are
stuck in the same spot forever
 To exit, take a chance and go
 Zelda, Lost Woods tricks you the opposite way
© Nintendo. All rights reserved. This content is excluded from our Creative
Commons license. For more information, see [Link]

while <exit_right>:
<set background to woods_background>
<ask user which way to go>
<set background to exit_background>

6.100L Lecture 3
while LOOPS

6.100L Lecture 3
BINGE ALL EPISODES OF ONE SHOW

Netflix: start watching a new show

Play the next one


There are
yes
more
episodes to
watch?
no

Suggest 3 more shows like this one

6.100L Lecture 3
CONTROL FLOW: while LOOPS

while <condition>:
<code>
<code>
...
 <condition> evaluates to a Boolean
 If <condition> is True, execute all the steps inside the
while code block
 Check <condition> again
 Repeat until <condition> is False
 If <condition> is never False, then will loop forever!!
8

6.100L Lecture 3
while LOOP EXAMPLE

You are in the Lost Forest.


************
************

************
************
Go left or right? where "right"

"left"

PROGRAM:
where = input("You're in the Lost Forest. Go left or right? ")
while where == "right":
where = input("You're in the Lost Forest. Go left or right? ")
print("You got out of the Lost Forest!")

6.100L Lecture 3
YOU TRY IT!
 What is printed when you type "RIGHT"?

where = input("Go left or right? ")


while where == "right":
where = input("Go left or right? ")
print("You got out!")

10

6.100L Lecture 3
while LOOP EXAMPLE

n = int(input("Enter a non-negative integer: "))


while n > 0:
print('x')
n = n-1
n 4

11

6.100L Lecture 3
while LOOP EXAMPLE

n = int(input("Enter a non-negative integer: "))


while n > 0:
print('x')
n = n-1

 To terminate:
 Hit CTRL-c or CMD-c in the shell
 Click the red square in the shell

12

6.100L Lecture 3
YOU TRY IT!
 Run this code and stop the infinite loop in your IDE
while True:
print("noooooo")

13

6.100L Lecture 3
BIG IDEA
while loops can repeat
code inside indefinitely!
Sometimes they need your intervention to end the program.

14

6.100L Lecture 3
YOU TRY IT!
 Expand this code to show a sad face when the user entered the
while loop more than 2 times.
 Hint: use a variable as a counter
where = input("Go left or right? ")
while where == "right":
where = input("Go left or right? ")
print("You got out!")

15

6.100L Lecture 3
CONTROL FLOW: while LOOPS

 Iterate through numbers in a sequence

n = 0
while n < 5:
print(n)
n = n+1

16

6.100L Lecture 3
A COMMON PATTERN

 Find 4!
 i is our loop variable
 factorial keeps track of the product
x = 4
i = 1
factorial = 1
while i <= x:
factorial *= i
i += 1
print(f'{x} factorial is {factorial}')

 Python Tutor LINK


17

6.100L Lecture 3
for LOOPS

18

6.100L Lecture 3
ARE YOU STILL WATCHING?
Netflix while falling asleep
(it plays only 4 episodes if
you’re not paying attention)

Play the next episode


4 episodes
in the Still more eps
sequence in sequence

Went through all


eps in sequence
Cuts you off 19

6.100L Lecture 3
CONTROL FLOW:
while and for LOOPS

 Iterate through numbers in a sequence

# very verbose with while loop


n = 0
while n < 5:
print(n)
n = n+1

# shortcut with for loop


for n in range(5):
print(n)
20

6.100L Lecture 3
STRUCTURE of for LOOPS

for <variable> in <sequence of values>:


<code>
...
 Each time through the loop, <variable> takes a value

 First time, <variable> is the first value in sequence


 Next time, <variable> gets the second value
 etc. until <variable> runs out of values
21

6.100L Lecture 3
A COMMON SEQUENCE of VALUES

for <variable> in range(<some_num>):


<code>
<code>
...

for n in range(5):
print(n)

 Each time through the loop, <variable> takes a value


 First time, <variable> starts at 0
 Next time, <variable> gets the value 1
 Then, <variable> gets the value 2
 ...
 etc. until <variable> gets some_num -1
22

6.100L Lecture 3
A COMMON SEQUENCE of VALUES

for <variable> in range(<some_num>):


<code>
<code> n 0
... 1

2
for n in range(5): 3
print(n)
4

 Each time through the loop, <variable> takes a value


 First time, <variable> starts at 0
 Next time, <variable> gets the value 1
 Then, <variable> gets the value 2
 ...
 etc. until <variable> gets some_num -1
23

6.100L Lecture 3
range

 Generates a sequence of ints, following a pattern


 range(start, stop, step)
 start: first int generated
 stop: controls last int generated (go up to but not including this int)
 step: used to generate next int in sequence
 A lot like what we saw for slicing
 Often omit start and step
 e.g., for i in range(4):
 start defaults to 0
 step defaults to 1
 e.g., for i in range(3,5):
 step defaults to 1

24

6.100L Lecture 3
YOU TRY IT!
 What do these print?
 for i in range(1,4,1):
print(i)
 for j in range(1,4,2):
print(j*2)
 for me in range(4,0,-1):
print("$"*me)

25

6.100L Lecture 3
RUNNING SUM

 mysum is a variable to store the running sum


 range(10) makes i be 0 then 1 then 2 then … then 9

mysum = 0 i 0

for i in range(10):
mysum += i
print(mysum)

mysum 0

26

6.100L Lecture 3
RUNNING SUM

 mysum is a variable to store the running sum


 range(10) makes i be 0 then 1 then 2 then … then 9

mysum = 0 i 0

for i in range(10): 1

mysum += i
print(mysum)

mysum 0
1

27

6.100L Lecture 3
RUNNING SUM

 mysum is a variable to store the running sum


 range(10) makes i be 0 then 1 then 2 then … then 9

mysum = 0 i 0

for i in range(10): 1

mysum += i 2

print(mysum)

mysum 1
3

28

6.100L Lecture 3
RUNNING SUM

 mysum is a variable to store the running sum


 range(10) makes i be 0 then 1 then 2 then … then 9

mysum = 0 i 0

for i in range(10): 1

mysum += i 2

print(mysum) 3

mysum 3
6

29

6.100L Lecture 3
RUNNING SUM

 mysum is a variable to store the running sum


 range(10) makes i be 0 then 1 then 2 then … then 9

mysum = 0 i 0

for i in range(10): 1

mysum += i 2

print(mysum)

3

mysum 36
45

30

6.100L Lecture 3
YOU TRY IT!
 Fix this code to use variables start and end in the range, to get
the total sum between and including those values.
 For example, if start=3 and end=5 then the sum should be 12.
mysum = 0
start = ??
end = ??
for i in range(start, end):
mysum += i
print(mysum)

31

6.100L Lecture 3
for LOOPS and range

 Factorial implemented with a while loop (seen this already)


and a for loop
x = 4
i = 1
factorial = 1
while i <= x:
factorial *= i
i += 1
print(f'{x} factorial is {factorial}’)

x = 4
factorial = 1
for i in range(1, x+1, 1):
factorial *= i
print(f'{x} factorial is {factorial}')
32

6.100L Lecture 3
BIG IDEA
for loops only repeat
for however long the
sequence is
The loop variables takes on these values in order.

33

6.100L Lecture 3
SUMMARY

 Looping mechanisms
 while and for loops
 Lots of syntax today, be sure to get lots of practice!
 While loops
 Loop as long as a condition is true
 Need to make sure you don’t enter an infinite loop
 For loops
 Can loop over ranges of numbers
 Can loop over elements of a string
 Will soon see many other things are easy to loop over

34

6.100L Lecture 3
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

35
DECOMPOSITION,
ABSTRACTION, FUNCTIONS
(download slides and .py files to follow along)
6.100L Lecture 7
Ana Bell

1
AN EXAMPLE: the SMARTPHONE

 A black box, and can be viewed in terms of


 Its inputs
 Its outputs
 How outputs are related to inputs, without any
knowledge of its internal workings
 Implementation is “opaque” (or black)

6.100L Lecture 7
AN EXAMPLE: the SMARTPHONE
ABSTRACTION
 User doesn’t know the details of how it
works
 We don’t need to know how something works in
order to know how to use it
 User does know the interface
 Device converts a sequence of screen touches and
sounds into expected useful functionality
 Know relationship between input and output

6.100L Lecture 7
ABSTRACTION ENABLES
DECOMPOSITION
 100’s of distinct parts
 Designed and made by different
companies
 Do not communicate with each other,
other than specifications for components
 May use same subparts as others
 Each component maker has to know
how its component interfaces to other
components
 Each component maker can solve sub-
problems independent of other parts,
so long as they provide specified inputs
 True for hardware and for software 4

6.100L Lecture 7
BIG IDEA
Apply
abstraction (black box) and
decomposition (split into self-contained parts)
to programming!

6.100L Lecture 7
SUPPRESS DETAILS with
ABSTRACTION
 In programming, want to think of piece of code as black box
 Hide tedious coding details from the user
 Reuse black box at different parts in the code (no copy/pasting!)
 Coder creates details, and designs interface
 User does not need or want to see details

6.100L Lecture 7
SUPPRESS DETAILS with
ABSTRACTION
 Coder achieves abstraction with a function (or procedure)
 You’ve already been using functions!
 A function lets us capture code within a black box
 Once we create function, it will produce an output from inputs, while
hiding details of how it does the computation

max(1,4)
abs(-3)
len("mom's spaghetti")

6.100L Lecture 7
SUPPRESS DETAILS with
ABSTRACTION
 A function has specifications, captured using docstrings
 Think of a docstring as “contract” between coder and user:
 If user provides input that satisfies stated conditions, function will
produce output according to specs, including indicated side effects
 Not typically enforced in Python (we’ll see assertions later), but user
relies on coder’s work satisfying the contract

abs(-3)

6.100L Lecture 7
CREATE STRUCTURE with
DECOMPOSITION
 Given the idea of black box abstraction, use it to divide code
into modules that are:
 Self-contained
 Intended to be reusable
 Modules are used to:
 Break up code into logical pieces
 Keep code organized
 Keep code coherent (readable and understandable)
 In this lecture, achieve decomposition with functions
 In a few lectures, achieve decomposition with classes
 Decomposition relies on abstraction to enable construction of
complex modules from simpler ones
9

6.100L Lecture 7
FUNCTIONS

 Reusable pieces of code, called functions or procedures


 Capture steps of a computation so that we can use with any
input
 A function is just some code written in a special, reusable way

10

6.100L Lecture 7
FUNCTIONS

 Defining a function tells Python some code now exists in


memory
 Functions are only useful when they are run (“called” or
“invoked”)
 You write a function once but can run it many times!
 Compare to code in a file
 It doesn’t run when you load the file
 It runs when you hit the run button

11

6.100L Lecture 7
FUNCTION CHARACTERISTICS

 Has a name
 (think: variable bound to a function object)
 Has (formal) parameters (0 or more)
 The inputs
 Has a docstring (optional but recommended)
 A comment delineated by """ (triple quotes) that provides a
specification for the function – contract relating output to input
 Has a body, a set of instructions to execute when function is
called
 Returns something
 Keyword return

12

6.100L Lecture 7
HOW to WRITE a FUNCTION

def is_even( i ):
"""
Input: i, a positive int
Returns True if i is even, otherwise False
"""
if i%2 == 0:
return True
else:
return False

13

6.100L Lecture 7
HOW TO THINK ABOUT WRITING
A FUNCTION
 What is the problem?
 Given an int, call it i, want to know if it is even
 Use this to write the function name and specs

def is_even( i ):
"""
Input: i, a positive int
Returns True if i is even, otherwise False
"""

14

6.100L Lecture 7
HOW TO THINK ABOUT WRITING
A FUNCTION
 How to solve the problem?
 Can check that remainder when divided by 2 is 0
 Think about what value you need to give back

def is_even( i ):
"""
Input: i, a positive int
Returns True if i is even, otherwise False
"""
if i%2 == 0:
return True
else:
return False

15

6.100L Lecture 7
HOW TO THINK ABOUT WRITING
A FUNCTION
 Can you make the code cleaner?
 i%2 is a Boolean that evaluates to True/False already

def is_even( i ):
"""
Input: i, a positive int
Returns True if i is even, otherwise False
"""
return i%2 == 0

16

6.100L Lecture 7
BIG IDEA
At this point, all we’ve
done is make a function
object

17

6.100L Lecture 7
HOW TO CALL (INVOKE) A
FUNCTION

is_even(3)
is_even(8)

 That’s all!

18

6.100L Lecture 7
HOW TO CALL (INVOKE) A
FUNCTION

is_even(3)
is_even(8)

 That’s all!

19

6.100L Lecture 7
ALL TOGETHER IN A FILE

 This code might be in one file

def is_even( i ):
return i%2 == 0

is_even(3)

20

6.100L Lecture 7
WHAT HAPPENS when you CALL a
FUNCTION?
 Python replaces:
formal parameters in function def with values from function call
i replaced with 3

def is_even( i ):
return i%2 == 0

is_even(3)

21

6.100L Lecture 7
WHAT HAPPENS when you CALL a
FUNCTION?
 Python replaces:
formal parameters in function def with values from function call
i replaced with 3
 Python executes expressions in the body of the function
 return 3%2 == 0

def is_even( i ):
return i%2 == 0

is_even(3)

22

6.100L Lecture 7
WHAT HAPPENS when you CALL a
FUNCTION?
 Python replaces:
formal parameters in function def with values from function call
i replaced with 3

def is_even( i ):
return i%2 == 0

is_even(3)
print(is_even(3))

23

6.100L Lecture 7
BIG IDEA
A function’s code
only runs when you
call (aka invoke) the function

24

6.100L Lecture 7
YOU TRY IT!
 Write code that satisfies the following specs
def div_by(n, d):
""" n and d are ints > 0
Returns True if d divides n evenly and False otherwise """

Test your code with:


 n = 10 and d = 3
 n = 195 and d = 13

25

6.100L Lecture 7
ZOOMING OUT
(no functions)

a = 3 Program Scope
b = 4 3
a
c = a+b
b 4

c 7

26

6.100L Lecture 7
ZOOMING OUT

This is my “black box”

def is_even( i ): Program Scope


print("inside is_even") function
Some
is_even
return i%2 == 0 object
code

a = is_even(3)
b = is_even(10)
c = is_even(123456)
This is me telling my black box to do
something
27

6.100L Lecture 7
ZOOMING OUT

This is my “black box”

def is_even( i ): Program Scope


print("inside is_even") function
Some
is_even
return i%2 == 0 object
code
a False

a = is_even(3)
b = is_even(10)
c = is_even(123456)
One function call

28

6.100L Lecture 7
ZOOMING OUT

This is my “black box”

def is_even( i ): Program Scope


print("inside is_even") function
Some
is_even
return i%2 == 0 object
code
a False

b True
a = is_even(3)
b = is_even(10)
c = is_even(123456)

One function call


29

6.100L Lecture 7
ZOOMING OUT

This is my “black box”

def is_even( i ): Program Scope


print("inside is_even") function
Some
is_even
return i%2 == 0 object
code
a False

b True
a = is_even(3)
b = is_even(10) c True
c = is_even(123456)

One function call


30

6.100L Lecture 7
INSERTING FUNCTIONS IN CODE

 Remember how expressions are replaced with the value?


 The function call is replaced with the return value!

print("Numbers between 1 and 10: even or odd")

for i in range(1,10):
if is_even(i):
print(i, "even")
else:
print(i, "odd")

31

6.100L Lecture 7
ANOTHER EXAMPLE

 Suppose we want to add all the odd integers between (and


including) a and b

def sum_odd(a, b):


 What is the input?
# your code here
 Values for a and b
return sum_of_odds
 What is the output?
 The sum_of_odds

32

6.100L Lecture 7
BIG IDEA
Don’t write code right
away!

33

6.100L Lecture 7
PAPER FIRST

 Suppose we want to add all the odd integers between (and


including) a and b

def sum_odd(a, b):


 Start with a simple
# your code here
example on paper
return sum_of_odds
 Systematically solve
the example

34

6.100L Lecture 7
SIMPLE TEST CASE

 Suppose we want to add all the odd integers between (and


including) a and b

def sum_odd(a, b):


 Start with a simple
# your code here
example on paper
return sum_of_odds
 a = 2 and b = 4
 sum_of_odds should be 3

2 3 4

a b 35

6.100L Lecture 7
MORE COMPLEX TEST CASE

 Suppose we want to add all the odd integers between (and


including) a and b

def sum_odd(a, b):


 Start with a simple
# your code here
example on paper
return sum_of_odds
 a = 2 and b = 7
 sum_of_odds should be 15

2 3 4 5 6 7

a b 36

6.100L Lecture 7
2 3 4
SOLVE SIMILAR PROBLEM
a b

 Start by looking at each number between (and including) a and b


 A similar problem that is
easier that you know
how to do? def sum_odd(a, b):
 Add ALL numbers between # your code here
(and including) a and b return sum_of_odds
 Start with this

37

6.100L Lecture 7
2 3 4
CHOOSE BIG-PICTURE STRUCTURE
a b

 Add ALL numbers between


(and including) a and b
 It’s a loop
 while or for? def sum_odd(a, b):
 Your choice # your code here
return sum_of_odds

38

6.100L Lecture 7
WRITE the LOOP 2 3 4
(for adding all numbers)
a b

for LOOP while LOOP


def sum_odd(a, b): def sum_odd(a, b):
for i in range(a, b): i = a
# do something while i <= b:
return sum_of_odds # do something
i += 1
return sum_of_odds

39

6.100L Lecture 7
DO the SUMMING 2 3 4
(for adding all numbers)
a b

for LOOP while LOOP


def sum_odd(a, b): def sum_odd(a, b):
for i in range(a, b): i = a
sum_of_odds += i while i <= b:
return sum_of_odds sum_of_odds += i
i += 1
return sum_of_odds

40

6.100L Lecture 7
INITIALIZE the SUM 2 3 4
(for adding all numbers)
a b

for LOOP while LOOP


def sum_odd(a, b): def sum_odd(a, b):
sum_of_odds = 0 sum_of_odds = 0
for i in range(a, b): i = a
sum_of_odds += i while i <= b:
return sum_of_odds sum_of_odds += i
i += 1
return sum_of_odds

41

6.100L Lecture 7
TEST! 2 3 4
(for adding all numbers)
a b

for LOOP while LOOP


def sum_odd(a, b): def sum_odd(a, b):
sum_of_odds = 0 sum_of_odds = 0
for i in range(a, b): i = a
sum_of_odds += i while i <= b:
return sum_of_odds sum_of_odds += i
i += 1
return sum_of_odds

print(sum_odd(2,4))
print(sum_odd(2,4))
42

6.100L Lecture 7
WEIRD RESULTS… 2 3 4
(for adding all numbers)
a b

for LOOP while LOOP


def sum_odd(a, b): def sum_odd(a, b):
sum_of_odds = 0 sum_of_odds = 0
for i in range(a, b): i = a
sum_of_odds += i while i <= b:
return sum_of_odds sum_of_odds += i
i += 1
return sum_of_odds

print(sum_odd(2,4))
print(sum_odd(2,4)) 9
5
43

6.100L Lecture 7
DEBUG! aka ADD PRINT STATEMENTS 2 3 4
(for adding all numbers)
a b

for LOOP while LOOP


def sum_odd(a, b): def sum_odd(a, b):
sum_of_odds = 0 sum_of_odds = 0
for i in range(a, b): i = a
sum_of_odds += i while i <= b:
print(i, sum_of_odds) sum_of_odds += i
return sum_of_odds print(i, sum_of_odds)
i += 1
22 return sum_of_odds
22
35 35
print(sum_odd(2,4)) 49
print(sum_odd(2,4)) 9
5
44

6.100L Lecture 7
FIX for LOOP END INDEX 2 3 4
(for adding all numbers)
a b

for LOOP while LOOP


def sum_odd(a, b): def sum_odd(a, b):
sum_of_odds = 0 sum_of_odds = 0
for i in range(a, b+1): i = a
sum_of_odds += i while i <= b:
print(i, sum_of_odds) sum_of_odds += i
return sum_of_odds print(i, sum_of_odds)
i += 1
return sum_of_odds
print(sum_odd(2,4))
print(sum_odd(2,4)) 9
9
45

6.100L Lecture 7
2 3 4
ADD IN THE ODD PART!
a b

for LOOP while LOOP


def sum_odd(a, b): def sum_odd(a, b):
sum_of_odds = 0 sum_of_odds = 0
for i in range(a, b+1): i = a
if i%2 == 1: while i <= b:
sum_of_odds += i if i%2 == 1:
print(i, sum_of_odds) sum_of_odds += i
return sum_of_odds print(i, sum_of_odds)
i += 1
print(sum_odd(2,4)) return sum_of_odds
print(sum_odd(2,4)) 3
3
46

6.100L Lecture 7
BIG IDEA
Solve a simpler problem
first.
Add functionality to the code later.

47

6.100L Lecture 7
TRY IT ON ANOTHER 2 3 4 5 6 7
EXAMPLE
a b

for LOOP while LOOP


def sum_odd(a, b): def sum_odd(a, b):
sum_of_odds = 0 sum_of_odds = 0
for i in range(a, b+1): i = a
if i%2 == 1: while i <= b:
sum_of_odds += i if i%2 == 1:
return sum_of_odds sum_of_odds += i
i += 1
return sum_of_odds
print(sum_odd(2,7))
print(sum_odd(2,7)) 15
15
48

6.100L Lecture 7
PYTHON TUTOR

 Also a great debugging tool

49

6.100L Lecture 7
BIG IDEA
Test code often.
Use prints to debug.

50

6.100L Lecture 7
YOU TRY IT!
 Write code that satisfies the following specs
def is_palindrome(s):
""" s is a string
Returns True if s is a palindrome and False otherwise
"""

For example:
 If s = "222" returns True
 If s = "2222" returns True
 If s = "abc" returns False

51

6.100L Lecture 7
SUMMARY

 Functions allow us to suppress detail from a user


 Functions capture computation within a black box
 A programmer writes functions with
 0 or more inputs
 Something to return
 A function only runs when it is called
 The entire function call is replaced with the return value
 Think expressions! And how you replace an entire expression with the
value it evaluates to.

52

6.100L Lecture 7
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

53
FUNCTIONS as OBJECTS
(download slides and .py files to follow along)
6.100L Lecture 8
Ana Bell

1
FUNCTION FROM LAST LECTURE

def is_even( i ):
"""
Input: i, a positive int
Returns True if i is even and False otherwise
"""
return i%2 == 0

 A function always returns something

6.100L Lecture 8
WHAT IF THERE IS
NO return KEYWORD
def is_even( i ):
"""
Input: i, a positive int
Does not return anything
"""
i%2 == 0

 Python returns the value None, if no return given


 Represents the absence of a value
 If invoked in shell, nothing is printed
 No static semantic error generated
3

6.100L Lecture 8
def is_even( i ):
"""
Input: i, a positive int
Does not return anything
"""
i%2 == 0
return None

6.100L Lecture 8
YOU TRY IT!
 What is printed if you run this code as a file?
def add(x,y):
return x+y
def mult(x,y):
print(x*y)

add(1,2)
print(add(2,3))
mult(3,4)
print(mult(4,5))

6.100L Lecture 8
return vs. print

 return only has meaning  print can be used outside


inside a function functions
 only one return executed  can execute many print
inside a function statements inside a function
 code inside function, but  code inside function can be
after return statement, executed after a print
not executed statement
 has a value associated  has a value associated with
with it, given to function it, outputted to the console
caller
 print expression itself returns
None value
6

6.100L Lecture 8
YOU TRY IT!
 Fix the code that tries to write this function
def is_triangular(n):
""" n is an int > 0
Returns True if n is triangular, i.e. equals a continued
summation of natural numbers (1+2+3+...+k), False otherwise """
total = 0
for i in range(n):
total += i
if total == n:
print(True)
print(False)

6.100L Lecture 8
FUNCTIONS SUPPORT
MODULARITY
 Here is our bisection square root method as a function
def bisection_root(x):
epsilon = 0.01
low = 0
Initialize variables
high = x
ans = (high + low)/2.0
guess not close enough
while abs(ans**2 - x) >= epsilon:
if ans**2 < x:
iterate update low or high,
low = ans depends on guess too
else: small or too large
high = ans
ans = (high + low)/2.0 new value for guess
# print(ans, 'is close to the root of', x)
return ans return result

6.100L Lecture 8
FUNCTIONS SUPPORT
MODULARITY
 Call it with different values

print(bisection_root(4))
print(bisection_root(123))

 Write a function that calls this one!

6.100L Lecture 8
YOU TRY IT!
 Write a function that satisfies the following specs
def count_nums_with_sqrt_close_to (n, epsilon):
""" n is an int > 2
epsilon is a positive number < 1
Returns how many integers have a square root within epsilon of n """

Use bisection_root we already wrote to get an approximation


for the sqrt of an integer.
For example: print(count_nums_with_sqrt_close_to(10, 0.1))
prints 4 because all these integers have a sqrt within 0.1
 sqrt of 99 is 9.949699401855469
 sqrt of 100 is 9.999847412109375
 sqrt of 101 is 10.049758911132812
 sqrt of 102 is 10.099456787109375

10

6.100L Lecture 8
ZOOMING OUT

This is my “black box”

def sum_odd(a, b): Program Scope


sum_of_odds = 0
for i in range(a, b+1): sum_odd Some
function
if i%2 == 1: code
object
sum_of_odds += i low 2
return sum_of_odds
high 7
low = 2
high = 7
my_sum = sum_odd(low, high) my_sum

One function call

11

6.100L Lecture 8
ZOOMING OUT

def sum_odd(a, b): Program Scope


sum_of_odds = 0
for i in range(a, b+1): sum_odd Some
function
if i%2 == 1: code
object
sum_of_odds += i low 2
return sum_of_odds
high 7
low = 2
high = 7
my_sum = sum_odd(low, high) my_sum

12

6.100L Lecture 8
ZOOMING OUT

This is my “black box”

def sum_odd(a, b): Program Scope


sum_of_odds = 0
for i in range(a, b+1): sum_odd Some
function
if i%2 == 1: code
object
sum_of_odds += i low 2
return sum_of_odds
high 7
low = 2
high = 7 15
my_sum = sum_odd(low, high) my_sum

15

13

6.100L Lecture 8
FUNCTION SCOPE

14

6.100L Lecture 8
UNDERSTANDING FUNCTION
CALLS

 How does Python execute a function call?


 How does Python know what value is associated with a variable
name?
 It creates a new environment with every function call!
 Like a mini program that it needs to complete
 The mini program runs with assigning its parameters to some inputs
 It does the work (aka the body of the function)
 It returns a value
 The environment disappears after it returns the value

15

6.100L Lecture 8
ENVIRONMENTS

 Global environment
 Where user interacts with Python interpreter
 Where the program starts out
 Invoking a function creates a new environment (frame/scope)

16

6.100L Lecture 8
VARIABLE SCOPE

 Formal parameters get bound to the value of input parameters


 Scope is a mapping of names to objects
 Defines context in which body is evaluated
 Values of variables given by bindings of names
 Expressions in body of function evaluated wrt this new scope
def f( x ):
x = x + 1
print('in f(x): x =', x)
return x

xy = 3
z = f( y
x )
17

6.100L Lecture 8
VARIABLE SCOPE
after evaluating def

This is my “black box”

def f( x ): Global scope


x = x + 1
function
Some
print('in f(x): x =', x) f object
code
return x

x = 3
z = f( x )
18

6.100L Lecture 8
VARIABLE SCOPE
after exec 1st assignment

This is my “black box”

def f( x ): Global scope


x = x + 1
Some
print('in f(x): x =', x) f code
return x
x 3
x = 3
z = f( x )
19

6.100L Lecture 8
VARIABLE SCOPE
after f invoked

def f( x ): Global scope f scope


x = x + 1
Some
print('in f(x): x =', x) f code
x 3
return x
x 3
x = 3
z = f( x )
20

6.100L Lecture 8
VARIABLE SCOPE
after f invoked

def f( x ): Global scope f scope


x = x + 1
Some
print('in f(x): x =', x) f code
x 3
return x
y 3
y = 3
z = f( y )
21

6.100L Lecture 8
VARIABLE SCOPE
eval body of f in f’s scope

in f(x): x = 4 printed out

def f( x ): Global scope f scope


x = x + 1
Some
print('in f(x): x =', x) f code
x 4
3
return x
x 3
x = 3
z = f( x )
22

6.100L Lecture 8
VARIABLE SCOPE
during return

def f( x ): Global scope f scope


x = x + 1
Some
print('in f(x): x =', x) f code
x 4
return x
x 3 returns 4
x = 3
z = f( x )
23

6.100L Lecture 8
VARIABLE SCOPE
after exec 2nd assignment

def f( x ): Global scope


x = x + 1
Some
print('in f(x): x =', x) f code
return x
x 3
x = 3
z = f( x ) 4
z
24

6.100L Lecture 8
BIG IDEA
You need to know what
expression you are executing
to know the scope you are in.

25

6.100L Lecture 8
ANOTHER SCOPE EXAMPLE

 Inside a function, can access a variable defined outside


 Inside a function, cannot modify a variable defined outside
(can by using global variables, but frowned upon)
 Use the Python Tutor to step through these!

def f(y): def g(y): def h(y):


x = 1 print(x) x += 1
x += 1 print(x + 1)
print(x) x = 5
x = 5 h(x)
x = 5 g(x) print(x)
f(x) print(x)
print(x)
5
2 6 Error
5 5

26

6.100L Lecture 8
FUNCTIONS as
ARGUMENTS

27

6.100L Lecture 8
HIGHER ORDER PROCEDURES

 Objects in Python have a type


 int, float, str, Boolean, NoneType, function
 Objects can appear in RHS of assignment statement
 Bind a name to an object
 Objects
 Can be used as an argument to a procedure
 Can be returned as a value from a procedure
 Functions are also first class objects!
 Treat functions just like the other types
 Functions can be arguments to another function
 Functions can be returned by another function

28

6.100L Lecture 8
OBJECTS IN A PROGRAM

function
my_func object with
some code
is_even

def is_even(i): r int object 2


return i%2 == 0
float object
pi
r = 2 3.14285714

pi = 22/7
a False
my_func = is_even
b True
a = is_even(3)

b = my_func(4)

29

6.100L Lecture 8
BIG IDEA
Everything in Python is
an object.

30

6.100L Lecture 8
FUNCTION AS A PARAMETER

def calc(op, x, y):


return op(x,y)

def add(a,b):
return a+b

def div(a,b):
if b != 0:
return a/b
print("Denominator was 0.")

print(calc(add, 2, 3))

31

6.100L Lecture 8
STEP THROUGH THE CODE

def calc(op, x, y):


return op(x,y)
Program Scope
def add(a,b):
return a+b calc function
Some
object
code
def div(a,b):
if b != 0: add function
Some
return a/b
object
code
print("Denom was 0.")
div function
Some
object
code
res = calc(add, 2, 3)

res

32

6.100L Lecture 8
CREATE calc SCOPE

def calc(op, x, y):


return op(x,y)
Program Scope calc scope
def add(a,b):
return a+b calc function
Some
object
code
def div(a,b):
if b != 0: add function
Some
return a/b
object
code
print("Denom was 0.")
div function
Some
object
code
res = calc(add, 2, 3)

res

33

6.100L Lecture 8
MATCH FORMAL PARAMS in calc

def calc(op, x, y):


return op(x,y)
Program Scope calc scope
def add(a,b):
return a+b calc function
Some op add
object
code
def div(a,b):
if b != 0: add function
Some x 2
return a/b
object
code
print("Denom was 0.")
div function
Some y 3
object
code
res = calc(add, 2, 3)

res

34

6.100L Lecture 8
FIRST (and only) LINE IN calc

def calc(op, x, y):


return op(x,y)
Program Scope calc scope
def add(a,b):
return a+b calc function
Some op add
object
code
def div(a,b):
if b != 0: add function
Some x 2
return a/b
object
code
print("Denom was 0.")
div function
Some y 3
object
code
res = calc(add, 2, 3)

res

35

6.100L Lecture 8
CREATE SCOPE OF add

def calc(op, x, y):


return op(x,y)
Program Scope calc scope add scope
def add(a,b):
return a+b calc function
Some op add
object
code
def div(a,b):
if b != 0: add function
Some x 2
return a/b
object
code
print("Denom was 0.")
div function
Some y 3
object
code
res = calc(add, 2, 3)

res

36

6.100L Lecture 8
MATCH FORMAL PARAMS IN add

def calc(op, x, y):


return op(x,y)
Program Scope calc scope add scope
def add(a,b):
return a+b calc function
Some op a
add 2
object
code
def div(a,b):
if b != 0: add function
Some x 2 b 3
return a/b
object
code
print("Denom was 0.")
div function
Some y 3
object
code
res = calc(add, 2, 3)

res

37

6.100L Lecture 8
EXECUTE LINE OF add

def calc(op, x, y):


return op(x,y)
Program Scope calc scope add scope
def add(a,b):
return a+b calc function
Some op a
add 2
object
code
def div(a,b):
if b != 0: add function
Some x 2 b 3
return a/b
object
code
print("Denom was 0.")
div function
Some y 3
object
code
res = calc(add, 2, 3)

res
returns 5
38

6.100L Lecture 8
REPLACE FUNC CALL WITH RETURN

def calc(op, x, y):


return op(x,y)
Program Scope calc scope
def add(a,b):
return a+b calc function
Some op add
object
code
def div(a,b):
if b != 0: add function
Some x 2
return a/b
object
code
print("Denom was 0.")
div function
Some y 3
object
code
res = calc(add, 2, 3)

res

39

6.100L Lecture 8
EXECUTE LINE OF calc

def calc(op, x, y):


return op(x,y)
Program Scope calc scope
def add(a,b):
return a+b calc function
Some op add
object
code
def div(a,b):
if b != 0: add function
Some x 2
return a/b
object
code
print("Denom was 0.")
div function
Some y 3
object
code
res = calc(add, 2, 3)

res
returns 5
40

6.100L Lecture 8
REPLACE FUNC CALL WITH RETURN

def calc(op, x, y):


return op(x,y)
Program Scope
def add(a,b):
return a+b calc function
Some
object
code
def div(a,b):
if b != 0: add function
Some
return a/b
object
code
print("Denom was 0.")
div function
Some
object
code
res = calc(add, 2, 3)

res 5

41

6.100L Lecture 8
YOU TRY IT!
 Do a similar trace with the function call
def calc(op, x, y):
return op(x,y)

def div(a,b):
if b != 0:
return a/b
print("Denom was 0.")

res = calc(div,2,0)

What is the value of res and what gets printed?

42

6.100L Lecture 8
ANOTHER EXAMPLE:
FUNCTIONS AS PARAMS

def func_a():
print('inside func_a')
def func_b(y):
print('inside func_b')
return y
def func_c(f, z):
print('inside func_c')
return f(z)
print(func_a())
print(5 + func_b(2))
print(func_c(func_b, 3))
43

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope func_a scope


def func_a(): Some
func_a
print('inside func_a') code
def func_b(y): Some
func_b code
print('inside func_b')
return y Some
def func_c(f, z): func_c code

print('inside func_c')
return f(z)
print(func_a())
print(5 + func_b(2))
print(func_c(func_b, 3))
44

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope func_a scope


def func_a(): Some
func_a
print('inside func_a') code
def func_b(y): Some
func_b code
print('inside func_b')
return y Some
def func_c(f, z): func_c code

print('inside func_c') None


return f(z)
print(func_a())
print(5 + func_b(2))
print(func_c(func_b, 3))
45

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope
def func_a(): Some
func_a
print('inside func_a') code
def func_b(y): Some
func_b code
print('inside func_b')
return y Some
def func_c(f, z): func_c code

print('inside func_c')
return f(z)
print(func_a())
print(5 + func_b(2))
print(func_c(func_b, 3))
46

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope func_b scope


def func_a(): Some
func_a y 2
print('inside func_a') code
def func_b(y): Some
func_b code
print('inside func_b')
return y Some
func_c code
def func_c(f, z):
print('inside func_c') None
return f(z)
print(func_a())
print(5 + func_b(2))
print(func_c(func_b, 3))
47

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope func_b scope


def func_a(): Some
func_a y 2
print('inside func_a') code
def func_b(y): Some
func_b code
print('inside func_b')
return y Some
func_c code
def func_c(f, z):
print('inside func_c') None
return f(z)
print(func_a())
print(5 + func_b(2))
print(func_c(func_b, 3))
48

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope func_b scope


def func_a(): Some
func_a y 2
print('inside func_a') code
def func_b(y): Some
func_b code
print('inside func_b')
return y Some
func_c code
def func_c(f, z):
print('inside func_c') None
return f(z)
print(func_a()) 7 returns 2
print(5 + func_b(2))
print(func_c(func_b, 3))
49

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope
def func_a(): Some
func_a
print('inside func_a') code
def func_b(y): Some
func_b code
print('inside func_b')
return y Some
func_c code
def func_c(f, z):
print('inside func_c') None
return f(z)
print(func_a()) 7
print(5 + func_b(2))
print(func_c(func_b, 3))
50

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope func_c scope


def func_a(): Some
func_a f func_b
print('inside func_a') code
def func_b(y): Some z
3
func_b code
print('inside func_b')
return y Some
func_c code
def func_c(f, z):
print('inside func_c') None
return f(z)
print(func_a()) 7
print(5 + func_b(2))
print(func_c(func_b, 3))
51

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope func_c scope


def func_a(): Some
func_a f func_b
print('inside func_a') code
def func_b(y): Some z
3
func_b code
print('inside func_b')
return y Some 3
func_c code
def func_c(f, z):
print('inside func_c') None returns 3 func_b scope
return f(z)
print(func_a()) y 3
7
print(5 + func_b(2))
print(func_c(func_b, 3))
52

6.100L Lecture 8
FUNCTIONS AS PARAMETERS

Global scope func_c scope


def func_a(): Some
func_a f func_b
print('inside func_a') code
def func_b(y): Some z
3
func_b code
print('inside func_b')
return y Some 3
func_c code
def func_c(f, z):
print('inside func_c') None
return f(z)
print(func_a()) 7
print(5 + func_b(2))
print(func_c(func_b, 3)) 3
53
returns 3
6.100L Lecture 8
YOU TRY IT!
 Write a function that meets these specs.
def apply(criteria,n):
"""
* criteria is a func that takes in a number and returns a bool
* n is an int
Returns how many ints from 0 to n (inclusive) match
the criteria (i.e. return True when run with criteria)
"""

54

6.100L Lecture 8
SUMMARY

 Functions are first class objects


 They have a type
 They can be assigned as a value bound to a name
 They can be used as an argument to another procedure
 They can be returned as a value from another procedure
 Have to be careful about environments
 Main program runs in the global environment
 Function calls each get a new temporary environment
 This enables the creation of concise, easily read code

55

6.100L Lecture 8
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

56
LAMBDA FUNCTIONS,
TUPLES and LISTS
(download slides and .py files to follow along)
6.100L Lecture 9
Ana Bell

1
FROM LAST TIME

def apply(criteria,n):
"""
* criteria: function that takes in a number and returns a bool
* n: an int
Returns how many ints from 0 to n (inclusive) match the
criteria (i.e. return True when run with criteria) """
count = 0
for i in range(n+1):
if criteria(i):
count += 1
return count

def is_even(x):
return x%2==0

print(apply(is_even,10))

6.100L Lecture 9
ANONYMOUS FUNCTIONS

 Sometimes don’t want to name functions, especially simple


ones. This function is a good example:
def is_even(x):
return x%2==0
 Can use an anonymous procedure by using lambda

lambda x: x%2 == 0

Body of lambda
parameter Note no return keyword

 lambda creates a procedure/function object, but simply does


not bind a name to it
3

6.100L Lecture 9
ANONYMOUS FUNCTIONS

 Function call with a named function:

apply( is_even , 10 )

 Function call with an anonymous function as parameter:

apply( lambda x: x%2 == 0 , 10 )

 lambda function is one-time use. It can’t be reused because it


has no name!

6.100L Lecture 9
YOU TRY IT!
 What does this print?

def do_twice(n, fn):


return fn(fn(n))

print(do_twice(3, lambda x: x**2))

6.100L Lecture 9
YOU TRY IT!
 What does this print?

def do_twice(n, fn):


return fn(fn(n))

print(do_twice(3, lambda x: x**2))

Global environment

do_twice function object

6.100L Lecture 9
YOU TRY IT!
 What does this print?

def do_twice(n, fn):


return fn(fn(n))

print(do_twice(3, lambda x: x**2))

Global environment do_twice environment

do_twice function object n 3


fn lambda x: x**2

6.100L Lecture 9
YOU TRY IT!
 What does this print?

def do_twice(n, fn):


return fn(fn(n))

print(do_twice(3, lambda x: x**2))

Global environment do_twice environment lambda x: x**2


environment
do_twice function object n 3
fn lambda x: x**2 x ???

6.100L Lecture 9
YOU TRY IT!
 What does this print?

def do_twice(n, fn):


return fn(fn(n))

print(do_twice(3, lambda x: x**2))

Global environment do_twice environment lambda x: x**2


environment
do_twice function object n 3
fn lambda x: x**2 x ???

lambda x: x**2
environment

x 3
9

6.100L Lecture 9
YOU TRY IT!
 What does this print?

def do_twice(n, fn):


9
return fn(fn(n))

print(do_twice(3, lambda x: x**2))

Global environment do_twice environment lambda x: x**2


environment
do_twice function object n 3
fn lambda x: x**2 x 9
???

lambda x: x**2
environment

x 3
10
Returns 9
6.100L Lecture 9
YOU TRY IT!
 What does this print?

def do_twice(n, fn):


81
return fn(fn(n))

print(do_twice(3, lambda x: x**2))

Global environment do_twice environment lambda x: x**2


environment
do_twice function object n 3
fn lambda x: x**2 x 99
Returns 81

11

6.100L Lecture 9
YOU TRY IT!
 What does this print?

def do_twice(n, fn):


return fn(fn(n))
81
print(do_twice(3, lambda x: x**2))

Global environment do_twice environment

do_twice function object n 3


fn lambda x: x**2
PRINTS 81
Returns 81

12

6.100L Lecture 9
TUPLES

13

6.100L Lecture 9
A NEW DATA TYPE

 Have seen scalar types: int,float,bool


 Have seen one compound type: string
 Want to introduce more general compound data types
 Indexed sequences of elements, which could themselves be compound
structures
 Tuples – immutable
 Lists – mutable

 Next lecture, will explore ideas of


 Mutability
 Aliasing
 Cloning

14

6.100L Lecture 9
TUPLES

 Indexable ordered sequence of objects


 Objects can be any type – int, string, tuple, tuple of tuples, …
 Cannot change element values, immutable
te = ()
ts = (2,)

t = (2, "mit", 3)
t[0]  evaluates to 2
(2,"mit",3) + (5,6)evaluates to a new tuple(2,"mit",3,5,6)
t[1:2]  slice tuple, evaluates to ("mit",)
t[1:3]  slice tuple, evaluates to ("mit",3)
len(t)  evaluates to 3
max((3,5,0))  evaluates 5
t[1] = 4  gives error, can’t modify object
15

6.100L Lecture 9
INDICES AND SLICING

seq = (2,'a',4,(1,2))
index: 0 1 2 3
print(len(seq))  4
print(seq[3])  (1,2)
print(seq[-1])  (1,2)
print(seq[3][0])  1
print(seq[4])  error

print(seq[1])  'a'
print(seq[-2:]  (4,(1,2))
print(seq[1:4:2]  ('a',(1,2))
print(seq[:-1])  (2,'a',4)
print(seq[1:3])  ('a',4)

for e in seq:  2
print(e) a
4
(1,2) 16

6.100L Lecture 9
TUPLES

 Conveniently used to swap variable values


x = 1 x = 1 x = 1
y = 2 y = 2 y = 2
x = y temp = x (x, y) = (y, x)
y = x x = y
y = temp

17

6.100L Lecture 9
TUPLES

 Used to return more than one value from a function


def quotient_and_remainder(x, y):
q = x // y
r = x % y
return (q, r)

both = quotient_and_remainder(10,3)

(quot, rem) = quotient_and_remainder(5,2)

18

6.100L Lecture 9
BIG IDEA
Returning
one object (a tuple)
allows you to return
multiple values (tuple elements)

19

6.100L Lecture 9
YOU TRY IT!
 Write a function that meets these specs:
 Hint: remember how to check if a character is in a string?

def char_counts(s):
""" s is a string of lowercase chars
Return a tuple where the first element is the
number of vowels in s and the second element
is the number of consonants in s """

20

6.100L Lecture 9
VARIABLE NUMBER of
ARGUMENTS

 Python has some built-in functions that take variable number


of arguments, e.g, min
 Python allows a programmer to have same capability,
using * notation
def mean(*args):
tot = 0
for a in args:
tot += a
return tot/len(args)
 numbers is bound to a tuple of the supplied values
 Example:
 mean(1,2,3,4,5,6)
21

6.100L Lecture 9
LISTS

22

6.100L Lecture 9
LISTS

 Indexable ordered sequence of objects


• Usually homogeneous (i.e., all integers, all strings, all lists)
• But can contain mixed types (not common)
 Denoted by square brackets, []
 Mutable, this means you can change values of specific
elements of list

23

6.100L Lecture 9
INDICES and ORDERING

a_list = []
L = [2, 'a', 4, [1,2]]
[1,2]+[3,4]  evaluates to [1,2,3,4]
len(L)  evaluates to 4
L[0]  evaluates to 2
L[2]+1  evaluates to 5
L[3]  evaluates to [1,2], another list!
L[4]  gives an error
i = 2
L[i-1]  evaluates to 'a' since L[1]='a'
max([3,5,0])  evaluates 5
24

6.100L Lecture 9
ITERATING OVER a LIST

 Compute the sum of elements of a list


 Common pattern

total = 0 total = 0
for i in range(len(L)): for i in L:
total += L[i] total += i
print(total) print(total)

 Notice
• list elements are indexed 0 to len(L)-1
and range(n) goes from 0 to n-1

25

6.100L Lecture 9
ITERATING OVER a LIST

 Natural to capture iteration over a list inside a function

def list_sum(L):
total = 0 total = 0
for i in L: for i in L:
# i is 8 then 3 then 5
total += i total += i
print(total) return total

 Function call list_sum([8,3,5])


 Loop variable i takes on values in the list in order! 8 then 3 then 5
 To help you write code and debug, comment on what the loop var
values are so you don’t get confused!
26

6.100L Lecture 9
LISTS SUPPORT ITERATION

 Because lists are ordered sequences of elements, they naturally


interface with iterative functions

Add the elements of a list Add the length of elements of a list


def list_sum(L): def len_sum(L):
total = 0 total = 0
for e in L: for s in L:
total += e total += len(s)
return(total) return(total)
list_sum([1,3,5])  9 len_sum(['ab', 'def', 'g'])  6

27

6.100L Lecture 9
YOU TRY IT!
 Write a function that meets these specs:
def sum_and_prod(L):
""" L is a list of numbers
Return a tuple where the first value is the
sum of all elements in L and the second value
is the product of all elements in L """

28

6.100L Lecture 9
SUMMARY

 Lambda functions are useful when you need a simple function


once, and whose body can be written in one line
 Tuples are indexable sequences of objects
 Can’t change its elements, for ex. can’t add more objects to a tuple
 Syntax is to use ()
 Lists are indexable sequences of objects
 Can change its elements. Will see this next time!
 Syntax is to use []
 Lists and tuples are very similar to strings in terms of
 Indexing,
 Slicing,
 Looping over elements
29

6.100L Lecture 9
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

30
LISTS, MUTABILITY
(download slides and .py files to follow along)
6.100L Lecture 10
Ana Bell

1
INDICES and ORDERING in LISTS

a_list = []
L = [2, 'a', 4, [1,2]]
len(L)  evaluates to 4
L[0]  evaluates to 2
L[3]  evaluates to [1,2], another list!
[2,'a'] + [5,6]  evaluates to [2,'a',5,6]
max([3,5,0])  evaluates to 5
L[1:3]  evaluates to ['a', 4]
for e in L  loop variable becomes each element in L
L[3] = 10  mutates L to [2,'a',4,10]
2

6.100L Lecture 10
MUTABILITY

 Lists are mutable!


 Assigning to an element at an index changes the value
L = [2, 4, 3]
L[1] = 5
 L is now [2, 5, 3]; note this is the same object L

[2,4,3]
[2,5,3]

L
3

6.100L Lecture 10
MUTABILITY

 Compare
 Making L by mutating an element vs.
 Making t by creating a new object

L = [2, 4, 3]
L[1] = 5 L [2,5,3]
[2,4,3]

t = (2, 4, 3) t x (2,4,3)
t = (2, 5, 3) (2,5,3)

6.100L Lecture 10
OPERATION ON LISTS – append

 Add an element to end of list with [Link](element)


 Mutates the list!
L = [2,1,3]
[Link](5)  L is now [2,1,3,5]

[2,1,3]
[2,1,3,5]

L
6.100L Lecture 10

5
OPERATION ON LISTS – append

 Add an element to end of list with [Link](element)


 Mutates the list!
L = [2,1,3]
[Link](5)  L is now [2,1,3,5]
L = [Link](5)

[2,1,3]
[2,1,3,5]

L
6.100L Lecture 10

6
OPERATION ON LISTS – append

 Add an element to end of list with [Link](element)


 Mutates the list!
L = [2,1,3]
[Link](5)  L is now [2,1,3,5]
L = [Link](5)

[2,1,3,5,5]
[2,1,3]

L
6.100L Lecture 10

7
OPERATION ON LISTS – append

 Add an element to end of list with [Link](element)


 Mutates the list!
L = [2,1,3]
[Link](5)  L is now [2,1,3,5]
L = [Link](5)

[2,1,3,5,5]
[2,1,3]

None

L
6.100L Lecture 10

8
OPERATION ON LISTS – append

 Add an element to end of list with [Link](element)


 Mutates the list!
L = [2,1,3]
[Link](5)  L is now [2,1,3,5]
[Link](5)  L is now [2,1,3,5,5]
print(L)
[2,1,3,5,5]
[2,1,3]

L
6.100L Lecture 10

9
YOU TRY IT!
 What is the value of L1, L2, L3 and L at the end?
L1 = ['re']
L2 = ['mi']
L3 = ['do']
L4 = L1 + L2
[Link](L4)
L = [Link](L3)

10

6.100L Lecture 10
BIG IDEA
Some functions mutate
the list and don’t return
anything.
We use these functions for their side effect.

11

6.100L Lecture 10
OPERATION ON LISTS: append

 L = [2,1,3]
[Link](5)

 What is the dot?


• Lists are Python objects, everything in Python is an object
• Objects have data
• Object types also have associated operations
• Access this information by object_name.do_something()
• Equivalent to calling append with arguments L and 5
12

6.100L Lecture 10
YOU TRY IT!
 Write a function that meets these specs:
def make_ordered_list(n):
""" n is a positive int
Returns a list containing all ints in order
from 0 to n (inclusive)
"""

13

6.100L Lecture 10
YOU TRY IT!
 Write a function that meets the specification.
def remove_elem(L, e):
"""
L is a list
Returns a new list with elements in the same order as L
but without any elements equal to e.
"""

L = [1,2,2,2]
print(remove_elem(L, 2)) # prints [1]

14

6.100L Lecture 10
STRINGS to LISTS

 Convert string to list with list(s)


 Every character from s is an element in a list
 Use [Link](), to split a string on a character parameter,
splits on spaces if called without a parameter

s = "I<3 cs &u?"  s is a string


L = list(s)  L is ['I','<','3',' ','c','s',' ','&','u','?']

L1 = [Link](' ')  L1 is ['I<3','cs','&u?']


L2 = [Link]('<')  L2 is ['I', '3 cs &u?']

15

6.100L Lecture 10
LISTS to STRINGS

 Convert a list of strings back to string


 Use ''.join(L) to turn a list of strings into a bigger string
 Can give a character in quotes to add char between every
element
L = ['a','b','c']  L is a list
A = ''.join(L)  A is "abc"
B = '_'.join(L)  B is "a_b_c"
C = ''.join([1,2,3])  an error
C = ''.join(['1','2','3']  C is "123" a string!

16

6.100L Lecture 10
YOU TRY IT!
 Write a function that meets these specs:
def count_words(sen):
""" sen is a string representing a sentence
Returns how many words are in s (i.e. a word is a
a sequence of characters between spaces. """

print(count_words("Hello it's me"))

17

6.100L Lecture 10
A FEW INTERESTING LIST
OPERATIONS
 Add an element to end of list with [Link](element)
 mutates the list
 sort()
 L = [4,2,7]
[Link]()
 Mutates L
 reverse()
 L = [4,2,7]
[Link]()
 Mutates L
 sorted()
 L = [4,2,7]
 L_new = sorted(L)
 Returns a sorted version of L (no mutation!)

18

6.100L Lecture 10
MUTABILITY

L=[9,6,0,3]
[Link](5)
a = sorted(L)  returns a new sorted list, does not mutate L

b = [Link]()  mutates L to be [0,3,5,6,9] and returns None


[Link]()  mutates L to be [9,6,5,3,0] and returns None

[9,6,0,3,5]
[9,6,0,3]

19

6.100L Lecture 10
MUTABILITY

L=[9,6,0,3]
[Link](5)
a = sorted(L)  returns a new sorted list, does not mutate L

b = [Link]()  mutates L to be [0,3,5,6,9] and returns None


[Link]()  mutates L to be [9,6,5,3,0] and returns None

[9,6,0,3,5]

L
[0,3,5,6,9]

a
20

6.100L Lecture 10
MUTABILITY

L=[9,6,0,3]
[Link](5)
a = sorted(L)  returns a new sorted list, does not mutate L

b = [Link]()  mutates L to be [0,3,5,6,9] and returns None


[Link]()  mutates L to be [9,6,5,3,0] and returns None

None
b
[0,3,5,6,9]
[9,6,0,3,5]

L
[0,3,5,6,9]

a
21

6.100L Lecture 10
MUTABILITY

L=[9,6,0,3]
[Link](5)
a = sorted(L)  returns a new sorted list, does not mutate L

b = [Link]()  mutates L to be [0,3,5,6,9] and returns None


[Link]()  mutates L to be [9,6,5,3,0] and returns None

None
b
[9,6,5,3,0]
[0,3,5,6,9]

L
[0,3,5,6,9]

a
22

6.100L Lecture 10
YOU TRY IT!
 Write a function that meets these specs:
def sort_words(sen):
""" sen is a string representing a sentence
Returns a list containing all the words in sen but
sorted in alphabetical order. """

print(sort_words("look at this photograph"))

23

6.100L Lecture 10
BIG IDEA
Functions with side
effects mutate inputs.
You can write your own!

24

6.100L Lecture 10
LISTS SUPPORT ITERATION

 Let’s write a function that mutates the input


 Example: square every element of a list, mutating original list

def square_list(L):
for elem in L:
# ?? How to do L[index] = the square ??
# ?? elem is an element in L, not the index :(

 Solutions (we’ll go over option 2, try the others on your own!):


 Option 1: Make a new variable representing the index, initialized to 0
before the loop and incremented by 1 in the loop.
 Option 2: Loop over the index not the element, and use L[index] to get
the element
 Option 3: Use enumerate in the for loop (I leave this option to you to
look up). i.e. for i,e in enumerate(L)
25

6.100L Lecture 10
LISTS SUPPORT ITERATION

 Example: square every element of a list, mutating original list

def square_list(L):
for i in range(len(L)):
L[i] = L[i]**2

 Note, no return!
26

6.100L Lecture 10
TRACE the CODE with an
EXAMPLE
 Example: square every element of a list, mutating original list

def square_list(L):
for i in range(len(L)):
L[i] = L[i]**2

Suppose L is [2,3,4]
i is 0: L is mutated to [4, 3, 4]
i is 1: L is mutated to [4, 9, 4]
i is 2: L is mutated to [4, 9, 16]

27

6.100L Lecture 10
TRACE the CODE with an
EXAMPLE
 Example: square every element of a list, mutating original list

def square_list(L):
for i in range(len(L)):
L[i] = L[i]**2

Lin = [2,3,4]
print("before fcn call:",Lin) # prints [2,3,4]
square_list(Lin)
print("after fcn call:",Lin) # prints [4,9,16]

28

6.100L Lecture 10
BIG IDEA
Functions that mutate
the input likely…..
Iterate over len(L) not L.
Return None, so the function call does not need to be saved.

29

6.100L Lecture 10
MUTATION

 Lists are mutable structures


 There are many advantages to being able to change a portion
of a list
 Suppose I have a very long list (e.g. of personnel records) and I want to
update one element. Without mutation, I would have to copy the
entire list, with a new version of that record in the right spot. A
mutable structure lets me change just that element
 But, this ability can also introduce unexpected challenges

30

6.100L Lecture 10
TRICKY EXAMPLES OVERVIEW

 TRICKY EXAMPLE 1:
 A loop iterates over indices of L and mutates L each time (adds more
elements).
 TRICKY EXAMPLE 2:
 A loop iterates over L’s elements directly and mutates L each time (adds
more elements).
 TRICKY EXAMPLE 3:
 A loop iterates over L’s elements directly but reassigns L to a new
object each time
 TRICKY EXAMPLE 4 (next time):
 A loop iterates over L’s elements directly and mutates L by removing
elements.

31

6.100L Lecture 10
TRICKY EXAMPLE 1: append

 Range returns something that behaves like a tuple


(but isn’t – it returns an iterable)
 Returns the first element, and an iteration method by which
subsequent elements are generated as needed
range(4)  kind of like tuple (0,1,2,3)
range(2,9,2)  kind of like tuple (2,4,6,8)
L = [1,2,3,4]
for i in range(len(L)):
1st time: L is [1, 2, 3, 4, 0]
[Link](i)
2nd time: L is [1, 2, 3, 4, 0, 1]
print(L) 3rd time: L is [1, 2, 3, 4, 0, 1, 2]
4th time: L is [1, 2, 3, 4, 0, 1, 2, 3]
32

6.100L Lecture 10
TRICKY EXAMPLE 1: append

L = [1,2,3,4]
for i in range(len(L)):
[Link](i) [1,2,3,4,0,1,2]
[1,2,3,4,0]
[1,2,3,4]
[1,2,3,4,0,1]
[1,2,3,4,0,1,2,3]

print(L) L
(0,1,2,3)

i
1st time: L is [1, 2, 3, 4, 0]
2nd time: L is [1, 2, 3, 4, 0, 1]
3rd time: L is [1, 2, 3, 4, 0, 1, 2]
4th time: L is [1, 2, 3, 4, 0, 1, 2, 3]

33

6.100L Lecture 10
TRICKY EXAMPLE 2: append

Looks similar but … e


L = [1,2,3,4]
i = 0 [1,2,3,4,0,1]
[1,2,3,4,0,1,2]
[1,2,3,4,0]
[1,2,3,4]

for e in L: 1
3
0
2
L
[Link](i)
i
i += 1
print(L) 1st time: L is [1, 2, 3, 4, 0]
2nd time: L is [1, 2, 3, 4, 0, 1]
In previous example, L was accessed at
onset to create a range iterable; in this 3rd time: L is [1, 2, 3, 4, 0, 1, 2]
example, the loop is directly accessing 4th time: L is [1, 2, 3, 4, 0, 1, 2, 3]
indices into L NEVER STOPS!
34

6.100L Lecture 10
COMBINING LISTS

 Concatenation, + operator, creates a new list, with copies


 Mutate list with [Link](some_list) (copy of some_list)
L1 = [2,1,3]
L2 = [4,5,6]
L3 = L1 + L2  L3 is [2,1,3,4,5,6]

L1 [2,1,3]

L2 [4,5,6]

L3 [2,1,3,4,5,6]

35

6.100L Lecture 10
COMBINING LISTS

 Concatenation, + operator, creates a new list, with copies


 Mutate list with [Link](some_list) (copy of some_list)
L1 = [2,1,3]
L2 = [4,5,6]
L3 = L1 + L2  L3 is [2,1,3,4,5,6]
[Link]([0,6])  mutate L1 to [2,1,3,0,6]

L1 [2,1,3]
[2,1,3,0,6]

L2 [4,5,6]

L3 [2,1,3,4,5,6]

36

6.100L Lecture 10
COMBINING LISTS

 Concatenation, + operator, creates a new list, with copies


 Mutate list with [Link](some_list) (copy of some_list)
L1 = [2,1,3]
L2 = [4,5,6]
L3 = L1 + L2  L3 is [2,1,3,4,5,6]
[Link]([0,6])  mutate L1 to [2,1,3,0,6]
[Link]([[1,2],[3,4]])  mutates L2 to [4,5,6,[1,2],[3,4]]

L1 [2,1,3]
[2,1,3,0,6]

L2 [4,5,6]
[4,5,6,[1,2],[3,4]]

L3 [2,1,3,4,5,6]

37

6.100L Lecture 10
TRICKY EXAMPLE 3: combining

1st time: new L is [1, 2, 3, 4, 1, 2, 3, 4]


2nd time: new L is [ 1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4]
L = [1,2,3,4]
3rd time: new L is [ 1, 2, 3, 4, 1, 2, 3, 4,
for e in L: 1, 2, 3, 4, 1, 2, 3, 4
1, 2, 3, 4, 1, 2, 3, 4,
L = L + L 1, 2, 3, 4, 1, 2, 3, 4]
4th time: new L is [ 1, 2, 3, 4, 1, 2, 3, 4,
print(L) 1, 2, 3, 4, 1, 2, 3, 4
1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4
1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4
1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4]
38

6.100L Lecture 10
TRICKY EXAMPLE 3: combining

e
L = [1,2,3,4]
for e in L: [1,2,3,4]

[1,2,3,4,1,2,3,4]
L = L + L L

print(L)

1st time: new L is [1, 2, 3, 4, 1, 2, 3, 4]

39

6.100L Lecture 10
TRICKY EXAMPLE 3: combining

e
L = [1,2,3,4]
for e in L: [1,2,3,4]

[1,2,3,4,1,2,3,4]
L = L + L L
[1,2,3,4,1,2,3,4,
1,2,3,4,1,2,3,4]
print(L)

1st time: new L is [1, 2, 3, 4, 1, 2, 3, 4]


2nd time: new L is [1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4 ]

40

6.100L Lecture 10
TRICKY EXAMPLE 3: combining

e
L = [1,2,3,4]
for e in L: [1,2,3,4]

[1,2,3,4,1,2,3,4]
L = L + L L
[1,2,3,4,1,2,3,4,
1,2,3,4,1,2,3,4]
print(L)
[1,2,3,4,1,2,3,4,
1,2,3,4,1,2,3,4,
1st time: new L is [1, 2, 3, 4, 1, 2, 3, 4] 1,2,3,4,1,2,3,4,
1,2,3,4,1,2,3,4,]
2nd time: new L is [1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4 ]
3rd time: new L is [1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4 ,
1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4] 41

6.100L Lecture 10
TRICKY EXAMPLE 3: combining

e
L = [1,2,3,4]
for e in L: [1,2,3,4]

[1,2,3,4,1,2,3,4]
L = L + L L
[1,2,3,4,1,2,3,4,
1,2,3,4,1,2,3,4]
print(L)
[1,2,3,4,1,2,3,4,
4th time: new L is [1, 2, 3, 4, 1, 2, 3, 4, 1,2,3,4,1,2,3,4,
1, 2, 3, 4, 1, 2, 3, 4 , 1,2,3,4,1,2,3,4,
1,2,3,4,1,2,3,4,]
1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4 [1,2,3,4,1,2,3,4,
1,2,3,4,1,2,3,4,
1, 2, 3, 4, 1, 2, 3, 4, 1,2,3,4,1,2,3,4,
1, 2, 3, 4, 1, 2, 3, 4 , 1,2,3,4,1,2,3,4,
1,2,3,4,1,2,3,4,
1, 2, 3, 4, 1, 2, 3, 4, 1,2,3,4,1,2,3,4,
1, 2, 3, 4, 1, 2, 3, 4 ] 42
1,2,3,4,1,2,3,4,
1,2,3,4,1,2,3,4,]
6.100L Lecture 10
EMPTY OUT A LIST AND CHECKING
THAT IT’S THE SAME OBJECT
 You can mutate a list to remove all its elements
 This does not make a new empty list!
 Use [Link]()
 How to check that it’s the same object in memory?
 Use the id() function
 Try this in the console
>>> L = [4,5,6] >>> L = [4,5,6]
>>> id(L) >>> id(L)
>>> [Link](8) >>> [Link](8)
>>> id(L) >>> id(L)
>>> [Link]() >>> L = []
>>> id(L) >>> id(L)
43

6.100L Lecture 10
SUMMARY

 Lists and tuples provide a way to organize data that naturally


supports iterative functions
 Tuples are immutable (like strings)
 Tuples are useful when you have data that doesn’t need to change.
e.g. (latitude, longitude) or (page #, line #)
 Lists are mutable
 You can modify the object by changing an element at an index
 You can modify the object by adding elements to the end
 Will see many more operations on lists next time
 Lists are useful in dynamic situations.
e.g. a list of daily top 40 songs or a list of recently watched movies

44

6.100L Lecture 10
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

45
ALIASING,
CLONING
(download slides and .py files to follow along)
6.100L Lecture 11
Ana Bell

1
MAKING A COPY OF THE LIST

 Can make a copy of a list object by duplicating all elements


(top-level) into a new list object
 Lcopy = L[:]
 Equivalent to looping over L and appending each element to Lcopy
 This does not make a copy of elements that are lists (will see how to do
this at the end of this lecture)
Loriginal = [4,5,6]
Lnew = Loriginal[:]

Loriginal [4,5,6]

Lnew [4,5,6]

6.100L Lecture 11
YOU TRY IT!
 Write a function that meets the specification.
 Hint. Make a copy to save the elements. The use [Link]() to
empty out the list and repopulate it with the ones you’re
keeping.
def remove_all(L, e):
"""
L is a list
Mutates L to remove all elements in L that are equal to e
Returns None
"""

L = [1,2,2,2]
remove_all(L, 2)
print(L) # prints [1]

6.100L Lecture 11
OPERATION ON LISTS: remove

 Delete element at a specific index with del(L[index])


 Remove element at end of list with [Link](), returns the
removed element (can also call with specific index:
[Link](3))
 Remove a specific element with [Link](element)
• Looks for the element and removes it (mutating the list)
• If element occurs multiple times, removes first occurrence
• If element not in list, gives an error
L = [2,1,3,6,3,7,0] # do below in order
[Link](2)  mutates L = [1,3,6,3,7,0]
[Link](3)  mutates L = [1,6,3,7,0]
del(L[1])  mutates L = [1,3,7,0]
a = [Link]()  returns 0 and mutates L = [1,3,7]
4

6.100L Lecture 11
EXERCISE WITH REMOVE INSTEAD
OF COPY AND CLEAR
 Rewrite the code to remove e as long as we still had it in the list
 It works well!

def remove_all(L, e):


"""
L is a list
Mutates L to remove all elements in L that are equal to e
Returns None.
"""
while e in L:
[Link](e)

6.100L Lecture 11
EXERCISE WITH REMOVE INSTEAD
OF COPY AND CLEAR
 What if the code was this:

def remove_all(L, e):


"""
L is a list
Mutates L to remove all elements in L that are equal to e
Returns None.
"""
for elem in L:
if elem == e:
[Link](e)

L = [1,2,2,2]
remove_all(L, 2)
print(L) # should print [1]

6.100L Lecture 11
EXERCISE WITH REMOVE INSTEAD
OF COPY AND CLEAR

def remove_all(L, e):


"""
L is a list
Mutates L to remove all elements in L that are equal to e
Returns None.
"""
for elem in L:
if elem == e: elem
[Link](e)

L = [1,2,2,2]
remove_all(L, 2) L [1,2,2,2]
print(L) # should print [1]

6.100L Lecture 11
EXERCISE WITH REMOVE INSTEAD
OF COPY AND CLEAR

def remove_all(L, e):


"""
L is a list
Mutates L to remove all elements in L that are equal to e
Returns None.
"""
for elem in L:
if elem == e: elem
[Link](e)

L = [1,2,2,2]
remove_all(L, 2) L [1,2,2,2]
print(L) # should print [1]

6.100L Lecture 11
EXERCISE WITH REMOVE INSTEAD
OF COPY AND CLEAR

def remove_all(L, e):


"""
L is a list
Mutates L to remove all elements in L that are equal to e
Returns None.
"""
for elem in L:
if elem == e: elem
[Link](e)

L = [1,2,2,2]
remove_all(L, 2) L [1,2,2,2]
[1,2,2]
print(L) # should print [1]

6.100L Lecture 11
EXERCISE WITH REMOVE INSTEAD
OF COPY AND CLEAR

def remove_all(L, e):


"""
L is a list
Mutates L to remove all elements in L that are equal to e
Returns None.
"""
for elem in L:
if elem == e: elem
[Link](e)

L = [1,2,2,2]
remove_all(L, 2) L [1,2,2]
print(L) # should print [1]

10

6.100L Lecture 11
EXERCISE WITH REMOVE INSTEAD
OF COPY AND CLEAR
 It’s not correct! We removed items as we iterated over the list!

def remove_all(L, e):


"""
L is a list
Mutates L to remove all elements in L that are equal to e
Returns None.
"""
for elem in L:
if elem == e: elem
[Link](e)

L = [1,2,2,2]
remove_all(L, 2) L [1,2]
[1,2,2]
print(L) # should print [1]

11

6.100L Lecture 11
TRICKY EXAMPLES OVERVIEW

 TRICKY EXAMPLE 1:
 A loop iterates over indices of L and mutates L each time (adds more
elements).
 TRICKY EXAMPLE 2:
 A loop iterates over L’s elements directly and mutates L each time (adds
more elements).
 TRICKY EXAMPLE 3:
 A loop iterates over L’s elements directly but reassigns L to a new
object each time
 TRICKY EXAMPLE 4:
 A loop iterates over L’s elements directly and mutates L by removing
elements.

12

6.100L Lecture 11
TRICKY EXAMPLE 4
PYTHON TUTOR LINK to see step-by-step

 Want to mutate L1 to remove any elements that are also in L2


def remove_dups(L1, L2):
for e in L1:
if e in L2:
[Link](e)

L1 = [10, 20, 30, 40]


L2 = [10, 20, 50, 60]
remove_dups(L1, L2)
 L1 is [20,30,40] not [30,40] Why?
 You are mutating a list as you are iterating over it
 Python uses an internal counter. Tracks of index in the loop over list L1
 Mutating changes the list but Python doesn’t update the counter
 Loop never sees element 20
13

6.100L Lecture 11
MUTATION AND ITERATION WITHOUT CLONE

def remove_dups(L1, L2):


for e in L1:
if e in L2:
[Link](e)

e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1 [10,20,30,40]

L2 [10,20,50,60]

14

6.100L Lecture 11
MUTATION AND ITERATION WITHOUT CLONE

def remove_dups(L1, L2):


for e in L1:
if e in L2:
[Link](e)

e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1 [20,30,40]

L2 [10,20,50,60]

15

6.100L Lecture 11
MUTATION AND ITERATION WITHOUT CLONE

def remove_dups(L1, L2):


for e in L1:
if e in L2:
[Link](e)

e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1 [20,30,40]

L2 [10,20,50,60]

16

6.100L Lecture 11
MUTATION AND ITERATION WITHOUT CLONE

def remove_dups(L1, L2):


for e in L1:
if e in L2:
[Link](e)

e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1 [20,30,40]

L2 [10,20,50,60]

17

6.100L Lecture 11
MUTATION AND ITERATION WITH CLONE
L1_copy = L1[:]

 Make a clone with [:]


def remove_dups(L1, L2): def remove_dups(L1, L2):
for e in L1: L1_copy = L1[:]
for e in L1_copy:
if e in L2:
if e in L2:
[Link](e) [Link](e)

L1 = [10, 20, 30, 40]


L2 = [10, 20, 50, 60]
remove_dups(L1, L2)
 New version works!
 Iterate over a copy
 Mutate original list, not the copy
 Indexing is now consistent
18

6.100L Lecture 11
def remove_dups(L1, L2):
L1_copy = L1[:]
for e in L1_copy:
if e in L2:
[Link](e)
e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1_copy [10,20,30,40]

L1 [10,20,30,40]

L2 [10,20,50,60]

19

6.100L Lecture 11
def remove_dups(L1, L2):
L1_copy = L1[:]
for e in L1_copy:
if e in L2:
[Link](e)
e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1_copy [10,20,30,40]

L1 [20,30,40]

L2 [10,20,50,60]

20

6.100L Lecture 11
def remove_dups(L1, L2):
L1_copy = L1[:]
for e in L1_copy:
if e in L2:
[Link](e)
e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1_copy [10,20,30,40]

L1 [20,30,40]

L2 [10,20,50,60]

21

6.100L Lecture 11
def remove_dups(L1, L2):
L1_copy = L1[:]
for e in L1_copy:
if e in L2:
[Link](e)
e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1_copy [10,20,30,40]

L1 [30,40]

L2 [10,20,50,60]

22

6.100L Lecture 11
def remove_dups(L1, L2):
L1_copy = L1[:]
for e in L1_copy:
if e in L2:
[Link](e)
e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1_copy [10,20,30,40]

L1 [30,40]

L2 [10,20,50,60]

23

6.100L Lecture 11
def remove_dups(L1, L2):
L1_copy = L1[:]
for e in L1_copy:
if e in L2:
[Link](e)
e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2)

L1_copy [10,20,30,40]

L1 [30,40]

L2 [10,20,50,60]

24

6.100L Lecture 11
ALIASING

 City may be known by many names


 Attributes of a city Boston
 Small, tech-savvy The Hub
Beantown
 All nicknames point to the same city Athens of America
• Add new attribute to one nickname …

Boston small tech-savvy snowy

… all the aliases refer to the old attribute and all the new ones
The Hub small tech-savvy snowy

Beantown small tech-savvy snowy

25

6.100L Lecture 11
MUTATION AND ITERATION WITH ALIAS
L1_copy = L1

 Assignment (= sign) on mutable obj creates an alias, not a clone


def remove_dups(L1, L2): def remove_dups(L1, L2):
L1_copy = L1 L1_copy = L1[:]
for e in L1_copy: for e in L1_copy:
if e in L2: if e in L2:
[Link](e) [Link](e)

L1 = [10, 20, 30, 40]


L2 = [10, 20, 50, 60]
remove_dups(L1, L2)
 Using a simple assignment without making a copy
 Makes an alias for list (same list object referenced by another name)
 It’s like iterating over L itself, it doesn’t work!
26

6.100L Lecture 11
def remove_dups(L1, L2):
L1_copy = L1
for e in L1_copy:
if e in L2:
[Link](e)
e
L1 = [10, 20, 30, 40]
L2 = [10, 20, 50, 60]
remove_dups(L1, L2) L1_copy
L1 [20,30,40]
[10,20,30,40]

L2 [10,20,50,60]

27

6.100L Lecture 11
BIG IDEA
When you pass a list as a
parameter to a function,
you are making an alias.
The actual parameter (from the function call) is an alias for
the formal parameter (from the function definition).

28

6.100L Lecture 11
def remove_dups(L1, L2):
L1_copy = L1
for e in L1_copy:
if e in L2:
[Link](e)
e
La = [10, 20, 30, 40]
Lb = [10, 20, 50, 60]
remove_dups(La, Lb) L1_copy
print(La) La [20,30,40]
[10,20,30,40]
L1
Lb [10,20,50,60]
L2

29

6.100L Lecture 11
ALIASES,
SHALLOW COPIES, AND
DEEP COPIES WITH
MUTABLE ELEMENTS

30

6.100L Lecture 11
CONTROL COPYING

 Assignment just creates a new pointer to same object


old_list = [[1,2],[3,4],[5,'foo']]
new_list = old_list

new_list[2][1] = 6
print("New list:", new_list) New list: [[1,2],[3,4],[5,6]]
print("Old list:", old_list) Old list: [[1,2],[3,4],[5,6]]
 So mutating one object changes the other
[ , , ]

old_list [1,2] [3,4] [5,‘foo’]


[5,6]

new_list
31

6.100L Lecture 11
CONTROL COPYING

 Suppose we want to create a copy of a list, not just a shared


pointer
 Shallow copying does this at the top level of the list
 Equivalent to syntax [:]
 Any mutable elements are NOT copied
 Use this when your list contains immutable objects only
import copy
old_list = [[1,2],[3,4],[5,6]]
new_list = [Link](old_list)

print("New list:", new_list)


print("Old list:", old_list)
32

6.100L Lecture 11
old_list = [[1,2],[3,4],[5,6]]
new_list = [Link](old_list)

print("New list:", new_list) New list: [[1,2],[3,4],[5,6]]


print("Old list:", old_list) Old list: [[1,2],[3,4],[5,6]]

[ , , ]

old_list
[1,2] [3,4] [5,6]
new_list 6.0001 LECTURE 5
[ , , ]
33

6.100L Lecture 11
CONTROL COPYING

 Now we mutate the top level structure


import copy
old_list = [[1,2],[3,4],[5,6]]
new_list = [Link](old_list)

old_list.append([7,8])
print("New list:", new_list)
print("Old list:", old_list)

34

6.100L Lecture 11
old_list = [[1,2],[3,4],[5,6]]
new_list = [Link](old_list)

old_list.append([7,8])
print("New list:", new_list)
New list: [[1,2],[3,4],[5,6]]
print("Old list:", old_list)
Old list: [[1,2],[3,4],[5,6],[7,8]]

[[ ,, ,, ], ]

old_list
[1,2] [3,4] [5,6] [7,8]
new_list 6.0001 LECTURE 5

35
[ , , ]
6.100L Lecture 11
CONTROL COPYING

 But if we change an element in one of the sub-structures, they


are shared!
 If your elements are not mutable then this is not a problem
import copy
old_list = [[1,2],[3,4],[5,6]]
new_list = [Link](old_list)

old_list.append([7,8])
old_list[1][1] = 9
print("New list:", new_list)
print("Old list:", old_list)

36

6.100L Lecture 11
old_list = [[1,2],[3,4],[5,6]]
new_list = [Link](old_list)

old_list.append([7,8])
old_list[1][1] = 9
print("New list:", new_list) New list: [[1,2],[3,9],[5,6]]
print("Old list:", old_list) Old list: [[1,2],[3,9],[5,6],[7,8]]

[[ ,, ,, ], ]

old_list
[1,2] [3,4]
[3,9] [5,6] [7,8]
new_list 6.0001 LECTURE 5
[
37
, , ]
6.100L Lecture 11
CONTROL COPYING

 If we want all structures to be new copies, we need a deep


copy
 Use deep copy when your list might have mutable elements to
ensure every structure at every level is copied
import copy
old_list = [[1,2],[3,4],[5,6]]
new_list = [Link](old_list)

old_list.append([7,8])
old_list[1][1] = 9
print("New list:", new_list)
print("Old list:", old_list)
38

6.100L Lecture 11
old_list = [[1,2],[3,4],[5,6]]
new_list = [Link](old_list)

old_list.append([7,8])
old_list[1][1] = 9
print("New list:", new_list) New list: [[1,2],[3,4],[5,6]]
print("Old list:", old_list) Old list: [[1,2],[3,9],[5,6],[7,8]]

[ , , ]
, ]

old_list [1,2] [3,9]


[3,4] [5,6] [7,8]

new_list [1,2] [3,4] [5,6]

[39 , , ]
6.100L Lecture 11
LISTS in MEMORY

 Separate the idea of the object vs. the name we give an object
 A list is an object in memory
 Variable name points to object
 Lists are mutable and behave differently than immutable types
 Using equal sign between mutable objects creates aliases
 Both variables point to the same object in memory
 Any variable pointing to that object is affected by mutation of object,
even if mutation is by referencing another name
 If you want a copy, you explicitly tell Python to make a copy
 Key phrase to keep in mind when working with lists is side
effects, especially when dealing with aliases – two names
pointing to the same structure in memory
 Python Tutor is your best friend to help sort this out!
[Link] 40

6.100L Lecture 11
WHY LISTS and TUPLES?

 If mutation can cause so many problems, why do we even


want to have lists, why not just use tuples?
 Efficiency – if processing very large sequences, don’t want to have
to copy every time we change an element

 If lists basically do everything that tuples do, why not just


have lists?
 Immutable structures can be very valuable in context of other
object types
 Don’t want to accidentally have other code mutate some
important data, tuples safeguard against this
 They can be a bit faster

41

6.100L Lecture 11
AT HOME TRACING
EXAMPLES SHOWCASING
ALIASING AND CLONING

42

6.100L Lecture 11
ALIASES

 hot is an alias for warm – changing one changes the other!


 append() has a side effect

43

6.100L Lecture 11
ALIASES

 hot is an alias for warm – changing one changes the other!


 append() has a side effect

44

6.100L Lecture 11
CLONING A LIST

 Create a new list and copy every element using a clone


chill = cool[:]

45

6.100L Lecture 11
CLONING A LIST

 Create a new list and copy every element using a clone


chill = cool[:]

46

6.100L Lecture 11
CLONING A LIST

 Create a new list and copy every element using a clone


chill = cool[:]

47

6.100L Lecture 11
LISTS OF LISTS
OF LISTS OF….
 Can have nested lists
 Side effects still
possible after mutation

48

6.100L Lecture 11
LISTS OF LISTS
OF LISTS OF….
 Can have nested lists
 Side effects still
possible after mutation

49

6.100L Lecture 11
LISTS OF LISTS
OF LISTS OF….
 Can have nested lists
 Side effects still
possible after mutation

50

6.100L Lecture 11
LISTS OF LISTS
OF LISTS OF….
 Can have nested lists
 Side effects still
possible after mutation

51

6.100L Lecture 11
LISTS OF LISTS
OF LISTS OF….
 Can have nested lists
 Side effects still
possible after mutation

52

6.100L Lecture 11
LISTS OF LISTS
OF LISTS OF….
 Can have nested lists
 Side effects still
possible after mutation

53

6.100L Lecture 11
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

54
LIST COMPREHENSION,
FUNCTIONS AS OBJECTS,
TESTING, DEBUGGING
(download slides and .py files to follow along)
6.100L Lecture 12
Ana Bell

1
LIST COMPREHENSIONS

6.100L Lecture 12
LIST COMPREHENSIONS

 Applying a function to every element of a sequence, then


creating a new list with these values is a common concept
 Example:
def f(L):
Lnew = []
for e in L:
[Link](e**2)
return Lnew
 Python provides a concise one-liner way to do this, called a list
comprehension
 Creates a new list
 Applies a function to every element of another iterable
 Optional, only apply to elements that satisfy a test

[expression for elem in iterable if test]


3

6.100L Lecture 12
LIST COMPREHENSIONS

 Create a new list, by applying a function to every element of


another iterable that satisfies a test

def f(L):
Lnew = []
for e in L: Lnew = [e**2 for e in L]
[Link](e**2)
return Lnew

6.100L Lecture 12
LIST COMPREHENSIONS

 Create a new list, by applying a function to every element of


another iterable that satisfies a test

def f(L):
Lnew = []
for e in L: Lnew = [e**2 for e in L]
[Link](e**2)
return Lnew

def f(L):
Lnew = []
for e in L:
if e%2==0:
[Link](e**2)
return Lnew
5

6.100L Lecture 12
LIST COMPREHENSIONS

 Create a new list, by applying a function to every element of


another iterable that satisfies a test

def f(L):
Lnew = []
for e in L: Lnew = [e**2 for e in L]
[Link](e**2)
return Lnew

def f(L):
Lnew = []
for e in L:
if e%2==0:
[Link](e**2) Lnew = [e**2 for e in L if e%2==0]
return Lnew
6

6.100L Lecture 12
LIST COMPREHENSIONS

 Create a new list, by applying a function to every element of


another iterable that satisfies a test

def f(L):
Lnew = []
for e in L: Lnew = [e**2 for e in L]
[Link](e**2)
return Lnew

def f(L):
Lnew = []
for e in L:
if e%2==0:
[Link](e**2) Lnew = [e**2 for e in L if e%2==0]
return Lnew
7

6.100L Lecture 12
LIST COMPREHENSIONS

 Create a new list, by applying a function to every element of


another iterable that satisfies a test

def f(L):
Lnew = []
for e in L: Lnew = [e**2 for e in L]
[Link](e**2)
return Lnew

def f(L):
Lnew = []
for e in L:
if e%2==0:
[Link](e**2) Lnew = [e**2 for e in L if e%2==0]
return Lnew
8

6.100L Lecture 12
LIST COMPREHENSIONS

[expression for elem in iterable if test]


 This is equivalent to invoking this function (where expression is
a function that computes that expression)
def f(expr, old_list, test = lambda x: True):
new_list = []
for e in old_list:
if test(e):
new_list.append(expr(e))
return new_list

[e**2 for e in range(6)]  [0, 1, 4, 9, 16, 25]


[e**2 for e in range(8) if e%2 == 0]  [0, 4, 16, 36]
[[e,e**2] for e in range(4) if e%2 != 0]  [[1,1], [3,9]]
9

6.100L Lecture 12
YOU TRY IT!
 What is the value returned by this expression?
 Step1: what are all values in the sequence
 Step2: which subset of values does the condition filter out?
 Step3: apply the function to those values

[len(x) for x in ['xy', 'abcd', 7, '4.0'] if type(x) == str]

10

6.100L Lecture 12
FUNCTIONS: DEFAULT
PARAMETERS

11

6.100L Lecture 12
SQUARE ROOT with BISECTION

def bisection_root(x):
epsilon = 0.01
low = 0
high = x
guess = (high + low)/2.0
while abs(guess**2 - x) >= epsilon:
if guess**2 < x:
low = guess
else:
high = guess
guess = (high + low)/2.0
return guess

print(bisection_root(123))
12

6.100L Lecture 12
ANOTHER PARAMETER

 Motivation: want a more accurate answer


def bisection_root(x)can be improved
 Options?
 Change epsilon inside function (all function calls are affected)
 Use an epsilon outside function (global variables are bad)
 Add epsilon as an argument to the function

13

6.100L Lecture 12
epsilon as a PARAMETER

def bisection_root(x, epsilon):


low = 0
high = x
guess = (high + low)/2.0
while abs(guess**2 - x) >= epsilon:
if guess**2 < x:
low = guess
else:
high = guess
guess = (high + low)/2.0
return guess

print(bisection_root(123, 0.01))
14

6.100L Lecture 12
KEYWORD PARAMETERS &
DEFAULT VALUES
def bisection_root(x, epsilon)can be improved
 We added epsilon as an argument to the function
 Most of the time we want some standard value, 0.01
 Sometimes, we may want to use some other value
 Use a keyword parameter aka a default parameter

15

6.100L Lecture 12
Epsilon as a KEYWORD
PARAMETER
def bisection_root(x, epsilon=0.01):
low = 0
high = x
guess = (high + low)/2.0
while abs(guess**2 - x) >= epsilon:
if guess**2 < x:
low = guess
else:
high = guess
guess = (high + low)/2.0
return guess

print(bisection_root(123))
print(bisection_root(123, 0.5))
16

6.100L Lecture 12
RULES for KEYWORD PARAMETERS

 In the function definition:


 Default parameters must go at the end

 These are ok for calling a function:


 bisection_root_new(123)
 bisection_root_new(123, 0.001)
 bisection_root_new(123, epsilon=0.001)
 bisection_root_new(x=123, epsilon=0.1)
 bisection_root_new(epsilon=0.1, x=123)

 These are not ok for calling a function:


 bisection_root_new(epsilon=0.001, 123) #error
 bisection_root_new(0.001, 123) #no error but wrong

17

6.100L Lecture 12
FUNCTIONS RETURNING
FUNCTIONS

18

6.100L Lecture 12
OBJECTS IN A PROGRAM
function
my_func object
named
is_even is_even

def is_even(i): r int object 2


return i%2 == 0
float object
pi
r = 2 3.14285714

pi = 22/7
a False
my_func = is_even
b True
a = is_even(3)

b = my_func(4)

19

6.100L Lecture 12
FUNCTIONS CAN RETURN
FUNCTIONS
def make_prod(a):
def g(b):
return a*b
return g

val = make_prod(2)(3) doubler = make_prod(2)


print(val) val = doubler(3)
print(val)

20

6.100L Lecture 12
SCOPE DETAILS FOR WAY 1

def make_prod(a):
def g(b):
return a*b
return g

val = make_prod(2)(3)
print(val)

21

6.100L Lecture 12
SCOPE DETAILS FOR WAY 1

def make_prod(a): Global scope


def g(b):
make_prod Some
return a*b
code
return g

val = make_prod(2)(3)
print(val)

22

6.100L Lecture 12
SCOPE DETAILS FOR WAY 1 NOTE: definition
of g is done
within scope of
make_prod, so
binding of g is
def make_prod(a): Global scope make_prod within that
scope frame/scope
def g(b):
make_prod Some Since g is bound
return a*b a 2 in this frame,
code
cannot access it
return g by evaluation in
Some global frame
g
code g can only be
val = make_prod(2)(3) accessed within
call to
print(val) make_prod, and
each call will
create a new,
internal g

23

6.100L Lecture 12
SCOPE DETAILS FOR WAY 1

def make_prod(a): Global scope make_prod


scope
def g(b):
make_prod Some
return a*b a 2
code
return g
g’s g Some
code! code
val = make_prod(2)(3)
print(val)

Evaluating make_prod(2) has


Returns pointer
returned an anonymous procedure
24
to g code
6.100L Lecture 12
SCOPE DETAILS FOR WAY 1

def make_prod(a): Global scope make_prod g scope


scope
def g(b):
make_prod Some b
return a*b a 2 3
code
return g
g’s g Some
code! code
val = make_prod(2)(3)
print(val)

25

6.100L Lecture 12
SCOPE DETAILS FOR WAY 1

def make_prod(a): Global scope make_prod g scope


scope
def g(b):
make_prod Some b
return a*b a 2 3
code
return g
g’s g Some
code! code 6
val = make_prod(2)(3)
print(val)
val 6
Internal procedure only
accessible within scope from
parent procedure’s call

How does g get value for a?


Interpreter can move up hierarchy
26
of frames to see both b and a values
6.100L Lecture 12
SCOPE DETAILS FOR WAY 2

def make_prod(a):
def g(b):
return a*b
return g

doubler = make_prod(2)
val = doubler(3)
print(val)

27

6.100L Lecture 12
SCOPE DETAILS FOR WAY 2

def make_prod(a): Global scope make_prod


scope
def g(b):
make_prod Some
return a*b a 2
code
return g

doubler g’s g Some


doubler = make_prod(2) code! code
val = doubler(3)
print(val)

28

6.100L Lecture 12
SCOPE DETAILS FOR WAY 2

def make_prod(a): Global scope make_prod


scope
def g(b):
make_prod Some
return a*b a 2
code
return g

doubler g’s g Some


doubler = make_prod(2) code! code
val = doubler(3)
print(val)

29

6.100L Lecture 12
SCOPE DETAILS FOR WAY 2

def make_prod(a): Global scope make_prod doubler scope


scope
def g(b):
make_prod Some
return a*b a 2 b 3
code
return g
doubler g’s g Some
code! code 6
doubler = make_prod(2)
val = doubler(3)
print(val) val 6

Returns value
30

6.100L Lecture 12
WHY BOTHER RETURNING
FUNCTIONS?
 Code can be rewritten without returning function objects
 Good software design
 Embracing ideas of decomposition, abstraction
 Another tool to structure code
 Interrupting execution
 Example of control flow
 A way to achieve partial execution and use result somewhere else
before finishing the full evaluation

31

6.100L Lecture 12
TESTING and
DEBUGGING

32

6.100L Lecture 12
DEFENSIVE PROGRAMMING
• Write specifications for functions
• Modularize programs
• Check conditions on inputs/outputs (assertions)

TESTING/VALIDATION DEBUGGING
• Compare input/output • Study events leading up
pairs to specification to an error
• “It’s not working!” • “Why is it not working?”
• “How can I break my • “How can I fix my
program?” program?”

33

6.100L Lecture 12
SET YOURSELF UP FOR EASY
TESTING AND DEBUGGING

 From the start, design code to ease this part


 Break program up into modules that can be tested and
debugged individually
 Document constraints on modules
• What do you expect the input to be?
• What do you expect the output to be?
 Document assumptions behind code design

34

6.100L Lecture 12
WHEN ARE YOU READY TO TEST?

 Ensure code runs


• Remove syntax errors
• Remove static semantic errors
• Python interpreter can usually find these for you
 Have a set of expected results
• An input set
• For each input, the expected output

35

6.100L Lecture 12
CLASSES OF TESTS

 Unit testing
• Validate each piece of program
• Testing each function separately
 Regression testing
• Add test for bugs as you find them
• Catch reintroduced errors that were previously
fixed
 Integration testing
• Does overall program work?
• Tend to rush to do this
36

6.100L Lecture 12
TESTING APPROACHES

 Intuition about natural boundaries to the problem


def is_bigger(x, y):
""" Assumes x and y are ints
Returns True if y is less than x, else False """
• can you come up with some natural partitions?
 If no natural partitions, might do random testing
• Probability that code is correct increases with more tests
• Better options below
 Black box testing
• Explore paths through specification
 Glass box testing
• Explore paths through code
37

6.100L Lecture 12
BLACK BOX TESTING

def sqrt(x, eps):


""" Assumes x, eps floats, x >= 0, eps > 0
Returns res such that x-eps <= res*res <= x+eps """

 Designed without looking at the code


 Can be done by someone other than the implementer to
avoid some implementer biases
 Testing can be reused if implementation changes
 Paths through specification
• Build test cases in different natural space partitions
• Also consider boundary conditions (empty lists, singleton list, large
numbers, small numbers)

38

6.100L Lecture 12
BLACK BOX TESTING

def sqrt(x, eps):


""" Assumes x, eps floats, x >= 0, eps > 0
Returns res such that x-eps <= res*res <= x+eps """

CASE x eps
boundary 0 0.0001
perfect square 25 0.0001
less than 1 0.05 0.0001
irrational square root 2 0.0001
extremes 2 1.0/2.0**64.0
extremes 1.0/2.0**64.0 1.0/2.0**64.0
extremes 2.0**64.0 1.0/2.0**64.0
extremes 1.0/2.0**64.0 2.0**64.0
extremes 2.0**64.0 39 2.0**64.0
6.100L Lecture 12
GLASS BOX TESTING

 Use code directly to guide design of test cases


 Called path-complete if every potential path through
code is tested at least once
 What are some drawbacks of this type of testing?
• Can go through loops arbitrarily many times
• Missing paths
 Guidelines
• Branches
• For loops
• While loops

40

6.100L Lecture 12
GLASS BOX TESTING

def abs(x):
""" Assumes x is an int
Returns x if x>=0 and –x otherwise """
if x < -1:
return –x
else:
return x
 Aa path-complete test suite could miss a bug
 Path-complete test suite: 2 and -2
 But abs(-1) incorrectly returns -1
 Should still test boundary cases

41

6.100L Lecture 12
DEBUGGING

 Once you have discovered that your code does not run
properly, you want to:
 Isolate the bug(s)
 Eradicate the bug(s)
 Retest until code runs correctly for all cases
 Steep learning curve
 Goal is to have a bug-free program
 Tools
• Built in to IDLE and Anaconda
• Python Tutor
• print statement
• Use your brain, be systematic in your hunt
42

6.100L Lecture 12
ERROR MESSAGES – EASY

 Trying to access beyond the limits of a list


test = [1,2,3] then test[4]  IndexError
 Trying to convert an inappropriate type
int(test)  TypeError
 Referencing a non-existent variable
a  NameError
 Mixing data types without appropriate coercion
'3'/4  TypeError
 Forgetting to close parenthesis, quotation, etc.
a = len([1,2,3]
print(a)  SyntaxError
43

6.100L Lecture 12
LOGIC ERRORS - HARD

 think before writing new code


 draw pictures, take a break
 explain the code to
• someone else
• a rubber ducky

44

6.100L Lecture 12
DEBUGGING STEPS

 Study program code


• Don’t ask what is wrong
• Ask how did I get the unexpected result
• Is it part of a family?
 Scientific method
• Study available data
• Form hypothesis
• Repeatable experiments
• Pick simplest input to test with

45

6.100L Lecture 12
PRINT STATEMENTS

 Good way to test hypothesis


 When to print
• Enter function
• Parameters
• Function results
 Use bisection method
• Put print halfway in code
• Decide where bug may be depending on values

46

6.100L Lecture 12
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

47
EXCEPTIONS,
ASSERTIONS
(download slides and .py files to follow along)
6.100L Lecture 13
Ana Bell

1
EXCEPTIONS

2
UNEXPECTED
CONDITIONS

 What happens when procedure execution hits an unexpected


condition?
 Get an exception… to what was expected
• Trying to access beyond list limits
test = [1,7,4]
test[4]  IndexError
• Trying to convert an inappropriate type
int(test)  TypeError
• Referencing a non-existing variable
a  NameError
• Mixing data types without coercion
'a'/4  TypeError

6.100L Lecture 13
HANDLING EXCEPTIONS

 Typically, exception causes an error to occur and execution to stop


 Python code can provide handlers for exceptions
try: if :
<all potentially problematic code succeeds>
# do some potentially # great, all that code
# problematic code # just ran fine!
except: else:
# do something to # do something to
# handle the problem # handle the problem
 If expressions in try block all succeed
 Evaluation continues with code after except block
 Exceptions raised by any statement in body of try are handled by the
except statement
 Execution continues with the body of the except statement
 Then other expressions after that block of code
4

6.100L Lecture 13
EXAMPLE with CODE YOU MIGHT
HAVE ALREADY SEEN
 A function that sums digits in a string
CODE YOU’VE SEEN CODE WITH EXCEPTIONS
def sum_digits(s): def sum_digits(s):
""" s is a non-empty string """ s is a non-empty string
containing digits. containing digits.
Returns sum of all chars that Returns sum of all chars that
are digits """ are digits """
total = 0 total = 0
for char in s: for char in s:
if char in '0123456789': try:
val = int(char) val = int(char)
total += val total += val
return total except:
print("can't convert", char)
return total
5

6.100L Lecture 13
USER INPUT CAN LEAD TO
EXCEPTIONS

 User might input a character :(


 User might make b be 0 :(
a = int(input("Tell me one number:"))
b = int(input("Tell me another number:"))
print(a/b)

 Use try/except around the problematic code


try:
a = int(input("Tell me one number:"))
b = int(input("Tell me another number:"))
print(a/b)
except:
print("Bug in user input.")
6

6.100L Lecture 13
HANDLING SPECIFIC EXCEPTIONS

 Have separate except clauses to deal with a particular


type of exception
try:
a = int(input("Tell me one number: "))
b = int(input("Tell me another number: "))
print("a/b = ", a/b)
print("a+b = ", a+b)
except ValueError:
print("Could not convert to a number.")
except ZeroDivisionError:
print("Can't divide by zero")
print("a/b = infinity")
print("a+b =", a+b)
except:
print("Something went very wrong.")
7

6.100L Lecture 13
OTHER BLOCKS ASSOCIATED WITH
A TRY BLOCK
 else:
• Body of this is executed when execution of associated try body
completes with no exceptions
 finally:
• Body of this is always executed after try, else and except clauses,
even if they raised another error or executed a break, continue or
return
• Useful for clean-up code that should be run no matter what else
happened (e.g. close a file)
 Nice to know these exist, but we don’t really use these in this
class

6.100L Lecture 13
WHAT TO DO WITH EXCEPTIONS?

 What to do when encounter an error?


 Fail silently:
• Substitute default values or just continue
• Bad idea! user gets no warning
 Return an “error” value
• What value to choose?
• Complicates code having to check for a special value
 Stop execution, signal error condition
• In Python: raise an exception
raise ValueError("something is wrong")

6.100L Lecture 13
EXAMPLE with SOMETHING
YOU’VE ALREADY SEEN
 A function that sums digits in a string
 Execution stopping means a bad result is not propagated
def sum_digits(s):
""" s is a non-empty string containing digits.
Returns sum of all chars that are digits """
total = 0
for char in s:
try:
val = int(char)
total += val
except:
raise ValueError("string contained a character")
return total

10

6.100L Lecture 13
YOU TRY IT!
def pairwise_div(Lnum, Ldenom):
""" Lnum and Ldenom are non-empty lists of equal lengths containing numbers

Returns a new list whose elements are the pairwise


division of an element in Lnum by an element in Ldenom.

Raise a ValueError if Ldenom contains 0. """


# your code here

# For example:
L1 = [4,5,6]
L2 = [1,2,3]
# print(pairwise_div(L1, L2)) # prints [4.0,2.5,2.0]

L1 = [4,5,6]
L2 = [1,0,3]
# print(pairwise_div(L1, L2)) # raises a ValueError

11

6.100L Lecture 13
ASSERTIONS

12

6.100L Lecture 13
ASSERTIONS: DEFENSIVE
PROGRAMMING TOOL
 Want to be sure that assumptions on state of computation are as
expected
 Use an assert statement to raise an AssertionError
exception if assumptions not met
assert <statement that should be true>, "message if not true"
 An example of good defensive programming
 Assertions don’t allow a programmer to control response to unexpected
conditions
 Ensure that execution halts whenever an expected condition is not met
 Typically used to check inputs to functions, but can be used anywhere
 Can be used to check outputs of a function to avoid propagating bad
values
 Can make it easier to locate a source of a bug
13

6.100L Lecture 13
EXAMPLE with SOMETHING
YOU’VE ALREADY SEEN
 A function that sums digits in a NON-EMPTY string
 Execution stopping means a bad result is not propagated
def sum_digits(s):
""" s is a non-empty string containing digits.
Returns sum of all chars that are digits """
assert len(s) != 0, "s is empty"
total = 0
for char in s:
try:
val = int(char)
total += val
except:
raise ValueError("string contained a character")
14

6.100L Lecture 13
YOU TRY IT!
def pairwise_div(Lnum, Ldenom):
""" Lnum and Ldenom are non-empty lists of equal lengths
containing numbers
Returns a new list whose elements are the pairwise
division of an element in Lnum by an element in Ldenom.
Raise a ValueError if Ldenom contains 0. """
# add an assert line here

15

6.100L Lecture 13
ANOTHER EXAMPLE

16

6.100L Lecture 13
LONGER EXAMPLE OF
EXCEPTIONS and ASSERTIONS

 Assume we are given a class list for a subject: each


entry is a list of two parts
• A list of first and last name for a student
• A list of grades on assignments

test_grades = [[['peter', 'parker'], [80.0, 70.0, 85.0]],


[['bruce', 'wayne'], [100.0, 80.0, 74.0]]]
 Create a new class list, with name, grades, and an
average added at the end

[[['peter', 'parker'], [80.0, 70.0, 85.0], 78.33333],


[['bruce', 'wayne'], [100.0, 80.0, 74.0], 84.666667]]]

17

6.100L Lecture 13
EXAMPLE [[['peter', 'parker'], [80.0, 70.0, 85.0]],
CODE [['bruce', 'wayne'], [100.0, 80.0, 74.0]]]

def get_stats(class_list):
new_stats = []
for stu in class_list:
new_stats.append([stu[0], stu[1], avg(stu[1])])
return new_stats

def avg(grades):
return sum(grades)/len(grades)

18

6.100L Lecture 13
ERROR IF NO GRADE FOR A
STUDENT

 If one or more students don’t have any grades,


get an error
test_grades = [[['peter', 'parker'], [10.0,55.0,85.0]],
[['bruce', 'wayne'], [10.0,80.0,75.0]],
[['captain', 'america'], [80.0,10.0,96.0]],
[['deadpool'], []]]
 Get ZeroDivisionError: float division by zero
because try to
return sum(grades)/len(grades)

19

6.100L Lecture 13
OPTION 1: FLAG THE ERROR BY
PRINTING A MESSAGE

 Decide to notify that something went wrong with a msg


def avg(grades):
try:
return sum(grades)/len(grades)
except ZeroDivisionError:
print('warning: no grades data')

 Running on same test data gives


warning: no grades data
[[['peter', 'parker'], [10.0, 55.0, 85.0], 50.0],
[['bruce', 'wayne'], [10.0, 80.0, 75.0], 55.0],
[['captain', 'america'], [80.0, 10.0, 96.0], 62.0],
[['deadpool'], [], None]]
20

6.100L Lecture 13
OPTION 2: CHANGE THE POLICY

 Decide that a student with no grades gets a zero


def avg(grades):
try:
return sum(grades)/len(grades)
except ZeroDivisionError:
print('warning: no grades data')
return 0.0
 Running on same test data gives
warning: no grades data
[[['peter', 'parker'], [10.0, 55.0, 85.0], 50.0],
[['bruce', 'wayne'], [10.0, 80.0, 75.0], 55.0],
[['captain', 'america'], [80.0, 10.0, 96.0], 62]
[['deadpool'], [], 0.0]]
21

6.100L Lecture 13
OPTION 3: HALT EXECUTION IF
ASSERT IS NOT MET

def avg(grades):
assert len(grades) != 0, 'no grades data'
return sum(grades)/len(grades)

 Raises an AssertionError if it is given an empty list


for grades, prints out string message; stops execution
 Otherwise runs as normal

22

6.100L Lecture 13
ASSERTIONS vs. EXCEPTIONS

 Goal is to spot bugs as soon as introduced and make


clear where they happened
 Exceptions provide a way of handling unexpected input
 Use when you don’t need to halt program execution
 Raise exceptions if users supplies bad data input
 Use assertions:
• Enforce conditions on a “contract” between a coder and a user
• As a supplement to testing
• Check types of arguments or values
• Check that invariants on data structures are met
• Check constraints on return values
• Check for violations of constraints on procedure (e.g. no
duplicates in a list) 23

6.100L Lecture 13
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

24
DICTIONARIES
(download slides and .py files to follow along)
6.100L Lecture 14
Ana Bell

1
HOW TO STORE
STUDENT INFO
 Suppose we want to store and use grade information for
a set of students
 Could store using separate lists for each kind of
information
names = ['Ana', 'John', 'Matt', 'Katy']
grades = ['A+' , 'B' , 'A' , 'A' ]
microquizzes = ...
psets = ...
 Info stored across lists at same index, each index refers to
information for a different person
 Indirectly access information by finding location in lists
corresponding to a person, then extract
2

6.100L Lecture 14
HOW TO ACCESS
STUDENT INFO
def get_grade(student, name_list, grade_list):
i = name_list.index(student)
grade = grade_list[i]
return (student, grade)

 Messy if have a lot of different info of which to keep track,


e.g., a separate list for microquiz scores, for pset scores, etc.
 Must maintain many lists and pass them as arguments
 Must always index using integers
 Must remember to change multiple lists, when adding or
updating information
3

6.100L Lecture 14
HOW TO STORE AND
ACCESS STUDENT INFO
 Alternative might be to use a list of lists
eric = ['eric', ['ps', [8, 4, 5]], ['mq', [6, 7]]]
ana = ['ana', ['ps', [10, 10, 10]], ['mq', [9, 10]]]
john = ['john', ['ps', [7, 6, 5]], ['mq', [8, 5]]]

grades = [eric, ana, john]

 Then could access by searching lists, but code is still messy


def get_grades(who, what, data):
for stud in data:
if stud[0] == who:
for info in stud[1:]:
if info[0] == what:
return who, info

print(get_grades('eric', 'mq', grades))


print(get_grades('ana', 'ps', grades))
4

6.100L Lecture 14
A BETTER AND CLEANER WAY –
A DICTIONARY
 Nice to use one data structure, no separate lists
 Nice to index item of interest directly
 A Python dictionary has entries that map a key:value
A list A dictionary
0 Elem 1 Key 1 Val 1

1 Elem 2 Key 2 Val 2

2 Elem 3 Key 3 Val 3

3 Elem 4 Key 4 Val 4

… … … …

6.100L Lecture 14
BIG IDEA
Dict value refers to the
value associated with a
key.
This terminology is may sometimes be confused with the
regular value of some variable.

6.100L Lecture 14
A PYTHON DICTIONARY

 Store pairs of data as an entry 'Ana'


Key 1 'B'1
Val
• key (any immutable object)
'Matt'
Key 2 'A'2
Val
• str, int, float, bool, tuple, etc
• value (any data object) 'John'
Key 3 'B'3
Val
• Any above plus lists and other dicts!
'Katy'
… 'A'

my_dict = {}
d = {4:16}
grades = {'Ana':'B', 'Matt':'A', 'John':'B', 'Katy':'A'}

key1 val1 key2 val2 key3 val3 key4 val4


7

6.100L Lecture 14
DICTIONARY LOOKUP

 Similar to indexing into a list 'Ana'


Key 1 'B'1
Val
Key
 Looks up the key 'John' 'Matt'
Key 2 'A'2
Val
 Returns the value associated with
'John'
Key 3 'B'3
Val
the key
 If key isn’t found, get an error 'Katy'
… 'A'

 There is no simple expression to
get a key back given some value! Value associated
with key 'John'

grades = {'Ana':'B', 'Matt':'A', 'John':'B', 'Katy':'A'}


grades['John']  evaluates to 'B'
grades['Grace']  gives a KeyError

6.100L Lecture 14
YOU TRY IT!
 Write a function according to this spec
def find_grades(grades, students):
""" grades is a dict mapping student names (str) to grades (str)
students is a list of student names
Returns a list containing the grades for students (in same order) """

# for example

d = {'Ana':'B', 'Matt':'C', 'John':'B', 'Katy':'A'}


print(find_grades(d, ['Matt', 'Katy'])) # returns ['C', 'A']

6.100L Lecture 14
BIG IDEA
Getting a dict value is
just a matter of indexing
with a key.
No. Need. To. Loop

10

6.100L Lecture 14
'Ana' 'B'
DICTIONARY 'Matt' 'A'
OPERATIONS 'John' 'B'

'Katy' 'A'

'Grace' 'A'
'C'

grades = {'Ana':'B', 'Matt':'A', 'John':'B', 'Katy':'A'}

 Add an entry
grades['Grace'] = 'A'
 Change entry
grades['Grace'] = 'C'
 Delete entry
del(grades['Ana'])

11

6.100L Lecture 14
'Ana' 'B'
DICTIONARY 'Matt' 'A'
OPERATIONS 'John' 'B'

'Katy' 'A'

grades = {'Ana':'B', 'Matt':'A', 'John':'B', 'Katy':'A'}

 Test if key in dictionary


'John' in grades  returns True
'Daniel' in grades  returns False
'B' in grades  returns False

12

6.100L Lecture 14
YOU TRY IT!
 Write a function according to these specs
def find_in_L(Ld, k):
""" Ld is a list of dicts
k is an int
Returns True if k is a key in any dicts of Ld and False otherwise """

# for example
d1 = {1:2, 3:4, 5:6}
d2 = {2:4, 4:6}
d3 = {1:1, 3:9, 4:16, 5:25}

print(find_in_L([d1, d2, d3], 2) # returns True


print(find_in_L([d1, d2, d3], 25) # returns False

13

6.100L Lecture 14
'Ana' 'B'
DICTIONARY 'Matt' 'A'
OPERATIONS
'John' 'B'

'Katy' 'A'
 Can iterate over dictionaries but
assume there is no guaranteed order
grades = {'Ana':'B', 'Matt':'A', 'John':'B', 'Katy':'A'}

 Get an iterable that acts like a tuple of all keys


[Link]()  returns dict_keys(['Ana', 'Matt', 'John', 'Katy'])

list([Link]())  returns ['Ana', 'Matt', 'John', 'Katy']

 Get an iterable that acts like a tuple of all dict values


[Link]()  returns dict_values(['B', 'A', 'B', 'A'])

list([Link]())  returns ['B', 'A', 'B', 'A']

14

6.100L Lecture 14
DICTIONARY OPERATIONS 'Ana' 'B'

most useful way to iterate over 'Matt' 'A'


dict entries (both keys and vals!) 'John' 'B'

'Katy' 'A'
 Can iterate over dictionaries but
assume there is no guaranteed order
grades = {'Ana':'B', 'Matt':'A', 'John':'B', 'Katy':'A'}

 Get an iterable that acts like a tuple of all items


[Link]()
 returns dict_items([('Ana', 'B'), ('Matt', 'A'), ('John', 'B'), ('Katy', 'A')])

list([Link]())
 returns [('Ana', 'B'), ('Matt', 'A'), ('John', 'B'), ('Katy', 'A')]

 Typical use is to iterate over key,value tuple


for k,v in [Link]():
print(f"key {k} has value {v}")
15

6.100L Lecture 14
YOU TRY IT!
 Write a function that meets this spec
def count_matches(d):
""" d is a dict
Returns how many entries in d have the key equal to its value """

# for example
d = {1:2, 3:4, 5:6}
print(count_matches(d)) # prints 0
d = {1:2, 'a':'a', 5:5}
print(count_matches(d)) # prints 2

16

6.100L Lecture 14
DICTIONARY KEYS & VALUES

 Dictionaries are mutable objects (aliasing/cloning rules apply)


 Use = sign to make an alias
 Use [Link]() to make a copy
 Assume there is no order to keys or values!
 Dict values
• Any type (immutable and mutable)
• Dictionary values can be lists, even other dictionaries!
• Can be duplicates
 Keys
• Must be unique
• Immutable type (int, float, string, tuple,bool)
• Actually need an object that is hashable, but think of as immutable as all
immutable types are hashable
• Be careful using float type as a key
17

6.100L Lecture 14
WHY IMMUTABLE/HASHABLE
KEYS?
 A dictionary is stored in memory in a special way
 Next slides show an example

 Step 1: A function is run on the dict key


 The function maps any object to an int
E.g. map “a” to 1, “b” to 2, etc, so “ab” could map to 3
 The int corresponds to a position in a block of memory addresses
 Step 2: At that memory address, store the dict value
 To do a lookup using a key, run the same function
 If the object is immutable/hashable then you get the same int back
 If the object is changed then the function gives back a different int!

18

6.100L Lecture 14
Hash function:
1) Sum the letters Memory block (like a list)
2) Take mod 16 (to fit in a memory
block with 16 entries) 0 Ana: C
1
1 + 14 + 1 = 16
16%16 = 0 2
3
Ana C 4
Eric: A

5 + 18 + 9 + 3 = 35
35%16 = 3
5 [K,a,t,e]: B
6
Eric A 7
10 + 15 + 8 + 14 = 47 8
47%16 = 15
9
John B 10
11
12
13
11 + 1 + 20 + 5 = 37 14
37%16 = 5 15 John: B
[K, a, t, e] B 19

6.100L Lecture 14
Hash function:
1) Sum the letters Memory block (like a list)
2) Take mod 16 (to fit in a memory
block with 16 entries) 0 Ana: C
1
Kate changes her name to Cate. Same 2
person, different name. Look up her 3 Eric: A
grade? 4
5 [K,a,t,e]: B
6
7
8
9
10
11
12
13  ??? Not here!
3 + 1 + 20 + 5 = 29 14
29%16 = 13 15 John: B
[C, a, t, e] 20

6.100L Lecture 14
A PYTHON DICTIONARY for
STUDENT GRADES

 Separate students are Key 1 Val 1


separate dict entries
 Entries are separated using
a comma Key 2 Val 2

grades = {'Ana':{'mq':[5,4,4], 'ps': [10,9,9], 'fin': 'B'},


'Bob':{'mq':[6,7,8], 'ps': [8,9,10], 'fin': 'A'}}

21

6.100L Lecture 14
A PYTHON DICTIONARY for
STUDENT GRADES

 Each dict entry maps a key 'Ana'


Key 1 'mq' [5,4,4]
Val 1
to a value 'ps' [10,9,9]
 The mapping is done with 'fin' 'B'
a : character 'Bob'
Key 2 'mq' Val [6,7,8]
2
 grades maps str:dict 'ps' [8,9,10]
'fin' 'A'

grades = {'Ana':{'mq':[5,4,4], 'ps': [10,9,9], 'fin': 'B'},


'Bob':{'mq':[6,7,8], 'ps': [8,9,10], 'fin': 'A'}}

22

6.100L Lecture 14
A PYTHON DICTIONARY for
STUDENT GRADES

 The values of grades are 'Ana'


Key 1 'mq' [5,4,4]
Val 1
dicts 'ps' [10,9,9]
 Each value maps a 'fin' 'B'
 str:list 'Bob'
Key 1 'mq' [6,7,8]
Val 1
 str:str 'ps' [8,9,10]
'fin' 'A'

grades = {'Ana':{'mq':[5,4,4], 'ps': [10,9,9], 'fin': 'B'},


'Bob':{'mq':[6,7,8], 'ps': [8,9,10], 'fin': 'A'}}

23

6.100L Lecture 14
A PYTHON DICTIONARY for
STUDENT GRADES

 The values of grades are 'Ana'


Key 1 'mq' [5,4,4]
dicts 'ps' [10,9,9]
 Each value maps a 'fin' 'B'
 str:list 'Bob'
Key 1 'mq' [6,7,8]
Val 1
 str:str 'ps' [8,9,10]
'fin' 'A'

grades = {'Ana':{'mq':[5,4,4], 'ps': [10,9,9], 'fin': 'B'},


'Bob':{'mq':[6,7,8], 'ps': [8,9,10], 'fin': 'A'}}
grades['Ana']['mq'][0] returns 5
24

6.100L Lecture 14
YOU TRY IT!
my_d ={'Ana':{'mq':[10], 'ps':[10,10]},
'Bob':{'ps':[7,8], 'mq':[8]},
'Eric':{'mq':[3], 'ps':[0]} }

def get_average(data, what):


all_data = []
for stud in [Link]():
INSERT LINE HERE
return sum(all_data)/len(all_data)

Given the dict my_d, and the outline of a function to compute an average, which line should
be inserted where indicated so that get_average(my_d, 'mq') computes average
for all 'mq' entries? i.e. find average of all mq scores for all students.

A) all_data = all_data + data[stud][what]


B) all_data.append(data[stud][what])
C) all_data = all_data + data[stud[what]]
D) all_data.append(data[stud[what]])
25

6.100L Lecture 14
list vs dict

 Ordered sequence of  Matches “keys” to


elements “values”
 Look up elements by an  Look up one item by
integer index another item
 Indices have an order  No order is guaranteed
 Index is an integer  Key can be any
immutable type
 Value can be any type
 Value can be any type

26

6.100L Lecture 14
EXAMPLE: FIND MOST COMMON
WORDS IN A SONG’S LYRICS

1) Create a frequency dictionary mapping str:int


2) Find word that occurs most often and how many times
• Use a list, in case more than one word with same number
• Return a tuple (list,int) for (words_list, highest_freq)
3) Find the words that occur at least X times
• Let user choose “at least X times”, so allow as parameter
• Return a list of tuples, each tuple is a (list, int) containing the
list of words ordered by their frequency
• IDEA: From song dictionary, find most frequent word. Delete most
common word. Repeat. It works because you are mutating the song
dictionary.
27

6.100L Lecture 14
CREATING A DICTIONARY
Python Tutor LINK
song = "RAH RAH AH AH AH ROM MAH RO MAH MAH"
def generate_word_dict(song):
song_words = [Link]()
words_list = song_words.split()
word_dict = {}
for w in words_list:
if w in word_dict:
word_dict[w] += 1
else:
word_dict[w] = 1
return word_dict

28

6.100L Lecture 14
USING THE DICTIONARY
Python Tutor LINK
word_dict = {'rah':2, 'ah':3, 'rom':1, 'mah':3, 'ro':1}

def find_frequent_word(word_dict):
words = []
highest = max(word_dict.values())
for k,v in word_dict.items():
if v == highest:
[Link](k)
return (words, highest)

29

6.100L Lecture 14
FIND WORDS WITH FREQUENCY
GREATER THAN x=1
 Repeat the next few steps as long as the highest frequency is
greater than x
 Find highest frequency

word_dict = {'rah':2, 'ah':3, 'rom':1, 'mah':3, 'ro':1}

30

6.100L Lecture 14
FIND WORDS WITH FREQUENCY
GREATER THAN x=1
 Use function find_frequent_word to get words with the
biggest frequency

word_dict = {'rah':2, 'ah':3, 'rom':1, 'mah':3, 'ro':1}

31

6.100L Lecture 14
FIND WORDS WITH FREQUENCY
GREATER THAN x=1
 Remove the entries corresponding to these words from
dictionary by mutation

word_dict = {'rah':2, 'rom':1, 'ro':1}

 Save them in the result

freq_list = [(['ah','mah'],3)]

32

6.100L Lecture 14
FIND WORDS WITH FREQUENCY
GREATER THAN x=1
 Find highest frequency in the mutated dict

word_dict = {'rah':2, 'rom':1, 'ro':1}

 The result so far…

freq_list = [(['ah','mah'],3)]

33

6.100L Lecture 14
FIND WORDS WITH FREQUENCY
GREATER THAN x=1
 Use function find_frequent_word to get words with that
frequency

word_dict = {'rah':2, 'rom':1, 'ro':1}

 The result so far…

freq_list = [(['ah','mah'],3)]

34

6.100L Lecture 14
FIND WORDS WITH FREQUENCY
GREATER THAN x=1
 Remove the entries corresponding to these words from
dictionary by mutation

word_dict = { 'rom':1, 'ro':1}

 Add them to the result so far

freq_list = [(['ah','mah'],3), (['rah'],2)]

35

6.100L Lecture 14
FIND WORDS WITH FREQUENCY
GREATER THAN x=1
 The highest frequency is now smaller than x=2, so stop

word_dict = { 'rom':1, 'ro':1}

 The final result

freq_list = [(['ah','mah'],3), (['rah'],2)]

36

6.100L Lecture 14
LEVERAGING DICT PROPERTIES
Python Tutor LINK

word_dict = {'rah':2, 'ah':3, 'rom':1, 'mah':3, 'ro':1}

def occurs_often(word_dict, x):


freq_list = []
word_freq_tuple = find_frequent_word(word_dict)

while word_freq_tuple[1] > x:

word_freq_tuple = find_frequent_word(word_dict)
freq_list.append(word_freq_tuple)
for word in word_freq_tuple[0]:
del(word_dict[word])
return freq_list
37

6.100L Lecture 14
SOME OBSERVATIONS

 Conversion of string into list of words enables use of list


methods
 Used words_list = song_words.split()
 Iteration over list naturally follows from structure of lists
 Used for w in words_list:
 Dictionary stored the same data in a more appropriate way
 Ability to access all values and all keys of dictionary allows
natural looping methods
 Used for k,v in word_dict.items():
 Mutability of dictionary enables iterative processing
 Used del(word_dict[word])
 Reused functions we already wrote!
38

6.100L Lecture 14
SUMMARY

 Dictionaries have entries that map a key to a value


 Keys are immutable/hashable and unique objects
 Values can be any object
 Dictionaries can make code efficient
 Implementation-wise
 Runtime-wise

39

6.100L Lecture 14
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

40
PYTHON CLASSES
(download slides and .py files to follow along)
6.100L Lecture 17
Ana Bell

1
OBJECTS

 Python supports many different kinds of data


1234 3.14159 "Hello" [1, 5, 7, 11, 13]
{"CA": "California", "MA": "Massachusetts"}
 Each is an object, and every object has:
• An internal data representation (primitive or composite)
• A set of procedures for interaction with the object
 An object is an instance of a type
• 1234 is an instance of an int
• "hello" is an instance of a str

6.100L Lecture 17
OBJECT ORIENTED
PROGRAMMING (OOP)

 EVERYTHING IN PYTHON IS AN OBJECT (and has a type)


 Can create new objects of some type
 Can manipulate objects
 Can destroy objects
 Explicitly using del or just “forget” about them
 Python system will reclaim destroyed or inaccessible objects –
called “garbage collection”

6.100L Lecture 17
WHAT ARE OBJECTS?

 Objects are a data abstraction


that captures…
(1) An internal representation
 Through data attributes
(2) An interface for
interacting with object
 Through methods
(aka procedures/functions)
 Defines behaviors but
hides implementation

6.100L Lecture 17
EXAMPLE:
[1,2,3,4] has type list

 (1) How are lists represented internally?


Does not matter for so much for us as users (private representation)
L = 1 ->2 -> 3
or L = 1 -> 2 -> 3 -> 4 ->
 (2) How to interface with, and manipulate, lists?
• L[i], L[i:j], +
• len(), min(), max(), del(L[i])
• [Link](),[Link](),[Link](),[Link](),
[Link](),[Link](),[Link](),[Link](),
[Link]()
 Internal representation should be private
 Correct behavior may be compromised if you manipulate internal
representation directly
5

6.100L Lecture 17
REAL-LIFE EXAMPLES

 Elevator: a box that can change floors


 Represent using length, width, height, max_capacity, current_floor
 Move its location to a different floor, add people, remove people
 Employee: a person who works for a company
 Represent using name, birth_date, salary
 Can change name or salary
 Queue at a store: first customer to arrive is the first one helped
 Represent customers as a list of str names
 Append names to the end and remove names from the beginning
 Stack of pancakes: first pancake made is the last one eaten
 Represent stack as a list of str
 Append pancake to the end and remove from the end
6

6.100L Lecture 17
ADVANTAGES OF OOP

 Bundle data into packages together with procedures that


work on them through well-defined interfaces
 Divide-and-conquer development
• Implement and test behavior of each class separately
• Increased modularity reduces complexity
 Classes make it easy to reuse code
• Many Python modules define new classes
• Each class has a separate environment (no collision on function
names)
• Inheritance allows subclasses to redefine or extend a selected
subset of a superclass’ behavior

6.100L Lecture 17
BIG IDEA
You write the class so you
make the design decisions.
You decide what data represents the class.
You decide what operations a user can do with the class.

6.100L Lecture 17
Implementing the class Using the class

CREATING AND USING YOUR


OWN TYPES WITH CLASSES
 Make a distinction between creating a class and
using an instance of the class
 Creating the class involves
• Defining the class name
• Defining class attributes
• for example, someone wrote code to implement a list class
 Using the class involves
• Creating new instances of the class
• Doing operations on the instances
• for example, L=[1,2] and len(L)

6.100L Lecture 17
A PARALLEL with FUNCTIONS

 Defining a class is like defining a function


 With functions, we tell Python this procedure exists
 With classes, we tell Python about a blueprint for this new data type
 Its data attributes
 Its procedural attributes

 Creating instances of objects is like calling the function


 With functions we make calls with different actual parameters
 With classes, we create new object tinstances in memory of this type
 L1 = [1,2,3]
L2 = [5,6,7]

10

6.100L Lecture 17
COORDINATE TYPE
DESIGN DECISIONS
Can create instances of a  Decide what data elements
Coordinate object constitute an object
• In a 2D plane
• A coordinate is defined by
(3 , 4) an x and y value

 Decide what to do with


coordinates
• Tell us how far away the
coordinate is on the x or y axes
• Measure the distance between
(1 , 1) two coordinates, Pythagoras

11

6.100L Lecture 17
Implementing the class Using the class

DEFINE YOUR OWN TYPES

 Use the class keyword to define a new type

class Coordinate(object):
#define attributes here

 Similar to def, indent code to indicate which statements are


part of the class definition
 The word object means that Coordinate is a Python
object and inherits all its attributes (will see in future lects)
12

6.100L Lecture 17
WHAT ARE ATTRIBUTES?

 Data and procedures that “belong” to the class


 Data attributes
• Think of data as other objects/variables that make up the class
• for example, a coordinate is made up of two numbers
 Methods (procedural attributes)
• Think of methods as functions that only work with this class
• How to interact with the object
• for example you can define a distance between two coordinate
objects but there is no meaning to a distance between two list
objects

13

6.100L Lecture 17
Implementing the class Using the class

DEFINING HOW TO CREATE AN INSTANCE OF A


CLASS
 First have to define how to create an instance of class
 Use a special method called __init__ to initialize some
data attributes or perform initialization operations
class Coordinate(object):
def __init__(self, xval, yval):
self.x = xval
self.y = yval

 self allows you to create variables that belong to this object


 Without self, you are just creating regular variables!
14

6.100L Lecture 17
Image © source unknown. All rights
reserved. This content is excluded from
our Creative Commons license. For more

WHAT is self?
information, see [Link]
help/faq-fair-use/

ROOM EXAMPLE
 Think of the class definition as a  Now when you create ONE instance
blueprint with placeholders for (name it living_room), self becomes
actual items this actual object
 self has a chair  living_room has a blue chair
 self has a coffee table  living_room has a black table
 self has a sofa  living_room has a white sofa
 Can make many instances using
the same blueprint

15

6.100L Lecture 17
BIG IDEA
When defining a class,
we don’t have an actual
tangible object here.
It’s only a definition.

16

6.100L Lecture 17
Implementing the class Using the class

Recall the __init__ method in the class def:


def __init__(self, xval, yval): ACTUALLY CREATING
self.x = xval
self.y = yval AN INSTANCE OF A CLASS

 Don’t provide argument for self, Python


does this automatically
c = Coordinate(3,4)
origin = Coordinate(0,0)

 Data attributes of an instance are called instance variables


 Data attributes were defined with [Link] and they are
accessible with dot notation for the lifetime of the object
 All instances have these data attributes, but with different values!
print(c.x)
print(origin.x)
17

6.100L Lecture 17
VISUALIZING INSTANCES

 Suppose we create an instance of


a coordinate
c = Coordinate(3,4) Type: Coordinate
c x: 3
 Think of this as creating a y: 4
structure in memory
 Then evaluating
c.x
looks up the structure to which
c points, then finds the binding
for x in that structure

18

6.100L Lecture 17
VISUALIZING INSTANCES:
in memory
 Make another instance using
a variable
a = 0 Type: Coordinate
c x: 3
orig = Coordinate(a,a) y: 4

orig.x a 0

 All these are just objects in Type: Coordinate


memory! orig x: 0
y: 0
 We just access attributes of
these objects

19

6.100L Lecture 17
VISUALIZING INSTANCES:
draw it

class Coordinate(object):
def __init__(self, xval, yval):
self.x = xval
self.y = yval
(3 , 4)
c
c = Coordinate(3,4)
origin = Coordinate(0,0)
print(c.x)
print(origin.x)

(0 , 0)
origin

20

6.100L Lecture 17
WHAT IS A METHOD?

 Procedural attribute
 Think of it like a function that works only with this class
 Python always passes the object as the first argument
 Convention is to use self as the name of the first argument of all
methods

21

6.100L Lecture 17
Implementing the class Using the class

DEFINE A METHOD
FOR THE Coordinate CLASS

class Coordinate(object):
def __init__(self, xval, yval):
self.x = xval
self.y = yval
def distance(self, other):
x_diff_sq = (self.x-other.x)**2
y_diff_sq = (self.y-other.y)**2
return (x_diff_sq + y_diff_sq)**0.5
 Other than self and dot notation, methods behave just
like functions (take params, do operations, return)
22

6.100L Lecture 17
HOW TO CALL A METHOD?

 The “.” operator is used to access any attribute


 A data attribute of an object (we saw c.x)
 A method of an object
 Dot notation
<object_variable>.<method>(<parameters>)

 Familiar?
my_list.append(4)
my_list.sort()
23

6.100L Lecture 17
Implementing the class Using the class

Recall the definition of distance method:


def distance(self, other):
HOW TO USE A METHOD
x_diff_sq = (self.x-other.x)**2
y_diff_sq = (self.y-other.y)**2
return (x_diff_sq + y_diff_sq)**0.5

Using the class:


c = Coordinate(3,4)
orig = Coordinate(0,0)
print([Link](orig))

 Notice that self becomes the object you call the


method on (the thing before the dot!)
24

6.100L Lecture 17
VISUALIZING INVOCATION

 Coordinate class is an object in


memory self.x
self.y
 From the class definition Coordinate __init__: some code
distance: some code
 Create two Coordinate objects
Type: Coordinate
c = Coordinate(3,4) c x: 3
y: 4
orig = Coordinate(0,0)
Type: Coordinate
orig x: 0
y: 0

25

6.100L Lecture 17
VISUALIZING INVOCATION

 Evaluate the method call


[Link](orig) self.x
self.y
Coordinate __init__: some code
 1) The object is before the dot distance: some code

 2) Looks up the type of c Type: Coordinate


c x: 3
 3) The method to call is after the y: 4

dot. Type: Coordinate


 4) Finds the binding for orig x: 0
y: 0
distance in that object class
 5) Invokes that method with
c as self and
orig as other
26

6.100L Lecture 17
Implementing the class Using the class

HOW TO USE A METHOD

 Conventional way  Equivalent to


c = Coordinate(3,4) c = Coordinate(3,4)
zero = Coordinate(0,0) zero = Coordinate(0,0)
[Link](zero) [Link](c, zero)

27

6.100L Lecture 17
BIG IDEA
The . operator accesses
either data attributes or
methods.
Data attributes are defined with [Link]
Methods are functions defined inside the class with self as the first parameter.

28

6.100L Lecture 17
THE POWER OF OOP

 Bundle together objects that share


• Common attributes and
• Procedures that operate on those attributes
 Use abstraction to make a distinction between how to
implement an object vs how to use the object
 Build layers of object abstractions that inherit behaviors
from other classes of objects
 Create our own classes of objects on top of Python’s
basic classes

29

6.100L Lecture 17
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

30
MORE PYTHON CLASS
METHODS
(download slides and .py files to follow along)
6.100L Lecture 18
Ana Bell

1
IMPLEMENTING USING
THE CLASS vs THE CLASS

 Write code from two different perspectives


Implementing a new Using the new object type in
object type with a class code
 Define the class • Create instances of the
 Define data attributes object type
(WHAT IS the object)
 Define methods
• Do operations with them
(HOW TO use the object)

Class abstractly captures Instances have specific


common properties and values for attributes
behaviors
2

6.100L Lecture 18
RECALL THE COORDINATE CLASS

 Class definition tells Python the blueprint for a type Coordinate

class Coordinate(object):
""" A coordinate made up of an x and y value """
def __init__(self, x, y):
""" Sets the x and y values """
self.x = x
self.y = y
def distance(self, other):
""" Returns euclidean dist between two Coord obj """
x_diff_sq = (self.x-other.x)**2
y_diff_sq = (self.y-other.y)**2
return (x_diff_sq + y_diff_sq)**0.5

6.100L Lecture 18
ADDING METHODS TO THE
COORDINATE CLASS
 Methods are functions that only work with objects of this type
class Coordinate(object):
""" A coordinate made up of an x and y value """
def __init__(self, x, y):
""" Sets the x and y values """
self.x = x
self.y = y
def distance(self, other):
""" Returns euclidean dist between two Coord obj """
x_diff_sq = (self.x-other.x)**2
y_diff_sq = (self.y-other.y)**2
return (x_diff_sq + y_diff_sq)**0.5
def to_origin(self):
""" always sets self.x and self.y to 0,0 """
self.x = 0
self.y = 0
4

6.100L Lecture 18
MAKING COORDINATE INSTANCES

 Creating instances makes actual Coordinate objects in memory


 The objects can be manipulated
 Use dot notation to call methods and access data attributes

c = Coordinate(3,4)
origin = Coordinate(0,0)

print(f"c's x is {c.x} and origin's x is {origin.x}")


print([Link](origin))

c.to_origin()
print(c.x, c.y)
5

6.100L Lecture 18
CLASS DEFINITION INSTANCE
OF AN OBJECT TYPE vs OF A CLASS

 Class name is the type  Instance is one specific object


class Coordinate(object) coord = Coordinate(1,2)

 Class is defined generically  Data attribute values vary


 Use self to refer to some between instances
instance while defining the c1 = Coordinate(1,2)
class c2 = Coordinate(3,4)
(self.x – self.y)**2
• c1 and c2 have different data
 self is a parameter to attribute values c1.x and c2.x
methods in class definition because they are different objects

 Class defines data and  Instance has the structure of


methods common across all the class
instances
6

6.100L Lecture 18
USING CLASSES TO BUILD OTHER
CLASSES
 Example: use Coordinates to build Circles
 Our implementation will use 2 data attributes
 Coordinate object representing the center
 int object representing the radius

radius

Center
coordinate

6.100L Lecture 18
CIRCLE CLASS:
DEFINITION and INSTANCES

class Circle(object):
def __init__(self, center, radius):
[Link] = center
[Link] = radius

center = Coordinate(2, 2)
my_circle = Circle(center, 2)

6.100L Lecture 18
YOU TRY IT!
 Add code to the init method to check that the type of center is
a Coordinate obj and the type of radius is an int. If either are
not these types, raise a ValueError.

def __init__(self, center, radius):


[Link] = center
[Link] = radius

6.100L Lecture 18
CIRCLE CLASS:
DEFINITION and INSTANCES

class Circle(object):
def __init__(self, center, radius):
[Link] = center
[Link] = radius
def is_inside(self, point):
""" Returns True if point is in self, False otherwise """
return [Link]([Link]) < [Link]

center = Coordinate(2, 2)
my_circle = Circle(center, 2)
p = Coordinate(1,1)
print(my_circle.is_inside(p))
10

6.100L Lecture 18
YOU TRY IT!
 Are these two methods in the Circle class functionally equivalent?

class Circle(object):
def __init__(self, center, radius):
[Link] = center
[Link] = radius

def is_inside1(self, point):


return [Link]([Link]) < [Link]

def is_inside2(self, point):


return [Link](point) < [Link]

11

6.100L Lecture 18
EXAMPLE:
FRACTIONS

 Create a new type to represent a number as a fraction


 Internal representation is two integers
• Numerator
• Denominator
 Interface a.k.a. methods a.k.a how to interact with
Fraction objects
• Add, subtract
• Invert the fraction
 Let’s write it together!

12

6.100L Lecture 18
NEED TO CREATE INSTANCES

class SimpleFraction(object):
def __init__(self, n, d):
[Link] = n
[Link] = d

13

6.100L Lecture 18
MULTIPLY FRACTIONS
class SimpleFraction(object):
def __init__(self, n, d):
[Link] = n
[Link] = d
def times(self, oth):
top = [Link]*[Link]
bottom = [Link]*[Link]
return top/bottom

14

6.100L Lecture 18
ADD FRACTIONS
class SimpleFraction(object):
def __init__(self, n, d):
[Link] = n
[Link] = d
………
def plus(self, oth):
top = [Link]*[Link] + [Link]*[Link]
bottom = [Link]*[Link]
return top/bottom

15

6.100L Lecture 18
LET’S TRY IT OUT

f1 = SimpleFraction(3, 4)
f2 = SimpleFraction(1, 4)
print([Link]) 3
print([Link]) 4
print([Link](f2)) 1.0
print([Link](f2)) 0.1875

16

6.100L Lecture 18
YOU TRY IT!
 Add two methods to invert fraction object according to the specs below:
class SimpleFraction(object):
""" A number represented as a fraction """
def __init__(self, num, denom):
[Link] = num
[Link] = denom
def get_inverse(self):
""" Returns a float representing 1/self """
pass
def invert(self):
""" Sets self's num to denom and vice versa.
Returns None. """
pass

# Example:
f1 = SimpleFraction(3,4)
print(f1.get_inverse()) # prints 1.33333333 (note this one returns value)
[Link]() # acts on data attributes internally, no return
print([Link], [Link]) # prints 4 3

17

6.100L Lecture 18
LET’S TRY IT OUT WITH MORE
THINGS
f1 = SimpleFraction(3, 4)
f2 = SimpleFraction(1, 4)
print([Link]) 3
print([Link]) 4
print([Link](f2)) 1.0
print([Link](f2)) 0.1875

print(f1) <__main__.SimpleFraction object at 0x00000234A8C41DF0>


print(f1 * f2) Error!

18

6.100L Lecture 18
SPECIAL OPERATORS IMPLEMENTED
WITH DUNDER METHODS

 +, -, ==, <, >, len(), print, and many others are


shorthand notations
 Behind the scenes, these get replaced by a method!
[Link]
 Can override these to work with your class

19

6.100L Lecture 18
SPECIAL OPERATORS IMPLEMENTED
WITH DUNDER METHODS

 Define them with double underscores before/after


__add__(self, other)  self + other
__sub__(self, other)  self - other
__mul__(self, other)  self * other
__truediv__(self, other)  self / other
__eq__(self, other)  self == other
__lt__(self, other)  self < other
__len__(self)  len(self)
__str__(self)  print(self)
__float__(self)  float(self) i.e cast
__pow__  self**other

... and others


20

6.100L Lecture 18
PRINTING OUR OWN
DATA TYPES

21

6.100L Lecture 18
PRINT REPRESENTATION OF AN
OBJECT

>>> c = Coordinate(3,4)
>>> print(c)
<__main__.Coordinate object at 0x7fa918510488>

 Uninformative print representation by default


 Define a __str__ method for a class
 Python calls the __str__ method when used with
print on your class object
 You choose what it does! Say that when we print a
Coordinate object, want to show

>>> print(c)
<3,4>
22

6.100L Lecture 18
DEFINING YOUR OWN PRINT
METHOD

class Coordinate(object):
def __init__(self, xval, yval):
self.x = xval
self.y = yval
def distance(self, other):
x_diff_sq = (self.x-other.x)**2
y_diff_sq = (self.y-other.y)**2
return (x_diff_sq + y_diff_sq)**0.5
def __str__(self):
return "<"+str(self.x)+","+str(self.y)+">"

23

6.100L Lecture 18
WRAPPING YOUR HEAD AROUND
TYPES AND CLASSES

 Can ask for the type of an object instance


>>> c = Coordinate(3,4)
>>> print(c)
<3,4>
>>> print(type(c))
<class __main__.Coordinate>
 This makes sense since
>>> print(Coordinate)
<class __main__.Coordinate>
>>> print(type(Coordinate))
<type 'type'>
 Use isinstance() to check if an object is a Coordinate
>>> print(isinstance(c, Coordinate))
True

24

6.100L Lecture 18
EXAMPLE: FRACTIONS WITH
DUNDER METHODS

 Create a new type to represent a number as a fraction


 Internal representation is two integers
• Numerator
• Denominator
 Interface a.k.a. methods a.k.a how to interact with
Fraction objects
• Add, sub, mult, div to work with +, -, *, /
• Print representation, convert to a float
• Invert the fraction
 Let’s write it together!

25

6.100L Lecture 18
CREATE & PRINT INSTANCES

class Fraction(object):
def __init__(self, n, d):
[Link] = n
[Link] = d
def __str__(self):
return str([Link]) + "/" + str([Link])

26

6.100L Lecture 18
LET’S TRY IT OUT

f1 = Fraction(3, 4)
f2 = Fraction(1, 4)
f3 = Fraction(5, 1)
print(f1) 3/4
print(f2) 1/4
print(f3) 5/1
Ok, but looks weird!

27

6.100L Lecture 18
YOU TRY IT!
 Modify the str method to represent the Fraction as just the
numerator, when the denominator is 1. Otherwise its
representation is the numerator then a / then the denominator.
class Fraction(object):
def __init__(self, num, denom):
[Link] = num
[Link] = denom
def __str__(self):
return str([Link]) + "/" + str([Link])

# Example:
a = Fraction(1,4)
b = Fraction(3,1)
print(a) # prints 1/4
print(b) # prints 3

28

6.100L Lecture 18
IMPLEMENTING
+-*/
float()

29

6.100L Lecture 18
COMPARING METHOD vs.
DUNDER METHOD

class SimpleFraction(object): class Fraction(object):


def __init__(self, n, d): def __init__(self, n, d):
[Link] = n [Link] = n
[Link] = d [Link] = d
……… ………
def times(self, oth): def __mul__(self, other):
top = [Link]*[Link] top = [Link]*[Link]
bottom = [Link]*[Link] bottom = [Link]*[Link]
return top/bottom return Fraction(top, bottom)

30

6.100L Lecture 18
LETS TRY IT OUT

a = Fraction(1,4)
b = Fraction(3,4)
print(a) 1/4
c = a * b
print(c) 3/16

31

6.100L Lecture 18
CLASSES CAN HIDE DETAILS

 These are all equivalent


print(a * b)
print(a.__mul__(b))
print(Fraction.__mul__(a, b))

 Every operation in Python


comes back to a method call
 The first instance makes clear
the operation, without worrying
about the internal details!
Abstraction at work

32

6.100L Lecture 18
BIG IDEA
Special operations we’ve
been using are just
methods behind the
scenes.
Things like:
print, len
+, *, -, /, <, >, <=, >=, ==, !=
[]
and many others!

33

6.100L Lecture 18
CAN KEEP BOTH OPTIONS BY ADDING
A METHOD TO CAST TO A float

class Fraction(object):
def __init__(self, n, d):
[Link] = n
[Link] = d
………
def __float__(self):
return [Link]/[Link]

c = a * b
print(c) 3/16
print(float(c)) 0.1875

34

6.100L Lecture 18
LETS TRY IT OUT SOME MORE

a = Fraction(1,4)
b = Fraction(2,3)
c = a * b
print(c) 2/12

 Not quite what we might expect? It’s not reduced.


 Can we fix this?

35

6.100L Lecture 18
ADD A METHOD
class Fraction(object):
………
def reduce(self):
def gcd(n, d):
while d != 0:
(d, n) = (n%d, d)
return n
if [Link] == 0:
return None
elif [Link] == 1:
return [Link]
else:
greatest_common_divisor = gcd([Link], [Link])
top = int([Link]/greatest_common_divisor)
bottom = int([Link]/greatest_common_divisor)
return Fraction(top, bottom)

c = a*b
print(c) 2/12
print([Link]()) 1/6 36
6.100L Lecture 18
WE HAVE SOME IMPROVEMENTS TO MAKE
class Fraction(object):
…………
def reduce(self):
def gcd(n, d):
while d != 0:
(d, n) = (n%d, d)
return n
if [Link] == 0:
return None
elif [Link] == 1:
s
return [Link]
else:
greatest_common_divisor = gcd([Link], [Link])
top = int([Link]/greatest_common_divisor)
bottom = int([Link]/greatest_common_divisor)
return Fraction(top, bottom)

37

6.100L Lecture 18
CHECK THE TYPES, THEY’RE DIFFERENT

a = Fraction(4,1)
b = Fraction(3,9)
ar = [Link]() 4

br = [Link]() 1/3

print(ar, type(ar)) 4 <class 'int'>


print(br, type(br)) 1/3 <class '__main__.Fraction'>
c = ar * br

38

6.100L Lecture 18
YOU TRY IT!
 Modify the code to return a Fraction object when denominator
is 1
class Fraction(object):
def reduce(self):
def gcd(n, d):
while d != 0:
(d, n) = (n%d, d)
return n
if [Link] == 0:
return None
elif [Link] == 1:
return [Link]
else:
greatest_common_divisor = gcd([Link], [Link])
top = int([Link]/greatest_common_divisor)
bottom = int([Link]/greatest_common_divisor)
return Fraction(top, bottom)

# Example:
f1 = Fraction(5,1)
print([Link]()) # prints 5/1
39
not 5
6.100L Lecture 18
WHY OOP and BUNDLING THE
DATA IN THIS WAY?
 Code is organized and modular
 Code is easy to maintain
 It’s easy to build upon objects to make more complex objects

 Decomposition and abstraction at work with Python classes


 Bundling data and behaviors means you can use objects consistently
 Dunder methods are abstracted by common operations, but they’re
just methods behind the scenes!

40

6.100L Lecture 18
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

41
INHERITANCE
(download slides and .py files to follow along)
6.100L Lecture 19
Ana Bell

1
WHY USE OOP AND
CLASSES OF OBJECTS?
 Mimic real life
 Group different objects part of the same type

Images © sources unknown. All rights reserved.


This content is excluded from our Creative
2
Commons license. For more information, see
6.100L Lecture 19 [Link]
WHY USE OOP AND
CLASSES OF OBJECTS?
 Mimic real life
 Group different objects part of the same type

Images © sources unknown. All rights reserved.


3 This content is excluded from our Creative
Commons license. For more information, see
6.100L Lecture 19 [Link]
GROUPS OF OBJECTS HAVE ATTRIBUTES
(RECAP)

 Data attributes
 How can you represent your object with data?
 What it is
for a coordinate: x and y values
for an animal: age
 Procedural attributes (behavior/operations/methods)
 How can someone interact with the object?
 What it does
for a coordinate: find distance between two
for an animal: print how long it’s been alive

6.100L Lecture 19
HOW TO DEFINE A CLASS (RECAP)

class Animal(object):
def __init__(self, age):
[Link] = age
[Link] = None

myanimal = Animal(3)

6.100L Lecture 19
GETTER AND SETTER METHODS

class Animal(object):
def __init__(self, age):
[Link] = age
[Link] = None
def __str__(self):
return "animal:"+str([Link])+":"+str([Link])

 Getters and setters should be used outside of class to


access data attributes
6

6.100L Lecture 19
GETTER AND SETTER METHODS

class Animal(object):
def __init__(self, age):
[Link] = age
[Link] = None
def __str__(self):
return "animal:"+str([Link])+":"+str([Link])
def get_age(self):
return [Link]
def get_name(self):
return [Link]
def set_age(self, newage):
[Link] = newage
def set_name(self, newname=""):
[Link] = newname

 Getters and setters should be used outside of class to


access data attributes
7

6.100L Lecture 19
AN INSTANCE and
DOT NOTATION (RECAP)
 Instantiation creates an instance of an object
a = Animal(3)
 Dot notation used to access attributes (data and methods)
though it is better to use getters and setters to access data
attributes
[Link]
a.get_age()

6.100L Lecture 19
INFORMATION HIDING

 Author of class definition may change data attribute variable


names
class Animal(object):
def __init__(self, age):
[Link] = age
def get_age(self):
return [Link]
 If you are accessing data attributes outside the class and class
definition changes, may get errors
 Outside of class, use getters and setters instead
 Use a.get_age() NOT [Link]
 good style
 easy to maintain code
 prevents bugs
9

6.100L Lecture 19
CHANGING INTERNAL REPRESENTATION

class Animal(object):
def __init__(self, age):
[Link] = age
[Link] = None
def __str__(self):
return "animal:"+str([Link])+":"+str([Link])
def get_age(self):
return [Link]
def set_age(self, newage):
[Link] = newage

a.get_age() # works
[Link] # error

 Getters and setters should be used outside of class to


access data attributes 10

6.100L Lecture 19
PYTHON NOT GREAT AT
INFORMATION HIDING

 Allows you to access data from outside class definition


print([Link])

 Allows you to write to data from outside class definition


[Link] = 'infinite'

 Allows you to create data attributes for an instance from


outside class definition
[Link] = "tiny"

 It’s not good style to do any of these!

11

6.100L Lecture 19
USE OUR NEW CLASS

def animal_dict(L):
""" L is a list
Returns a dict, d, mappping an int to an Animal object.
A key in d is all non-negative ints, n, in L. A value
corresponding to a key is an Animal object with n as its age. """
d = {}
for n in L:
if type(n) == int and n >= 0:
d[n] = Animal(n)
return d

L = [2,5,'a',-5,0]

12

6.100L Lecture 19
USE OUR NEW CLASS

 Python doesn’t know how to call print recursively


def animal_dict(L):
""" L is a list
Returns a dict, d, mappping an int to an Animal object.
A key in d is all non-negative ints n L. A value corresponding
to a key is an Animal object with n as its age. """
d = {}
for n in L:
if type(n) == int and n >= 0:
d[n] = Animal(n)
return d

L = [2,5,'a',-5,0]

animals = animal_dict(L)
print(animals)

13

6.100L Lecture 19
USE OUR NEW CLASS

def animal_dict(L):
""" L is a list
Returns a dict, d, mappping an int to an Animal object.
A key in d is all non-negative ints n L. A value corresponding
to a key is an Animal object with n as its age. """
d = {}
for n in L:
if type(n) == int and n >= 0:
d[n] = Animal(n)
return d

L = [2,5,'a',-5,0]

animals = animal_dict(L)
for n,a in [Link]():
print(f'key {n} with val {a}')

14

6.100L Lecture 19
YOU TRY IT!
 Write a function that meets this spec.
def make_animals(L1, L2):
""" L1 is a list of ints and L2 is a list of str
L1 and L2 have the same length
Creates a list of Animals the same length as L1 and L2.
An animal object at index i has the age and name
corresponding to the same index in L1 and L2, respectively. """

#For example:
L1 = [2,5,1]
L2 = ["blobfish", "crazyant", "parafox"]
animals = make_animals(L1, L2)
print(animals) # note this prints a list of animal objects
for i in animals: # this loop prints the individual animals
print(i)

15

6.100L Lecture 19
BIG IDEA
Access data attributes
(stuff defined by [Link])

through methods – it’s


better style.

16

6.100L Lecture 19
HIERARCHIES

17 Images © sources unknown. All rights reserved. This content is


excluded from our Creative Commons license. For more
6.100L Lecture 19 information, see [Link]
HIERARCHIES

 Parent class
(superclass) Animal
 Child class
(subclass)
• Inherits all data and
behaviors of parent Person Cat Rabbit
class
• Add more info
• Add more behavior
• Override behavior Student

18

6.100L Lecture 19
INHERITANCE:
PARENT CLASS

class Animal(object):
def __init__(self, age):
[Link] = age
[Link] = None
def get_age(self):
return [Link]
def get_name(self):
return [Link]
def set_age(self, newage):
[Link] = newage
def set_name(self, newname=""):
[Link] = newname
def __str__(self):
return "animal:"+str([Link])+":"+str([Link])
19

6.100L Lecture 19
SUBCLASS CAT

20

6.100L Lecture 19
INHERITANCE:
SUBCLASS

class Cat(Animal):
def speak(self):
print("meow")
def __str__(self):
return "cat:"+str([Link])+":"+str([Link])

 Add new functionality with speak()


 Instance of type Cat can be called with new methods
 Instance of type Animal throws error if called with Cat’s new
method
 __init__ is not missing, uses the Animal version
21

6.100L Lecture 19
WHICH METHOD
TO USE?

 Subclass can have methods with same name as superclass


 For an instance of a class, look for a method name in current
class definition
 If not found, look for method name up the hierarchy (in parent,
then grandparent, and so on)
 Use first method up the hierarchy that you found with that
method name

22

6.100L Lecture 19
SUBCLASS PERSON

23

6.100L Lecture 19
class Person(Animal):
def __init__(self, name, age):
Animal.__init__(self, age)
self.set_name(name)
[Link] = []
def get_friends(self):
return [Link]()
def add_friend(self, fname):
if fname not in [Link]:
[Link](fname)
def speak(self):
print("hello")
def age_diff(self, other):
diff = [Link] - [Link]
print(abs(diff), "year difference")
def __str__(self):
return "person:"+str([Link])+":"+str([Link])

24

6.100L Lecture 19
YOU TRY IT!
 Write a function according to this spec.
def make_pets(d):
""" d is a dict mapping a Person obj to a Cat obj
Prints, on each line, the name of a person, a colon, and the
name of that person's cat """
pass

p1 = Person("ana", 86)
p2 = Person("james", 7)
c1 = Cat(1)
c1.set_name("furball")
c2 = Cat(1)
c2.set_name("fluffsphere")

d = {p1:c1, p2:c2}
make_pets(d) # prints ana:furball
# james:fluffsphere

25

6.100L Lecture 19
BIG IDEA
A subclass can
use a parent’s attributes,
override a parent’s attributes, or
define new attributes.
Attributes are either data or methods.

26

6.100L Lecture 19
SUBCLASS STUDENT

27

6.100L Lecture 19
import random

class Student(Person):
def __init__(self, name, age, major=None):
Person.__init__(self, name, age)
[Link] = major
def change_major(self, major):
[Link] = major
def speak(self):
r = [Link]()
if r < 0.25:
print("i have homework")
elif 0.25 <= r < 0.5:
print("i need sleep")
elif 0.5 <= r < 0.75:
print("i should eat")
else:
print("i'm still zooming")
def __str__(self):
return "student:"+str([Link])+":"+str([Link])+":"+str([Link])

28

6.100L Lecture 19
SUBCLASS RABBIT

29

6.100L Lecture 19
CLASS VARIABLES AND THE Rabbit
SUBCLASS

 Class variables and their values are shared between all


instances of a class
class Rabbit(Animal):
tag = 1
def __init__(self, age, parent1=None,parent2=None):
Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
[Link] = [Link]
[Link] += 1
 tag used to give unique id to each new rabbit instance
30

6.100L Lecture 19
RECALL THE __init__ OF Rabbit

def __init__(self, age, parent1=None,parent2=None):


Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
[Link] = [Link]
[Link] += 1

[Link] 1
2
Age: 8
r1 Parent1: None
Parent2: None
r1 = Rabbit(8) Rid: 1

31

6.100L Lecture 19
RECALL THE __init__ OF Rabbit

def __init__(self, age, parent1=None,parent2=None):


Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
[Link] = [Link]
[Link] += 1

[Link] 1
3
2
Age: 8
r1 Parent1: None
Parent2: None
r1 = Rabbit(8) Rid: 1
r2 = Rabbit(6)
Age: 6
r2 Parent1: None
Parent2: None
Rid: 2

32

6.100L Lecture 19
RECALL THE __init__ OF Rabbit

def __init__(self, age, parent1=None,parent2=None):


Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
[Link] = [Link]
[Link] += 1

[Link] 1
3
2
4
Age: 8
r1 Parent1: None
Parent2: None
r1 = Rabbit(8) Rid: 1
r2 = Rabbit(6)
Age: 6
r3 = Rabbit(10) r2 Parent1: None
Parent2: None
Rid: 2
Age: 10
r3 Parent1: None
Parent2: None
Rid: 3

33

6.100L Lecture 19
Rabbit GETTER METHODS

class Rabbit(Animal):
tag = 1
def __init__(self, age, parent1=None, parent2=None):
Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
[Link] = [Link]
[Link] += 1
def get_rid(self):
return str([Link]).zfill(5)
def get_parent1(self):
return self.parent1
def get_parent2(self):
return self.parent2

34

6.100L Lecture 19
WORKING WITH YOUR OWN
TYPES

def __add__(self, other):


# returning object of same type as this class
return Rabbit(0, self, other)

recall Rabbit’s __init__(self, age, parent1=None, parent2=None)

 Define + operator between two Rabbit instances


 Define what something like this does: r4 = r1 + r2
where r1 and r2 are Rabbit instances
 r4 is a new Rabbit instance with age 0
 r4 has self as one parent and other as the other parent
 In __init__, parent1 and parent2 are of type Rabbit

35

6.100L Lecture 19
RECALL THE __init__ OF Rabbit

def __init__(self, age, parent1=None,parent2=None):


Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
[Link] = [Link]
[Link] += 1

[Link] 1
3
2
4
5
Age: 8
r1 Parent1: None
Parent2: None
Rid: 1
r1 = Rabbit(8) Age: 6
r2 = Rabbit(6) r2 Parent1: None
r3 = Rabbit(10) Parent2: None
Rid: 2
r4 = r1 + r2 Age: 10
r3 Parent1: None
Parent2: None
Rid: 3

Age: 0
Parent1: obj bound to r1
r4 Parent2: obj bound to r2
36
Rid: 4
6.100L Lecture 19
SPECIAL METHOD TO COMPARE TWO
Rabbits

 Decide that two rabbits are equal if they have the same two
parents
def __eq__(self, other):
parents_same = ([Link] == [Link] and [Link] == [Link])
parents_opp = ([Link] == [Link] and [Link] == [Link])
return parents_same or parents_opp

 Compare ids of parents since ids are unique (due to class var)
 Note you can’t compare objects directly
 For ex. with self.parent1 == other.parent1
 This calls the __eq__ method over and over until call it on None and
gives an AttributeError when it tries to do None.parent1

37

6.100L Lecture 19
BIG IDEA
Class variables are
shared between all
instances.
If one instance changes it, it’s changed for every instance.

38

6.100L Lecture 19
OBJECT ORIENTED
PROGRAMMING
 Create your own collections of data
 Organize information
 Division of work
 Access information in a consistent manner

 Add layers of complexity


 Hierarchies
 Child classes inherit data and methods from parent classes
 Like functions, classes are a mechanism for decomposition and
abstraction in programming

39

6.100L Lecture 19
MITOpenCourseWare
[Link]

6.100L Introduction to Computer Science and Programming Using Python


Fall 2022

For information about citing these materials or our Terms ofUse,visit: [Link]

40

You might also like