Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
9 views

Week-2 Python Fundamentals

Uploaded by

Shashank S
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

Week-2 Python Fundamentals

Uploaded by

Shashank S
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 68

NPTEL MOOC

PROGRAMMING,
DATA STRUCTURES AND
ALGORITHMS IN PYTHON
Week 2, Lecture 1

Madhavan Mukund, Chennai Mathematical Institute


http://www.cmi.ac.in/~madhavan
A typical Python program
def function_1(..,..): Interpreter executes
… statements from top
def function_2(..,..):
to bottom


Function definitions
def function_k(..,..):
are “digested” for

future use
statement_1
statement_2 Actual computation
⋮ starts from
statement_n statement_1
A more messy program
statement_1 Python allows free
mixing of function
def function_1(..,..):
… definitions and
statements
statement_2
statement_3 But programs written
like this are likely to
def function_2(..,..):
be harder to

understand and
statement_4 debug

Assignment statement
Assign a value to a name

i = 5
j = 2*i
j = j + 5

Left hand side is a name

Right hand side is an expression

Operations in expression depend on type of value


Numeric values

Numbers come in two flavours

int — integers

float — fractional numbers

178, -3, 4283829 are values of type int

37.82, -0.01, 28.7998 are values of type float


int vs float
Why are these different types?

Internally, a value is stored as a finite sequence of


0’s and 1’s (binary digits, or bits)

For an int, this sequence is read off as a binary


number

For a float, this sequence breaks up into a


mantissa and exponent

Like “scientific” notation: 0.602 x 1024


Operations on numbers
Normal arithmetic operations: +,-,*,/

Note that / always produces a float

7/3.5 is 2.0, 7/2 is 3.5

Quotient and remainder: // and %

9//5 is 1, 9%5 is 4

Exponentiation: **

3**4 is 81
Other operations on
numbers

log(), sqrt(), sin(), …

Built in to Python, but not available by default

Must include math “library”

from math import *


Names, values and types
Values have types

Type determines what operations are legal

Names inherit their type from their current value

Type of a name is not fixed

Unlike languages like C, C++, Java where each


name is “declared” in advance with its type
Names, values and types
Names can be assigned values of different types as
the program evolves

i = 5 # i is int
i = 7*1 # i is still int
j = i/3 # j is float, / creates float

i = 2*j # i is now float

type(e) returns type of expression e

Not good style to assign values of mixed types to


same name!
Boolean values: bool

True, False

Logical operators: not, and, or

not True is False, not False is True

x and y is True if both of x,y are True

x or y is True if at least one of x,y is True


Comparisons
x == y, a != b,
z < 17*5, n > m,
i <= j+k, 19 >= 44*d

Combine using logical operators

n > 0 and m%n == 0

Assign a boolean expression to a name

divisor = (m%n == 0)
Examples
def divides(m,n):
if n%m == 0:
return(True)
else:
return(False)

def even(n):
return(divides(2,n))

def odd(n):
return(not divides(2,n))
Summary

Values have types

Determine what operations are allowed

Names inherit type from currently assigned value

Can assign values of different types to a name

int, float, bool


NPTEL MOOC

PROGRAMMING,
DATA STRUCTURES AND
ALGORITHMS IN PYTHON
Week 2, Lecture 2

Madhavan Mukund, Chennai Mathematical Institute


http://www.cmi.ac.in/~madhavan
Names, values and types
Values have types

Determine what operations are allowed

Names inherit type from currently assigned value

Can assign values of different types to a name

int, float, bool

+,-,*,/,.. and,or,.. ==,!=,>,..


Manipulating text

Computation is a lot more than number crunching

Text processing is increasingly important

Document preparation

Importing/exporting spreadsheet data

Matching search queries to content


Strings —type str
Type string, str, a sequence of characters

A single character is a string of length 1

No separate type char

Enclose in quotes—single, double, even triple!


city = 'Chennai'

