UNB/ CS/ David Bremner/ teaching/ cs2613/ labs/ CS2613 Lab 17

Background

Globbing and List comprehensions

Time
25 minutes
Activity
Small groups

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/L17/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
25 minutes
Activity
Small groups

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

{ key: val for ...}

Create a file ~/fcshome/cs2613/labs/L17/list2dict.py with a function list2dict that transforms a list into a dictionary (similar to the Racket function list->hash in the midterm). Your function should return a dictionary comprehension and pass the following tests. One approach uses the python builtin range

#!/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
Small groups

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-impliment the function drop-divisible from A1. Notice that the implimentation of sieve_with is not suitable for a list comprehension because of the update of lst on every iteration (in the Racket original this was done by tail recursion).

#!/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 implimentation 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
Small groups

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)