Top Banner
CSC 310 – Procedural Programming Languages, Spring, 2009 Chapters 7 and 8: Python Data Types, Subroutines and Control Abstraction
34

CSC 310 – Procedural Programming Languages, Spring, 2009

Jan 08, 2016

Download

Documents

buitan buitan

CSC 310 – Procedural Programming Languages, Spring, 2009. Chapters 7 and 8: Python Data Types, Subroutines and Control Abstraction. Definition of Types. Denotational type system A type is a set of possible values. Constructive – type system is a union of: - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: CSC 310 – Procedural Programming Languages, Spring, 2009

CSC 310 – Procedural Programming Languages, Spring, 2009

Chapters 7 and 8: Python Data Types, Subroutines and Control Abstraction

Page 2: CSC 310 – Procedural Programming Languages, Spring, 2009

Definition of Types

• Denotational type system– A type is a set of possible values.

• Constructive – type system is a union of:– Built-in (primitive or predefined) types;– Composite, constructed types.

• Abstraction-based– Interface consisting of a set of constants and

operations

Page 3: CSC 310 – Procedural Programming Languages, Spring, 2009

Python’s Dynamic Type System

• Python uses dynamic typing. There is no type for parameters, variables and fields. Each value has a type tag.>>> a = 3>>> type(a)<type 'int'>>>> a = 3.0>>> type(a)<type 'float'>>>> a = 'this is a string‘>>> type(a)<type 'str'>

Page 4: CSC 310 – Procedural Programming Languages, Spring, 2009

Types are run-time values

• Compare types for equality.>>> type(a) == str # Some built-in types have built-in names.True>>> import types # See 'types' module in PY Ch. 13>>> type(a) == types.StringType # all built-in object typesTrue>>> t = type(type(a))>>> t<type 'type'>>>> type(t)<type 'type'>

Page 5: CSC 310 – Procedural Programming Languages, Spring, 2009

Dynamic versus static type checking Weak versus strong type checking

• Python is dynamically and strongly typed.– A value (a.k.a. object) carries a type tag.– Values must be type compatible within

operations.

• The source-to-bytecode compiler checks syntax, but it does not check type.

• Lack of static type checking puts a heavier burden on testing to verify type compatibility.

Page 6: CSC 310 – Procedural Programming Languages, Spring, 2009

Type equivalence

• Structural equivalence compares the composite construction of two types.

• Name equivalence is based on lexical occurrence of type definitions. Python uses name equivalence.>>> type(3)<type 'int'>>>> type(3) == type(4)True>>> from types import *>>> type(3) == IntTypeTrue

Page 7: CSC 310 – Procedural Programming Languages, Spring, 2009

Aliased types

• Some languages have strict name equivalence for aliased types. Each name is a distinct type.

• Python has loose name equivalence, because what matters is the type’s value.

>>> int<type 'int'>>>> mytype = int>>> mytype == intTrue>>> mytype(3.7)3>>> mytype("5")5

Page 8: CSC 310 – Procedural Programming Languages, Spring, 2009

Explicit type conversion

• Conversion uses a type name to cast a value from one type to another.>>> i = 3>>> type(i)<type 'int'>>>> i = float(i)>>> type(i)<type 'float'>

Page 9: CSC 310 – Procedural Programming Languages, Spring, 2009

Implicit type coercion

• Mixed type arithmetic promotes to float.>>> value = 3 + 4 * 2.0>>> value11.0Integer overflow promotes to extended precision

long.>>> i = 1 << 30 ; i1073741824>>> i = i << 1 ; i2147483648L

Page 10: CSC 310 – Procedural Programming Languages, Spring, 2009

Most conversions are explicit

• Most conversions must be explicit type casts>>> value = 3.0 + ' units'Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: unsupported operand type(s) for +: 'float' and 'str'>>> value = str(3.0) + ' units' ; value'3.0 units'>>> value = 3.0 + float("-4.5") ; value-1.5

Page 11: CSC 310 – Procedural Programming Languages, Spring, 2009

No C-like non-converting types casts

• C/C++ supports non-converting casts float fval = 1.3125 ; int ival = *((int *) &fval); printf("float value %f gives bit pattern 0x%x\n", fval, ival);float value 1.312500 gives bit pattern 0x3fa80000

• Python’s struct module can convert to a bit pattern format, then back to Python.from struct import pack, unpack>>> '%x' % (unpack('i', pack('f', 1.3125))[0])'3fa80000'

Page 12: CSC 310 – Procedural Programming Languages, Spring, 2009

Polymorphism

• A single body of code works with objects of multiple types.• Implicit parametric polymorphism in Python.

>>> def summer(termlist):... mysum = termlist[0]... for term in termlist[1:]:... mysum = mysum + term... return mysum...>>> summer([3, 5, 7])15>>> summer(('cat ', 'dog ', 'beaver '))'cat dog beaver '

Page 13: CSC 310 – Procedural Programming Languages, Spring, 2009

Abstraction-based types

• Python type compatibility is determined largely by the operators that combine values.

