123
Introduction to Python Based on material for the course Programming with Python by Chad Haynes. Modified at Kasetsart University by Chaiporn Jaokaew and James Brucker.

Introduction to Python B ased on material for the course Programming with Python by Chad Haynes. Modified at Kasetsart University by Chaiporn Jaokaew and

Embed Size (px)

Citation preview

Introduction to Python

Based on material for the course

Programming with Python by Chad Haynes.

Modified at Kasetsart University by Chaiporn Jaokaew and James Brucker.

Outline

Overview

Built-in objects

Functions and scopes

Object-oriented programming

Functional programming

Exercise

Python At First Glance

import math

def showArea(shape): print("Area = ", shape.area() )

def widthOfSquare(area): return math.sqrt(area)

class Rectangle(object):

def __init__(self, width, height):self.width = widthself.height = height

def area(self):return self.width * self.height

###### Main Program ######r = Rectangle(10, 20)

showArea(r)

Function definition

Class definition

Import a library module

Calling a function

Comment

Object instantiation

Why use Python?

Simple syntax: easy to learn and remember

Portable

Flexible

Large standard library

Short development time

Lots of 3rd party tools/add-ons

Many good implementations:

CPython, PyPy, IronPython, Jython

Active open-source community

Similarities to Java

Everything inherits from "object"

Has numbers, functions, classes, …

Everything is first-class

Large standard library

Garbage collection

Introspection, serialization, threads, net,…

Python vs. Java/C++/C

Typing: strong, but dynamic Names have no type Objects have type

No name declarations Sparse syntax

No { } for blocks, just indentation No ( ) for if/while conditions

Interactive interpreter # for comments (like Perl)

// this is Javaif (x < 10){ x = x + tmp; y = y * x;}System.out.println(y);

Java

# this is Pythonif x < 10:

x = x + tmpy = y * x

print( y )

Python

Getting Started

Download from: http://python.org/

Add python to PATH to run scripts from command line

Python is available for most platforms, even mobile.

Most Linux distributions have Python as package(s)

Python 3: print( "hello" )

There are some differences between Python 2.x and Python 3 syntax.

print is a function in Python 3, which uses parenthesis:

Python 3.x:

Python 2.x:

print("hello")

print "hello"

C#

Python

using System;class Hello{

static void Main(){

Console.WriteLine("Hello, World");}

}

Hello, World!

print("Hello, World")

Variables

>>> x = 23>>> print(x)23>>> x = 'foo'>>> print(x)foo>>> del x>>> print(x)Traceback (most recent call last): File "<stdin>", line 1, in <module>NameError: name 'x' is not defined>>>

name x means 23

now it means 'foo'

x is undefined

Var1

Var1_copy

Var2

Variables

Variable is a reference to an object not a value more than one variable can refer to the same

object

Numeric Types

Integers Generally signed, 32-bit

Long Integers Unlimited size Format: <number>L Example: 4294967296L

Float Platform dependant “double” precision

Complex Format: <real>+<imag>j Example: 6+3j

Strings

A sequence of characters enclosed in quotes3 ways to quote strings:

'Single Quotes'"Double Quotes""""Triple Quotes""" or '''triple quotes'''

– Triple quotes can span multiple lines

Examples>>> print('This string may contain a "')This string may contain a ">>> print("A ' is allowed")A ' is allowed>>> print("""Either " or ' are OK""")Either " or ' are OK

raw_input( [prompt] ) Print prompt and return user's input as a string a built-in function

Example

>>> reply = raw_input('Are you awake? ')

Are you awake? not sure

>>> print( reply )

not sure

raw_input for reading input

operators: + - * / // ** % abs

Examples:

>>> 5 + 3 # Addition8>>> 2 ** 8 # Exponentiation256>>> 13 / 4 # Integer (Truncating) Division*3>>> float(13) / 4 # Float Division3.25>>> 13 % 4 # Remainder1>>> abs(-3.5) # Absolute Value3.5

Arithmetic Operations

* 13/4 performs float division in Python 3.x

Comparison: < <= > >= == != <>

Results in 1 (true) or 0 (false)

Example

>>> 4 > 1.51>>> 'this' != 'that'1>>> 4+3j == 4-2j0>>> '5' == 50>>> 0 < 10 < 201

Boolean comparisons

Operators: and or not

Standard Boolean Algebra

