UNB/ CS/ David Bremner/ teaching/ cs2613/ labs/ Lab 15

Before the Lab

Background


Discussion

Time
10 minutes
Activity
Discussion

Globbing and List comprehensions

Time
20 minutes
Activity
individual

List Comprehensions can be seen as a special kinds of for loops. Construct an equivalent list comprehension to the given for loop.

#!/usr/bin/python3
import glob
import os
new_dir = os.path.expanduser("~/fcshome/cs2613/labs/test")

python_files_for = []

for file in glob.glob("*.py"):
    python_files_for.append(os.path.join(new_dir,file))

python_files_comp = ____________________________________________________________

Here is a test to make sure your two constructions are really equivalent; the use of sorted is probably unneeded here, but we don't need to depend on the order returned by glob being consistent. Put the following in ~fcshome/cs2613/labs/L15/test_globex.py.

#!/usr/bin/python3
import globex

def test_for():
    assert sorted(globex.python_files_for) == sorted(globex.python_files_comp)

In fact list comprehensions are really closer to a convenient syntax for map, which you may remember from Racket and JavaScript. Python also has map and lambda, although these are considered less idiomatic than using list comprehensions. Fill in the body of the lambda (should be similar or identical to your list comprehension expression).

python_files_map = map(lambda file: __________________________, glob.glob("*.py"))

The following test should pass

def test_map():
    assert sorted(globex.python_files_comp) == sorted(globex.python_files_map)

Dictionary Comprehensions

Time
20 minutes
Activity
Individual

Dictionary Comprehensions are quite similar to list comprehensions, except that they use

{ key: val for ...}

Create a file ~/fcshome/cs2613/labs/L15/list2dict.py with a function list2dict that transforms a list into a dictionary indexed by integers. Your function should use a dictionary comprehension and pass the following tests. One approach uses the python builtin range. It may help to write it first using a for loop.

#!/usr/bin/python3

from list2dict import list2dict

def test_empty():
    assert list2dict([]) == {}

def test_abc():
    dictionary=list2dict(["a", "b", "c"])
    assert dictionary == {1: 'a', 2: 'b', 3: 'c'}

Filtered List Comprehensions

Time
25 minutes
Activity
individual

Looking at the discussion of list comprehensions, we can see that it is possible to filter the list of values used in the the list comprehension with an if clause. Use this syntax to re-implement the function drop-divisible from A1. Notice that the implementation of sieve_with is not suitable for a list comprehension because of the update of lst on every iteration (in Racket this could be done without mutation by tail recursion or for/fold). Python does have a reduce function (in the functools module), but most Python programmers will prefer the 2 line loop given here.

#!/usr/bin/python3

from math import sqrt,ceil

def drop_divisible(n,lst):
    return __________________________________

def sieve_with(candidates, lst):
    for c in candidates:
        lst=drop_divisible(c,lst)
    return lst

def sieve(n):
    return sieve_with(range(2,ceil(sqrt(n))+1), range(2,n))

Your implementation should pass the following tests.

from sieve import drop_divisible

def test_drop_divisible():
    assert drop_divisible(3, [2, 3, 4, 5, 6, 7, 8, 9, 10]) == [2, 3, 4, 5, 7, 8, 10]

def test_sieve():
    assert sieve(10)== [2, 3, 5, 7]

Using format

Time
25 minutes
Activity
individual

Like JavaScript, Python supports a simple way of constructing output using the overloaded operator +. Python also supports a more powerful format method (similar to Racket's format function) for combining values into a formatted output string. Use the format method and a list comprehension to write an equivalent value into strings_format.

import os,glob

strings_plus = []
for p in glob.glob("*.py"):
    size=os.stat(p).st_size
    strings_plus.append(p + "\t" + str(size))

strings_format = __________________________________________________

Your code should pass the following test.

import formatex

def test_equality():
    assert sorted(formatex.strings_plus) == sorted(formatex.strings_format)