• Subtype polymorphism takes the form of related derived classes with alternative method definitions. The methods determine type compatibility.

• Operator overloading and make methods look syntactically like operators.

Page 14: CSC 310 – Procedural Programming Languages, Spring, 2009

Subtype polymorphism in Python>>> class baseclass(object):... def f(self, param):... raise Exception, "not implemented">>> class derived1(baseclass):... def f(self, param):... return int(param)>>> class derived2(baseclass):... def f(self, param):... return float(param)>>> d1 = derived1() ; d2 = derived2()>>> d1.f(3) RETURNS 3>>> d2.f(3) RETURNS 3.0>>> d1.f(-3.2) RETURNS -3>>> d2.f(-3.2) RETURNS -3.2000000000000002

Page 15: CSC 310 – Procedural Programming Languages, Spring, 2009

Additional explicit type check operations for objects

>>> baseclass<class '__main__.baseclass'>>>> derived1<class '__main__.derived1'>>>> type(derived1)<type 'type'>>>> type(int)<type 'type'>>>> isinstance<built-in function isinstance>>>> isinstance(d1, baseclass)True

>>> isinstance(d1, derived1)True>>> isinstance(d1, derived2)False>>> issubclass(derived1,

baseclass)True>>> issubclass(derived1,

derived1)True>>> issubclass(derived1,

derived2)False

Page 16: CSC 310 – Procedural Programming Languages, Spring, 2009

Python composite types• Strings are a built-in type with extensive support.• List type supports heterogeneous sequences.

• >>> l = [1, 'a', None] ; print l• [1, 'a', None]

• Tuple acts like an immutable list.• >>> t = (1, 'a', None, l) ; print t• (1, 'a', None, [1, 'a', None])

• Dictionary is a mapping. Key is immutable.• >>> d = {'a' : 1, 'b' : 2} ; print d['b']• 2

• Set or frozenset is an unordered collection.• >>> s = set([1, 'a', None]) ; print s• set(['a', 1, None])

Page 17: CSC 310 – Procedural Programming Languages, Spring, 2009

No support for explicit parametric polymorphism

• No C++ or Java-like “list of int” generic types.• >>> print type(l) ; print type(t) ; print type(d) ; print

type(s)• <type 'list'>• <type 'tuple'>• <type 'dict'>• <type 'set'>

• A Python container can hold a mix of types.

Page 18: CSC 310 – Procedural Programming Languages, Spring, 2009

Missing types

• No standard array type.• List indexing is similar to arrays.• Module array (PY 15) stores primitive type objects.

• No subranges or enumeration types.• No fixed or variant contiguous records.

• No struct or union as in C/C++.

• Class objects can be used as records.• No private, etc. access protection on fields.• __field__ naming convention denotes private.

• Programmers can create their own types via the C/C++ or Java (for Jython) extension APIs.

Page 19: CSC 310 – Procedural Programming Languages, Spring, 2009

Class objects as records

• >>> r = record() • print r.a ; r.b = "a value" ; print r.b

• None• a value

• Methods use self.a or self.b to access fields.• Parameter self is an explicit, first parameter to

object methods.• Equivalent to this in C++ or Java.

Page 20: CSC 310 – Procedural Programming Languages, Spring, 2009

Values and References

• Python uses values for primitives, references for composite types.

• Every datum is an object.• >>> from copy import copy, deepcopy ;

print l• [1, 'a', None]• >>> l2 = l• >>> l3 = copy(l) # shallow copy• >>> l4 = deepcopy(l)• >>> l2 == l• True

>>> l3 == lTrue>>> l4 == lTrue>>> l2 is lTrue>>> l3 is lFalse>>> l4 is lFalse

Page 21: CSC 310 – Procedural Programming Languages, Spring, 2009

Pointers and Recursive Types

• Object references are notational.• There are no explicit pointers. A reference is a pointer.• >>> l• [1, 'a', None]• >>> l.append(l)• >>> l• [1, 'a', None, [...]]• >>> l[3] == l• True• >>> l[3] is l• True• >>> l[3][3][3][3] is l• True

Page 22: CSC 310 – Procedural Programming Languages, Spring, 2009

Binary tree in a list>>> t = []>>> def insert_into_binary_tree(tree, value):... if (not tree): # 'null pointer' beyond a leaf... tree.extend([value, [], []])... return tree... elif (tree[0] == value):... return tree... elif (value < tree[0]):... return(insert_into_binary_tree(tree[1],

value))... else:... return(insert_into_binary_tree(tree[2],

value))>>> insert_into_binary_tree(t, 5)>>> insert_into_binary_tree(t, 4)>>> insert_into_binary_tree(t, 1)>>> insert_into_binary_tree(t, 2)>>> insert_into_binary_tree(t, 17)>>> insert_into_binary_tree(t, -5)>>> t[5, [4, [1, [-5, [], []], [2, [], []]], []], [17, [], []]]

>>> t[5, [4, [1, [-5, [], []], [2, [], []]], []], [17, [], []]]