Boolean Operations

i1 i2 i1 and i2

1

1

1

0

0

0

1

0

1

0

0

0

i1 or i2

1

1

1

0

i1 not i1

1

0 1

0

Boolean values

True: any non-zero, non-null value.

False: None (null)

empty string

empty list

0

s = "hello"

if s:

print("true")

lst = []

if lst:

print("list is not empty")

Boolean Expressions

>>> 1 == 1 and 2 >= 3False>>> 1 == 1 or 2 >= 3True>>> not 5.3 != 2.2 # same as: not (5.3 != 2.2)False>>> 2 and '23' > '11' or 0True

Concatenation (+): string1 + string2

Example:

>>> 'Rockefeller' + 'University'

'RockefellerUniversity'

Repetition (*): string * number

Example:

>>> 'dog' * 5

'dogdogdogdogdog'

Building strings

C-Style formatting (extended printf):

"format string" % (arg1, arg2, ...)

String Formatting

>>> "%i %s in the basket" % (2, "eggs")

'2 eggs in the basket'

>>> x = 2.0/9.0

>>> "%f to 2 dec places is %.2f" % (x, x)

'0.222222 to 2 decimal places is 0.22'

>>> length = 5

>>> obj = "fence"

>>> "Length of %(obj)s is %(length)i" % vars()

'Length of the fence is 5'

Format codes begin with "%":

String Format Codes

import math

x = 10

"x is %f" % x

"pi is %.8f" % math.pi

"pi is %12.6f" % math.pi

eps = 1.0E-17

"eps is %f (%g)" % (eps, eps)

Python format mini-language reference:

http://docs.python.org/3.1/library/string.html#format-specification-mini-language

String Formatting using .format

>>> "{0} {1} in the basket".format(2, "eggs")

'2 eggs in the basket'

>>> x = 2.0/9.0

>>> "{0} to 2 dec places is {0:.2f}".format(x)

'0.222222 to 2 decimal places is 0.22'

"{0} to {1} dec places is {0:.{1}f}".format(x,3)

'0.222222 to 3 decimal places is 0.222'

>>> name = "James Bond"

>>> id = 7

>>> "{0:12s} is {1:03d}".format(name,id)

'James Bond is 007'

String functionss = '''Now is the timefor all good men'''

Multi-line strings (triple quote)

list = s.splitlines() return list of lines in string

s.lower() to lowercase

s.upper() to uppercase

s.title() title case

s.index('me') index of first occurrence, throw exception if substring not found

s.count('me') count occurrences

s[1:10] slice, just like list slice

s.replace("men","people") replace substring.

String format functions

>>> "Hello".ljust(8)

"Hello "

Left justify to given length.

>>> "Hello".rjust(8)

" Hello"

Right justify.

>>> "Hello".center(8)

" Hello "

Center, of course.

>>> u = "Bird"

>>> "Hello {0}".format(u)

'Hello Bird'

Format using template.

Determine the type of an object

Syntax: type(object)

Examples

>>> type(2.45)

<type 'float'>

>>> type('x')

<type 'str'>

>>> type(2**34)

<type 'long'>

>>> type(3+2j)

<type 'complex'>

type determines type of Object

Testing the type

if type(x) is int:

print("x is an integer")

Functions to convert between types:

str() int() float() complex() bool()

Type Conversions

>>> str(0.5)'0.5'>>> float('-1.32e-3')-0.00132>>> int('0243')243>>> int(2**100)1267650600228229401496703205376>>> bool('hi')True>>> bool('False') # any non-zero, non-null is trueTrue

List l = [ 2, 3, 5, 8 ]

Tuple (read-only list) t = ( 2, 3, 5, 8 )

Set s = { 2, 5, 3, 8 }

Dictionary (key-value map) d = {"two":2, "three": 3, ...}

Built-in Data Structures

Syntax: [elem1, elem2, ...]

Ordered sequence of any type (mixed types ok)

Mutable

>>> list1 = [1, 'hello', 4+2j, 123.12]

>>> list1

[1, 'hello', (4+2j), 123.12]

>>> list1[0] = 'a'

>>> list1

['a', 'hello', (4+2j), 123.12]

Lists

Concatenation: list1 + list2

>>> [1, 'a', 'b'] + [3, 4, 5]

[1, 'a', 'b', 3, 4, 5]

Repetition: list * count