title = "Hitchhiker's Guide to the Galaxy"

dialogue = '''He said his favourite book is


"Hitchhiker's Guide to the Galaxy”'''
Strings as sequences

String: sequence or list of characters

Positions 0,1,2,…,n-1 for a string of length n


0 1 2 3 4
s = "hello" h e l l o
-5 -4 -3 -2 -1
Positions -1,-2,… count backwards from end

s[1] == "e", s[-2] = "l"


Operations on strings
Combine two strings: concatenation, operator +

s = "hello"

t = s + ", there"

t is now "hello, there"

len(s) returns length of s

Will see other functions to manipulate strings later


Extracting substrings
A slice is a “segment” of a string

s = "hello"

s[1:4] is “ell"

s[i:j] starts at s[i] and ends at s[j-1]

s[:j] starts at s[0], so s[0:j]

s[i:] ends at s[len(s)-1], so s[i:len(s)]


Modifying strings
Cannot update a string “in place”

s = "hello", want to change to "help!"

s[3] = "p" — error!

Instead, use slices and concatenation

s = s[0:3] + "p!"

Strings are immutable values (more later)


Summary
Text values — type str, sequence of characters

Single character is string of length 1

Extract individual characters by position

Slices extract substrings

+ glues strings together

Cannot update strings directly — immutable


NPTEL MOOC

PROGRAMMING,
DATA STRUCTURES AND
ALGORITHMS IN PYTHON
Week 2, Lecture 3

Madhavan Mukund, Chennai Mathematical Institute


http://www.cmi.ac.in/~madhavan
Types of values in Python
Numbers: int, float
Arithmetic operations +,-,*,/,…

Logical values: bool, {True, False}


Logical operations not,and,…
Comparisons ==,!=,<,>,<=,>=

Strings: str, sequences of characters


Extract by position s[i], slice s[i:j]
Concatenation +, length len(), …
Lists
Sequences of values
factors = [1,2,5,10]
names = ["Anand","Charles","Muqsit"]

Type need not be uniform


mixed = [3, True, "Yellow"]

Extract values by position, slice, like str


factors[3] is 10, mixed[0:2] is [3,True]

Length is given by len()


len(names) is 3
Lists and strings
For str, both a single position and a slice return
strings
h = "hello"
h[0] == h[0:1] == "h"

For lists, a single position returns a value, a slice


returns a list
factors = [1,2,5,10]
factors[0] == 1, factors[0:1] == [1]
Nested lists

Lists can contain other lists

nested = [[2,[37]],4,["hello"]]

nested[0] is [2,[37]]
nested[1] is 4
nested[2][0][3] is "l"
nested[0][1:2] is [[37]]
Updating lists
Unlike strings, lists can be updated in place

nested = [[2,[37]],4,["hello"]]
nested[1] = 7
nested is now [[2,[37]],7,["hello"]]
nested[0][1][0] = 19
nested is now [[2,[19]],7,["hello"]]

Lists are mutable, unlike strings


Mutable vs immutable
What happens when we assign names?

x = 5
y = x
x = 7

Has the value of y changed?

No, why should it?

Does assignment copy the value or make both


names point to the same value?
Mutable vs immutable …

Does assignment copy the value or make both


names point to the same value?

For immutable values, we can assume that


assignment makes a fresh copy of a value

Values of type int, float, bool, str are


immutable

Updating one value does not affect the copy


Mutable vs immutable …
For mutable values, assignment does not make a
fresh copy

list1 = [1,3,5,7]
list2 = list1
list1[2] = 4

What is list2[2] now?

list2[2] is also 4

list1 and list2 are two names for the same list
Copying lists
How can we make a copy of a list?

A slice creates a new (sub)list from an old one

Recall l[:k] is l[0:k], l[k:] is l[k:len(l)]

Omitting both end points gives a full slice


l[:] == l[0:len(l)]

