Chapter 1.8 - Iterators

In python, the mechanism for iteration is based upon the following conventions

An iterator can be produced via the syntax i = iter(data), and then each subsquent call to next(i) will return an element of that list

Generators

The most convienient technique for creating iterators in Python is through the use of generators.

For example, a traditional functions to find factors of n would be as so:

def factors(n): # traditional function that computes factors results = [ ] # store factors in a new list for k in range(1,n+1): if n % k == 0: # divides evenly, thus k is a factor results.append(k) # add k to the list of factors return results # return the entire list

In contrast, an implementation with a generator would be as so:

def factors(n): # generator that computes factors for k in range(1,n+1): if n % k == 0: # divides evenly, thus k is a factor yield k # yield this factor as next result

Chapter 5 - Array Based Techniques

Public behaviours

Implementation Details

Asymptotic and Experimental Analyses

5.2 Low level Arrays

Primary memory:

A group of related variables can be stored one after another in a contiguous portion of a computer's memory

Alt text

We describe this as an array of six characters

Referential Arrays

Assume we want a medical information system to keep track of the patients currently assigned to beds in a certain hospital

We could consider using an array-based structure to maintain the names of the patients currently assigned to those beds.

Instead, Python represents a list or ruple instance using an internal storage mechanism as an array of object references.

Alt text

The fact that lists and tuples are referential structures is significant to the semantics of these classes.

A single list instance may include multiple references to the same object as elements of the list, and it is possible for a single object to be an element of two or more lists, as those lists simply store references back to that object.

Alt text

If, for example, the command temp[2] = 15 were executed from this configuration, that does not change the existing integer object; it changes the reference in cell 2 of the temp list to reference a different object

The same semantics is demonstrated when making a new list as a copy of an existing one.

Common practise to initialise an array of integers such as counters = [0] * 8

Alt text

Compact arrays in Python

In the introduction to this section, we emphasized that strings are represented using an array of characters (not an array of references). We will refer to this more direct representation as a compact array because the array is storing the bits that represent the primary data (characters, e.g.)

Advantages:

Dynamic arrays and amortisation

When creating a low-level array in a computer system, the precise size of that array must be explicitly declared in order for the system to properly allocate a consecutive piece of memory for its storage.

Alt text

Because the system might dedicate neighboring memory locations to store other data, the capacity of an array cannot trivially be increased by expanding into subsequent cells.

Python’s list class presents a more interesting abstraction. Although a list has a particular length when constructed, the class allows us to add elements to the list, with no apparent limit on the overall capacity of the list.

Key principles:

At that point in time, the old array is no longer needed, so it is reclaimed by the system. Intuitively, this strategy is much like that of the hermit crab, which moves into a larger shell when it outgrows its previous one.

import sys # provides getsizeof function data = [ ] for k in range(n): # NOTE: must fix choice of n a = len(data) # number of elements b = sys.getsizeof(data) # actual size in bytes print( Length: {0:3d}; Size in bytes: {1:4d} .format(a, b)) data.append(None) # increase length by one

Output is as follows:

Length: 0; Size in bytes: 72 Length: 1; Size in bytes: 104 Length: 2; Size in bytes: 104 Length: 3; Size in bytes: 104 Length: 4; Size in bytes: 104 Length: 5; Size in bytes: 136 Length: 6; Size in bytes: 136 Length: 7; Size in bytes: 136 Length: 8; Size in bytes: 136 Length: 9; Size in bytes: 200 Length: 10; Size in bytes: 200 Length: 11; Size in bytes: 200 Length: 12; Size in bytes: 200 Length: 13; Size in bytes: 200 Length: 14; Size in bytes: 200 Length: 15; Size in bytes: 200 Length: 16; Size in bytes: 200 Length: 17; Size in bytes: 272 Length: 18; Size in bytes: 272 Length: 19; Size in bytes: 272 Length: 20; Size in bytes: 272 Length: 21; Size in bytes: 272 Length: 22; Size in bytes: 272 Length: 23; Size in bytes: 272 Length: 24; Size in bytes: 272 Length: 25; Size in bytes: 272 Length: 26; Size in bytes: 352

Observations