>>> [23, 'x'] * 4

[23, 'x', 23, 'x', 23, 'x', 23, 'x']

Joining and Repeating Lists

>>> list = [ "apple", "banana" ]

Append item to end

>>> list.append( "durian" )

Append another list

>>> list.extend( list2 )

- Same as list + list2

Insert item anywhere

>>> list.insert( 0, "artichoke" )

>>> list.insert( 2, "carrot" )Like Java list.add( n, item)

Adding Elements to a List

len( ) returns length of a list

>>> list = [ "a", "b", "c" ]

>>> len( list )

3

Not so object-oriented len( )

>>> list = [ "a" "b", "c", "b" ]

• Remove a matching element (w/o returning it)

>>> list.remove( "b" )

Throws exception if argument is not in the list

• Remove last element and return it

>>> list.pop( )

'b'

• Remove by position

>>> list.pop( 1 ) # 'b' removed already'c'

Removing Elements from a List

Syntax: list[n]

• Positive indices count from the left: list[0]

• Negative indices count from the right: list[-1]

Indexing

0 1 2 3 4 5 6

-7 -6 -5 -4 -3 -2 -1

a b c d e f g

list[0] == a sequence[-1] == g

list[2] == c sequence[-2] == f

list[6] == g sequence[-7] == a

list[m:n] return elements m up to n (exclusive)

syntax for both strings and lists

List Slicing: get a sublist

>>> x = [0, 1, 2, 3, 4, 5, 6, 7]

>>> x[1:4]

[1, 2, 3]

>>> x[2:-1]

[2, 3, 4, 5, 6]

# Missing Index means start or end of list

>>> x[:2]

[0, 1]

>>> "Hello nerd"[3:]

lo Nerd

List.sort( [comparator] )

Sort List in place. Result is applied to the list!

Example:

>>> list3 = [4, 12, 3, 9]

>>> list3.sort()

>>> list3

[3, 4, 9, 12]

Sorting a list

Count or find elements in a list

list.count( element )

count number of occurences of element.

n = list.index( element )

return index of first occurence of element.

Throws ValueError if element is not in list.

Immutable list

Syntax: (elem1, elem2, …)

A tuple cannot be changed.

Example:

>>> tuple1 = (1, 5, 10)

>>> tuple1[2] = 2

Traceback (most recent call last):

File "<pyshell#136>", line 1, in ?

tuple1[2] = 2

TypeError: object doesn't support item assignment

Tuples

Converting between list and tuple

>>> list1 = ['a', 'b', 'c']

>>> tuple1 = tuple( list1 )

>>> type( tuple1 )

<class 'tuple'>

>>> tuple2 = ('cat', 'dog')

>>> list2 = list(tuple2)

n = len(object)

Return the length of object

Examples

>>> list1 = [1, 2, 3, 4, 5]

>>> len(list1)

5

>>> string1 = "length of a string"

>>> len(string1)

18

len - Length of an object

len is not object-oriented.

(a,b,c) = (10, 20, 50)

>>> b

20

This can be used in for loops.

Multiple assignment using tuples

points = [ (1,0), (0.2,0.9), (1,2) ]

for (x,y) in points:

r = math.hypot(x,y)

print("radius of (%f,%f) is %f" % (x,y,r) )

A mapping of keys to values

Associate a key with a value

Each key must be unique

Dictionary: mapping key to value

'z' 'ab' 2.1 3keys

10 [2] (3,8) 'hello'values

Syntax: dict = {key1: value1, key2: value2, ...}

Using Dictionaries

>>> dict = {'a': 1, 'b': 2}

>>> dict

{'a': 1, 'b': 2}

>>> dict['a']

1

>>> dict['b']

2

>>> dict[3] = 'three'

>>> dict

{'a': 1, 'b': 2, 3: 'three'}

Set

An unordered collection, without duplicates (like Java).

Syntax is like dictionary, but no ":" between key-value.

>>> aset = { 'a', 'b', 'c' }

>>> aset

{'a', 'c', 'b'}