To make a copy of a list use a full slice


list2 = list1[:]
Digression on equality
Consider the following assignments
list1 = [1,3,5,7]
list2 = [1,3,5,7]
list3 = list2

All three lists are equal, but there is a difference


list1 and list2 are two lists with same value
list2 and list3 are two names for same list
Digression on equality …
list1 = [1,3,5,7]
list2 = [1,3,5,7]
list3 = list2
x == y checks if x and y have same value
x is y checks if x and y refer to same object
list1 == list2 is True
list2 == list3 is True
list2 is list3 is True
list1 is list2 is False
Concatenation
Like strings, lists can be glued together using +

list1 = [1,3,5,7]
list2 = [4,5,6,8]
list3 = list1 + list2
list3 is now [1,3,5,7,4,5,6,8]
Note that + always produces a new list
list1 = [1,3,5,7]
list2 = list1
list1 = list1 + [9]
list1 and list2 no longer point to the same object
Summary
Lists are sequences of values
Values need not be of uniform type
Lists may be nested

Can access value at a position, or a slice

Lists are mutable, can update in place


Assignment does not copy the value
Use full slice to make a copy of a list
NPTEL MOOC

PROGRAMMING,
DATA STRUCTURES AND
ALGORITHMS IN PYTHON
Week 2, Lecture 4

Madhavan Mukund, Chennai Mathematical Institute


http://www.cmi.ac.in/~madhavan
A typical Python program
def function_1(..,..): Interpreter executes
… statements from top
def function_2(..,..):
to bottom


Function definitions
def function_k(..,..):
are “digested” for

future use
statement_1
statement_2 Actual computation
⋮ starts from
statement_n statement_1
Control flow
Need to vary computation steps as values change

Control flow — determines order in which


statements are executed

Conditional execution

Repeated execution — loops

Function definitions
Conditional execution
if m%n != 0:
(m,n) = (n,m%n)
Second statement is executed only if the condition
m%n != 0 is True
Indentation demarcates body of if — must be uniform
if condition:
statement_1 # Execute conditionally
statement_2 # Execute conditionally
statement_3 # Execute unconditionally
Alternative execution

if m%n != 0:
(m,n) = (n,m%n)
else:
gcd = n

else: is optional
Shortcuts for conditions
Numeric value 0 is treated as False

Empty sequence "", [] is treated as False

Everything else is True

if m%n:
(m,n) = (n,m%n)
else:
gcd = n
Multiway branching, elif:
if x == 1: if x == 1:
y = f1(x) y = f1(x)
else: elif x == 2:
if x == 2: y = f2(x)
y = f2(x) elif x == 3:
else: y = f3(x)
if x == 3: else:
y = f3(x) y = f4(x)
else:
y = f4(x)
Loops: repeated actions

Repeat something a fixed number of times

for i in [1,2,3,4]:
y = y*i
z = z+1

Again, indentation to mark body of loop


Repeating n times
Often we want to do something exactly n times
for i in [1,2,..,n]:
. . .

range(0,n) generates sequence 0,1,…,n-1


for i in range(0,n):
. . .

range(i,j) generates sequence i,i+1,…,j-1

More details about range() later


Example
Find all factors of a number n

Factors must lie between 1 and n

def factors(n):
flist = []
for i in range(1,n+1):
if n%i == 0:
flist = flist + [i]
return(flist)
Loop based on a condition
Often we don’t know number of repetitions in
advance

while condition:
. . .

Execute body if condition evaluates to True

After each iteration, check condition again

Body must ensure progress towards termination!


Example
Euclid’s gcd algorithm using remainder

Update m, n till we find n to be a divisor of m

def gcd(m,n):
if m < n:
(m,n) = (n,m)
while m%n != 0:
(m,n) = (n,m%n)
return(n)
Summary
Normally, statements are executed top to bottom,
in sequence

Can alter the control flow

if … elif … else — conditional execution