Page 23: CSC 310 – Procedural Programming Languages, Spring, 2009

No dangling references or uncollected objects (no garbage)

• Python uses a garbage collector.• Reference counting tracks most objects.

• Every variable binding adds a reference.

• Additional garbage collection for circular structures.

• May be mark and sweep.• May be stop and copy.• May be generational collection.• Details not specified by the language.

Page 24: CSC 310 – Procedural Programming Languages, Spring, 2009

Subroutines and Control Abstraction

• Python supports functions / procedures, object methods, generators (iterators) and closures (function + static environment).

• Primitive parameters are values.• Object parameters are references.• Immutable objects (e.g. tuples) cannot be changed.

• Functions and methods are first class objects.• Reflection supports interactive inspection of

functions.

Page 25: CSC 310 – Procedural Programming Languages, Spring, 2009

Python’s call stack

• The call stack occupies contiguous memory.• >>> from sys import getrecursionlimit,

setrecursionlimit• getrecursionlimit()• 1000

• Each stack frame points to dynamic data structures.

• Both static (lexical) and dynamic bindings resides in dynamic data structures.

Page 26: CSC 310 – Procedural Programming Languages, Spring, 2009

Parameters are values for primitives, references for objects

>>> def modl(l):... l = [1, 2, 3]... print "modl sees

" + str(l)>>> gl = [4, 5, 6]>>> modl(gl)modl sees [1, 2, 3]>>> print gl[4, 5, 6]

>>> def modelem(l):... l[1] = 111... l.append('appended string')... print "modelem sees " +

str(l)>>> gl = [4, 5, 6]>>> modelem(gl)modelem sees [4, 111, 6,

'appended string']>>> print gl[4, 111, 6, 'appended string']>>> modelem(tuple(gl))Traceback (most recent call last):TypeError: 'tuple' object does not support item

assignment

Page 27: CSC 310 – Procedural Programming Languages, Spring, 2009

A closure both sees its lexical environment and saves it as well!

>>> def outer(vala):... def inner(valb):... return vala + valb... return inner...>>> f = outer(5)>>> f<function inner at 0x9ad70>>>> f(6)11

Page 28: CSC 310 – Procedural Programming Languages, Spring, 2009

Closures in Python

>>> dir(outer)['__call__', … 'func_closure', …]>>> dir(f)['__call__', … 'func_closure', …] >>> print outer.func_closureNone>>> print f.func_closure(<cell at 0xa4430: int object at 0x668c0>,)

Page 29: CSC 310 – Procedural Programming Languages, Spring, 2009

Uncovering the static link in a closure

• >>> print f.func_closure[0]• <cell at 0xa4430: int object at 0x668c0>• >>> print type(f.func_closure[0])• <type 'cell'>• >>> dir(f.func_closure[0])• ['__class__', '__cmp__', '__delattr__', '__doc__',

'__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'cell_contents']

• >>> f.func_closure[0].cell_contents• 5

Page 30: CSC 310 – Procedural Programming Languages, Spring, 2009

Both positional and keyword parameters supported

• Positional, if any, come first in a call.• Default values come last in a definition.• >>> def sum(a, b=3):• ... return a + b• >>> sum(2)• 5• >>> sum(2,7)• 9• >>> sum(b=8, a=9)• 17• >>> sum(4, a=9)• Traceback (most recent call last):• File "<stdin>", line 1, in <module>• TypeError: sum() got multiple values for keyword argument 'a'

Page 31: CSC 310 – Procedural Programming Languages, Spring, 2009

Apply allows processes to construct function calls at run time.

>>> f = sum>>> keywordargs = {'a': 3, 'b': 4}>>> apply(f,(),keywordargs)7>>> apply(f,(7, 6), {})13>>> eval("sum(4,5)") # eval() evaluates text9

Page 32: CSC 310 – Procedural Programming Languages, Spring, 2009

Variable number of *positional and **keyword arguments

• A trailing *param is a tuple of variable-length positional parameters. A trailing **param is a dictionary of keyword parameters.

• >>> def sum(*terms):• ... mysum = terms[0]• ... for t in terms[1:]:• ... mysum += t• ... return mysum• ...• >>> sum(1, 2, 3, 4, 5)• 15

Page 33: CSC 310 – Procedural Programming Languages, Spring, 2009

Exception handling• Exceptions are class objects, similar to C++ and Java.• Finally and except clauses cannot appear in the same try

statement. Use nested try.>>> try:... i = int('dog')... except ValueError, estring:... print "exception says: " + str(estring)...exception says: invalid literal for int() with base 10: 'dog‘• Use raise to throw an exception.

Page 34: CSC 310 – Procedural Programming Languages, Spring, 2009

Generators are Pythons iterators>>> def g(start, end):... for v in range(start,end):... yield v...>>> gen = g(1,4)>>> gen.next()1>>> gen.next()2>>> gen.next()3>>> gen.next()Traceback (most recent call last): File "<stdin>", line 1, in <module>StopIteration