>>> aset.add('c") # no effect, 'c' already in set

>>> aset

{'a', 'c', 'b'}

Set Methods

set.discard('cat') remove cat. No error if not in set.

set.remove('cat') remove cat. Error if not in set.

set3 = set1.union(set2) doesn't change set1.

set4 = set1.intersection(set2)

doesn't change set1.

set2.issubset( set1 )

set2.issuperset( set1 )

set1.difference( set2 ) element in set1 not set2

set1.symmetric_difference(set2)

xor

set1.clear( ) remove everything

Test for element in Set

item in set

>>> aset = { 'a', 'b', 'c' }

>>> 'a' in aset

True

>>> 'A' in aset

False

Flow Control

if condition :body

elif condition :body

else:body

if x%2 == 0:y = y + x

else:y = y - x

while count < 10: count = 2*count

for x in [1,2,3]:sum = sum + x

while condition:body

for name in iterable:body

range([start,] stop[, step])

Generate a list of numbers from start to stop stepping every step

start defaults to 0, step defaults to 1

Example

>>> range(5)

[0, 1, 2, 3, 4]

>>> range(1, 9)

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

>>> range(2, 20, 5)

[2, 7, 12, 17]

range: create a sequence

Use range to generate values to use in for loop

>>> for i in range(1,4):

print i

1

2

3

for loop using range( )

dir returns all methods for a class or object

>>> lst = [1, 3, 2]

>>> dir(lst)

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', ...

'__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'

>>> dir( math ) # import math first['__doc__', '__name__', '__package__', 'acos', 'asin", 'atan', 'atan2', 'ceil', 'copysoign', 'cos', 'degrees', 'e', 'exp', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'hypot', ...

dir: show all methods & attributes

Getting Help

The help function gives help for a module or function.

>>> help(str)Help on class str in module __builtin__:

class str(basestring) | str(object) -> string | | Return a nice string representation of the object. | | Method resolution order: | str | basestring | object | | Methods defined here: | ...

Functions and Scope

Syntax: def func(arg1, …):

body

Body of function must be indented

If no value is returned explicitly, function will return None

Defining Functions

def average(num1, num2, num3):

sum = num1 + num2 + num3

avg = sum / 3.0

return avg

• Parameters can be any type

- A function can take any number of parameters or none at all

Function Parameters

def usage(programName, version):

print("%s Version %i" % (programName, version))

print("Usage: %s arg1 arg2" % programName)

>>> usage('Test', 1.0)

Test Version 1.0

Usage: Test arg1 arg2

Parameters can be given a default values

split(string, substr=' ')

The function can be called with fewer arguments than there are parameters

Parameters with default values must come last

Function Default Parameter values

>>> def printName(last, first, mi=""):

print("%s, %s %s" % (last, first, mi))

>>> printName("Smith", "John")

Smith, John

>>> printName("Smith", "John", "Q")

Smith, John Q

Functions can be invoked using the name of the parameter and a value

func(param=value, ...)

The order of values passed by keyword does not matter

Keyword Arguments

def fun(key1="X", key2="X", key3="X", key4="X"):

'''function with keywords and default values'''

print(key1, key2, key3, key4)

>>> fun(key3="O", key2="O")

X O O X

>>> fun(key4='Z')

X X X Z

Functions can be used just like any other data type

Functions can be assigned to variables

def sub(a, b):

return a-b

>>> op = sub

>>> print op(3, 5)

-2

>>> type(op)

<type 'function'>

Functions at Values

Functions can be passed to other functions

Functions as Parameters

def convert(data, convertFunc):

for i in range(len(data)):

data[i] = convertFunc(data[i])

return data

>>> convert(['1', '5', '10', '53'], int)

[1, 5, 10, 53]

>>> convert(['1', 'nerd', '10', 'hi!'], len)

[1.0, 5.0, 10.0, 53.0]

>>> convert(['1', '5', '10', '53'], complex)

[(1+0j), (5+0j), (10+0j), (53+0j)]

Return a tuple of values.

Example: string.split( ) returns a tuple of substrings.

Functions can return multiple values

def separate(text, size=3):

'''divide a string into two parts'''

head = text[:size]

tail = text[size:]

return (head,tail)

# ok to omit parens: start,last = separate(...)

>>> (start,last) = separate('GOODBYE', 4)

>>> start

GOOD

>>> last

BYE

Generators

Generators are functions that generate a sequence of items, but only when requested

Generated sequence can be infinite

def fibonacci():a = b = 1while True:

yield aa, b = b, a+b

for rabbits in fibonacci():print( rabbits )if rabbits > 100: break

1 1 2 3 5 8 13 21 34 55 89 144

Generators

Generator invokes yield to "yield" control.

Receiver calls next(generator) to invoke generator.

def filereader( filename ):with open(filename) as infile:

line = infile.read()yield line

gen = filereader( "readme.txt" )s = next(gen)process_line(s)s = next(gen)...

Namespaces and Scopes

Namespace A mapping from names to objects (Currently) implemented as Python dictionaries

Scope A region of program where a namespace is accessible Name references search at most 3 scopes:

local, global, built-in Assignments create or change local names by default Can force names to be global with global command

Scope Example

X = 99def func(Y):

Z = X+Y # X not assigned, so it's globalreturn Z

>>> func(1)

X = 99def func(Y):

X = 10Z = X+Y # X is localreturn Z

>>> func(1)>>> X # still 99

A file containing Python definitions and statements

Modules can be “imported”

Module file name must end in .py

Used to divide code between files

Modules

import mathimport string…

math.py string.py

import <module name>

module name is the file name without .py extension

You must use the module name to call functions

import Statement

>>> import math

>>> dir(math)

['__doc__', '__name__', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', ...]

>>> math.e

2.71828182846

>>> math.sqrt(2.3)

1.51657508881

from <module> import <name> Import a specific name from a module into global namespace

Module name is not required to access imported name(s)

import specific names

>>> from math import sqrt

>>> sqrt(16)

4

>>> dir(math)

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

NameError: name 'math' is not defined

from <module> import *

Import everything into global namespace

import all names from module

>>> dir()

['__builtins__', '__doc__', '__name__']

>>> from time import *

>>> dir()

['__builtins__', '__doc__', '__name__', 'accept2dyear', 'altzone', 'asctime', 'clock', 'ctime', 'daylight', 'gmtime', 'localtime', 'mktime', 'sleep', 'strftime', 'time', ... ]

>>> time()

1054004638.75

Python Standard Libraries

sys System-specific parameters and functions

time Time access and conversions

thread Multiple threads of control

re Regular expression operations

email Email and MIME handling

httplib HTTP protocol client

tkinter GUI package based on TCL/Tk (in Python 2.x this is named Tkinter)

See http://docs.python.org/library/index.html

The os ModuleOperating System related functions

import os

os.getcwd( ) Get current working directory

os.chdir("/temp/somedir") Change dir. Use forward slash on MS Windows.

os.getenv('JAVA_HOME') Get environment variable.

os.unlink('filename') Remove regular file

os.removedirs('dirname') Remove directory(s)

stats = os.stat('file') Get file metadata: ctime, mtime, atime, uid, gid

os.path

Module for manipulating paths

> (dir, file) = os.path.split("/some/path/test.py")

> dir

'/some/path'

> file

'test.py'

> (name,ext) = os.path.splitext(file)

> ext

'py'

# Test absolute path to file

> os.chdir('/Temp/examples')

> os.path.realpath('readme.txt')

C:\\Temp\\examples\\readme.txt

glob

Module for getting files in directory

> import glob

> glob.glob('*.txt')

['help.txt', 'install.txt', 'readme.txt', 'zzz.txt']

with to define a block for open

File is automatically closed at end of "with" block, even if an exception occurs.

with open("students.csv",'r') as student_file:

# read each line of file

for line in student_file:

(id,name,email) = split(',', 3)

print("%s has id %s" % (name,id))

[ expression for var in list ]

Apply an expression to every element of a list

Can simultaneously map and filter

List Comprehensions

>>> import math

>>> [math.pow(2,x) for x in range(1,7)]

[2.0, 4.0, 8.0, 16.0, 32.0, 64.0]

result = [ expr for var in list if expr2 ]

apply to elements of list where expr2 is true

Example: Remove smallest element from list

>>> lst1 = [5, 10, 3, 9]

>>> [x for x in lst1 if x != min(lst1)]

[5, 10, 9]

Example: Sum all lists of size greater than 2>>> lst1 = [[1, 2, 4], [3, 1], [5, 9, 10, 11]]

>>> [reduce(operator.add, x) for x in lst1 if len(x) > 2]

[7, 35]

List Comprehension with filter

[expr for x in list1 for y in list2]

The loops will be nested

List Comprehension with nested for

>>> vowels = ['a','e','i','o','u']

>>> const = ['b','s']

>>> [c+v for c in const for v in vowels]

['ba', 'be', 'bi', 'bo', 'bu', 'sa', 'se', 'si', 'so', 'su']

List Comprehension for files Find all files in directory larger than 1MB

Return the real path to file

import os, glob

[os.path.realpath(f) for f in glob.glob('*.*')

if os.stat(f).st_size >= 1000000]

dict = {expr for var in list if expr2}

Like list comprehension but generates a dictionary.

• expr must be key:value pair (of course)

Dictionary Comprehensions

# Create dictionary of .exe filenames and sizes.

import os, glob

os.chdir('/windows/system32')

files = {fname:os.stat(fname).st_size

for fname in glob.glob('*.exe') }

# print them

for (key,val) in files.items():

print("%-20s %8d" % (key,val))

OO Programming

Defining a Class

Syntax:

Create a class with default superclass

class MyClass(object):myvar = 30

>>> MyClass.myvar30

class name[(base_class)]:body

# old styleclass name:

body

# new styleclass name(object):

body

Defining Constructor and Methods

All instance methods must must have explicit object reference (self) as the first parameter

self is the conventional name (like Java "this")

class Rectangle(object):def __init__(self, width, height):

self.width = widthself.height = height

def area(self):return self.width * self.height

>>> r = Rectangle(10, 20)>>> Rectangle.area(r)200>>> r.area()200

No "new".

constructor

Weak Encapsulation

Everything is public.

Instance methods can be used in static way.

class Person:

def __init__(self, name):

self.name = name

def greet(self):

print("Hello "+self.name)

>>> p = Person("Me")

>>> p.name # attributes are public

>>> p.greet() # O-O style method call

>>> Person.greet(p) # imperative style

Hiding by name mangling

Any attribute name that begins with "_ _" is mangled to "_Class_ _name".

class Person:def __init__(self, name):

self.__name = name# Mangled to _Person__name

@propertydef name(self):

return self.__name #auto demangle

>>> p = Person("Lone Ranger")>>> p.name # returns the nameLone Ranger>>> p.name = "Zoro"builtins.AttributeError: can't set attribute

Only One Constructor

Python classes can only have one __init__.

You can overload it using params with default values.

class Point:

'''Point with x,y coordinates'''

def __init__(self, x=0, y=0):

self.x = x

self.y = y

>>> p = Point(3,4)

>>> q = Point( ) # same as Point(0,0)

Static Methods

To define a static method, prefix with @staticmethod and no self parameter.

class Point:

'''create a point using polar coordinates.'''

@staticmethod

def makePoint(r,a):

return Point(r*math.cos(a), r*math.sin(a))

>>> p = Point.makePoint( 10, math.pi/4 )

Static factory methods can help overcome limitation of only one constructor.

Properties

Properties are like synthetic attributes. Used like "get" properties in C#. Only parameter is self.

class Point:

def __init__(self,x=0,y=0):

self.x = x

self.y = y

@property

def length(self):

return math.hypot(self.x, self.y)

>>> p = Point(3,4)

>>> p.length

5

"Set" properties

Can use @property and @x.setter to protect attributes.

class Person:

def __init__(self,name):

self.__name = name # hide the name

@property

def name(self): # name accessor

return self.__name

@name.setter

def name(self,value): # set the name

if not isinstnace(value, str):

raise TypeError("Name must be str")

self.__name = value

Restricting Keys in the Object dict

You can restrict the allowed attribute names. Use a tuple named __slots__

class Point:

__slots__ = ('x','y','name')

f.name = "weak, weak"

def __init__(x=0,y=0):

self.x, self.y = x, y

>>> p = Point(2,3)

>>> p.junk = "ha ha"

builtins.AttributeError: 'Point' object has no attribute 'junk'

Inheritance

Subclass must invoke parent's constructor explicitly

class Square(Rectangle):

def __init__(self, width):

Rectangle.__init__(self, width, width)

>>> s = Square(100)

>>> s.area()

10000

accessing superclass

Python 3 has a super() method to access superclass.

class Square(Rectangle):

def __init__(self, width):

super().__init__( width, width)

>>> s = Square(100)

>>> s.area()

10000

Polymorphism

All methods are virtual

import math

class Circle(object):def __init__(self, radius):

self.radius = radius

def area(self):return math.pi*self.radius*self.radius

>>> shapes = [Square(5), Rect(2,8), Circle(3)]>>> for x in shapes:... print x.area()251628.2743338823

Operator Overloading

Objects can implement infix operators by defining specialy named methods, such as __add__ operators: +, -, *, /, **, &, ^, ~, !=

class Point:

def __init__(self, x, y):

this.x, this.y = x, y

def __add__(self, other):

return Point(self.x+other.x, self.y+other.y);

>>> a = Point(1,2)

>>> b = Point(3,7)

>>> print(a + b) # invokes Point.__add__(a,b)

(4, 9) # assuming we also define Point.__str__

Python Object Hooks

Objects can support built-in operators by implementing special methods operators: +, -, *, /, **, &, ^, ~, != Indexing (like sequences): obj[idx] Calling (like functions): obj(args,...)

Iteration and containment tests

for item in obj: ...

if item in obj: ...

Object Data is Stored as a Dictionary

Attributes are stored in a dictionary (__dict__). You can add attributes to existing object!

f.name = value invokes f.__setattr__("name",value)

del f.name invokes f.__delattr__("name")

f = Fraction(2,3)

f.name = "weak, weak"

f.__dict__

{'num': 2, 'denom':3, 'name':'weak, weak'}

Testing object type

Get the type of a variable:

Test the type using isinstance:

>>> p = Point( 1, 3)

>>> type(p)

<class '__main__.Point'>

>>> p = Point( 1, 3)

>>> isinstance(p, Point)

True

>>> isinstance(p, float)

False

Functional Programming

• In Function Programming, functions can be used in the same way as other data types.

• Python borrows from functional languages:

Lisp/Scheme

Haskell

• Python built-in functions for functional style:

map()

filter()

reduce()

zip()

Functional Approaches

result = map(func, list)

- func is applied to each element of the list

- result is a new list, same length as original list

- the original list is not altered

map: "Apply to all" operation

>>> list = [2, 3, 4, 5]

>>> roots = map( math.sqrt, list )

>>> for x in roots:

print(x)

1.41421356237

1.73205080757

2.0

2.2360679775

Function as argument.

map in Action

func

y1 y2 y3 y4 y5 y6 y7 y8

ŷ1

func

y1 y2 y3 y4 y5 y6 y7 y8

ŷ2ŷ1

map in Action

func

y1 y2 y3 y4 y5 y6 y7 y8

ŷ3ŷ1 ŷ2

map in Action

func

y1 y2 y3 y4 y5 y6 y7 y8

ŷ4ŷ1 ŷ2 ŷ3

map in Action

func

y1 y2 y3 y4 y5 y6 y7 y8

ŷ8ŷ1 ŷ2 ŷ3 ŷ4 ŷ5 ŷ6 ŷ7

map in Action

What if the function requires more than one argument?

result = map(func, list1, ..., listn)

All lists must be of same length (not really)

Number of lists (n) must match #args needed by func

map with multiple lists

# powers of 2

pows = map( math.pow, [2]*5, [1,2,3,4,5] )

# same thing, using a range

pows = map( math.pow, [2]*5, range(1,6) )

Use map to reduce coding

lst1 = [0, 1, 2, 3]

lst2 = [4, 5, 6, 7]

lst3 = []

for k in range(len(lst1)):

lst3.append( add2(lst1[k],lst2[k]) )

lst1 = [0, 1, 2, 3]

lst2 = [4, 5, 6, 7]

lst3 = map(add2, lst1, lst2)

The map function can be used like an expression

Can be used as a parameter to a function

Benefits

>>> lst1 = [1, 2, 3, 4]

>>> string.join(lst1) # Error: lst1 contains ints

TypeError: sequence item 0: expected string, int found

>>> string.join( map(str, lst1) ) # Correct

'1 2 3 4'

sublist = filter(func, list)

return a sublist from list containing only elements that "pass" func (func returns True or non-zero for element)

the result has length less than or equal to the list

list is not altered

filter elements of a list

def isEven(x):

return x%2 == 0

lst = [2, 7, 9, 8, -12, 11]

even = filter(isEven, lst) # even = [2, 8, -12]

result = reduce(func, list)

Apply func cumulatively to a sequence

func must take 2 parameters

For each element in list, previous func result is used as 1st arg.

reduce accumulate a result

def multiply(x, y):

return x*y

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

result = reduce(multiply, lst) # result = 1*2*3*4*5

reduce(func, initial_value, list)

Use initial_value as parameter in first call to func

reduce with initial value

lst = [2,3,4,5]

result = reduce(multiply, 10, lst)

# result = 10 * 2 * 3 * 4 * 5

Code Comparison

lst1 = [ [2, 4], [5, 9], [1, 7] ]

result = operator.add([100], lst1[0])

for element in lst1[1:]:

result = operator.add(sum, element)

lst1 = [ [2, 4], [5, 9], [1, 7] ]

result = reduce(operator.add, lst1, [100])

zip(list1, …, listn)

Example: Combine two lists

>>> lst1 = [1, 2, 3, 4]

>>> lst2 = ['a', 'b', 'c', 'd', 'e']

>>> result = zip(lst1, lst2)

>>> result

[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]

The ‘e’ element was truncated since lst1 only has 4 elements

The result is a list of tuples

Join lists element-by-element

• Create a dictionary using zip() and dict()

>>> produce = ['apples', 'oranges', 'pears']

>>> prices = [0.50, 0.45, 0.55]

>>> priceDict = dict(zip(produce, prices))

>>> print priceDict

{'pears': 0.55, 'apples': 0.5, 'oranges': 0.45}

Uses for zip

Anonymous functions. Can be used assigned to variable.

Syntax : lambda p1[,…,pn]: expression

- expression should not use return

Example: create a square function

>>> sqr = lambda x: x*x

>>> print sqr(5)

25

Example: average of 2 values>>> avg = lambda x,y: (x+y)/2

>>> avg(2,7)

4.5

Lambda Functions

Lambda's can be return values or function arguments.

Function can return a Lambda

# define a power function: only x is "bound" to the lambda

define power(n):

return lambda x: math.pow(x, n)

cube = power(3)

cube(10)

1000.0

list( map( cube, range(1,10) ) )

[1.0, 8.0, 27.0, ..., 729.0]

Generator and Iterators

Any function that uses yield is a generator.

The return value is a generator type.

def fibonacci(max):

'''compute all fibonacci numbers < max'''

a, b = 0, 1

while b < max:

yield b # the next() result

a, b = b, a+b

>>> f = fibonacci(100)

>>> f

<generator object fibonacci at 0x00E52210>

Using Generator as Iterator

Each call to f.__next__( ) gets next return value.

>>> f = fibonacci(100)

>>> f.__next__( )

1

>>> f.__next__( )

1

>>> f.__next__( )

2

>>> f.__next__( )

3

Using Generator in context

Generators can be used in loops and as list generators

for x in fibonacci(40):print( x )

112358132134

lst = list(fibonacci(40))[1,1,2,3,5,8,13,21,34]

Infinite Series

Lazily generate values in a series.

import Fraction

def harmonic():

'''return elements of harmonic series'''

n = 1

while True:

yield Fraction(1,n) # the next() result

n = n + 1

# Print harmonic series until the sum > 5

sum = Fraction(0)

for f in harmonic():

Iterators

Iterators implement the Iterator pattern.

In Python, no "hasNext" method.

obj.__iter__() returns an iterator (usually self)

obj.__next__() returns next item. Raise a

StopIteration exception if no next

Note: in Python 2.x, __next__() was named next()

References

Python Documentation

http://docs.python.org

Videos

Python for Programmers by Alex Martelli

http://video.google.com/videoplay?docid=1135114630744003385

Advanced Python (Understanding Python) by Thomas Woutershttp://video.google.com/videoplay?docid=7760178035196894549

References

Books

Practical Programming: an Introduction ... by Jennifer Campbell, et al. (Pragmatic Programmers, 2009)

Good book for novice programmer.

Python Essential Reference, 4E. (Addison Wesley)

Recommended by CPE/SKE students. Has tutorial and language description. More than just a reference.

Exercise

Write a Python program freq.py to: Fetch a text file from the web Report the most frequently used words in file

$ python freq.py http://www.cpe.ku.ac.th/~cpj/gpl.txt 345: the 221: of 192: to 184: a 151: or 128: you 102: license 98: and 97: work 91: that$

Exercise Hints

Accessing command-line arguments

Read a webpage - don't do this, use an iterator

Extracting all English words from text

import urllibcontents = urllib.openurl(url).readlines()

import sysurl = sys.argv[1]

import rewords = re.findall('[A-Za-z]+', text)