for i in … — repeat a fixed number of times

while … — repeat based on a condition


NPTEL MOOC

PROGRAMMING,
DATA STRUCTURES AND
ALGORITHMS IN PYTHON
Week 2, Lecture 5

Madhavan Mukund, Chennai Mathematical Institute


http://www.cmi.ac.in/~madhavan
A typical Python program
def function_1(..,..): Interpreter executes
… statements from top
def function_2(..,..):
to bottom


Function definitions
def function_k(..,..):
are “digested” for

future use
statement_1
statement_2 Actual computation
⋮ starts from
statement_n statement_1
Function definition
def f(a,b,c):
statement_1
statement_2
..
return(v)
..

Function name, arguments/parameters

Body is indented

return() statement exits and returns a value


Passing values to functions

Argument value is substituted for name

def power(x,n): power(3,5)


ans = 1 x = 3
for i in range(0,n): n = 5
ans = ans*x ans = 1
return(ans) for i in range..

Like an implicit assignment statement


Passing values …

Same rules apply for mutable, immutable values

Immutable value will not be affected at calling


point

Mutable values will be affected


Example
def update(l,i,v): ns = [3,11,12]
if i >= 0 and i < len(l): z = 8
l[i] = v update(ns,2,z)
return(True) update(ns,4,z)
else:
v = v+1 ns is [3,11,8]
return(False) z remains 8

Return value may be ignored

If there is no return(), function ends when last


statement is reached
Scope of names
Names within a function have local scope

def stupid(x):
n = 17
return(x)

n = 7
v = stupid(28)
# What is n now?

n is still 7
Name n inside function is separate from n outside
Defining functions
A function must be defined before it is invoked

This is OK This is not

def f(x): def f(x):


return(g(x+1)) return(g(x+1))

def g(y): z = f(77)


return(y+3)
def g(y):
z = f(77) return(y+3)
Recursive functions

A function can call itself — recursion

def factorial(n):
if n <= 0:
return(1)
else:
val = n * factorial(n-1)
return(val)
Summary
Functions are a good way to organise code in logical
chunks

Passing arguments to a function is like assigning


values to names

Only mutable values can be updated

Names in functions have local scope

Functions must be defined before use

Recursion — a function can call itself


NPTEL MOOC

PROGRAMMING,
DATA STRUCTURES AND
ALGORITHMS IN PYTHON
Week 2, Lecture 6

Madhavan Mukund, Chennai Mathematical Institute


http://www.cmi.ac.in/~madhavan
Some examples
Find all factors of a number n

Factors must lie between 1 and n

def factors(n):
factorlist = []
for i in range(1,n+1):
if n%i == 0:
factorlist = factorlist + [i]
return(factorlist)
Primes
Prime number — only factors are 1 and itself

factors(17) is [1,17]

factors(18) is [1,2,3,6,9,18]

def isprime(n):
return(factors(n) == [1,n])

1 should not be reported as a prime

factors(1) is [1], not [1,1]


Primes upto n

List all primes below a given number

def primesupto(n):
primelist = []
for i in range(1,n+1):
if isprime(i):
primelist = primelist + [i]
return(primelist)
First n primes

List the first n primes

def nprimes(n):
(count,i,plist) = (0,1,[])
while(count < n):
if isprime(i):
(count,plist) = (count+1,plist+[i])
i = i+1
return(plist)
for and while

primesupto()

Know we have to scan from 1 to n, use for

nprimes()

Range to scan not known in advance, use while


for and while
Can use while to simulate for

for n in range(i,j): n = i
statement while n < j:
statement
n = n+1

for n in l: i = 0
statement while i < len(l):
n = l[i]
statement
i = i+1
for and while
Can use while to simulate for
However, use for where it is natural
Makes for more readable code
What makes a good program?
Correctness and efficiency — algorithm
Readability, ease of maintenance — style
What you say, and how you say it

You might also like