Skip to content

12/4

Reminders

Avoiding Argument Modification

Some of the functions from PA3 take collections as arguments and include the requirement that the arguments must not be modified. For example, the wording from the json_to_catalog docstring is: "This will return an exact copy of the provided dictionary except for the following:" It does not say "this will modify the provided dictionary".

Here is an example function that illustrates the issue:

def all_upper(words):
    """Return a list with all words converted to upper-case.

    The provided list will not be modified.

    Args:
        words (list): A list of strings

    Returns:
        list: A list of upper-case strings

    """
    for i in range(len(words)):
        words[i] = words[i].upper()
    return words

if __name__ == "__main__":
    some_words = ["tree", "house"]
    up_words = all_upper(some_words)
    print(some_words)
    print(up_words)

When this code is executed, the output is:

['TREE', 'HOUSE']
['TREE', 'HOUSE']

This is bad! The provided argument, some_words should not have been modified.

We might try to fix it like this:

def all_upper(words):
    """Return a list with all words converted to upper-case.

    The provided list will not be modified.

    Args:
        words (list): A list of strings

    Returns:
        list: A list of upper-case strings

    """
    words_copy = words  # This doesn't actually make a copy! We just have
                        # two names for the exact same list.
    for i in range(len(words)):
        words_copy[i] = words[i].upper()
    return words_copy

if __name__ == "__main__":
    some_words = ["tree", "house"]
    up_words = all_upper(some_words)
    print(some_words)
    print(up_words)

This doesn't help at all. Instead, we need to make a new list object that has the desired contents:

def all_upper(words):
    """Return a list with all words converted to upper-case.

    The provided list will not be modified.

    Args:
        words (list): A list of strings

    Returns:
        list: A list of upper-case strings

    """
    result = []
    for word in words:
        result.append(word.upper())
    return result

if __name__ == "__main__":
    some_words = ["tree", "house"]
    up_words = all_upper(some_words)
    print(some_words)
    print(up_words)

This works. Now we'll see:

['tree', 'house']
['TREE', 'HOUSE']

Recursion Practice

Complete the following function so that it conforms to the docstring:

from pathlib import Path

def all_files(path):
    """Return the file names of all files that can found under the provided path.

    Directory names are not included.  This includes all files stored in the provided
    directory, plus all of the files in any directories contained in that directory,
    and so on. If the argument is itself a path to a file, then that filename will
    be returned

    Args:
        path (str or Path object): the starting path

    Returns:
        list: A list of string filenames.

    """
    p = Path(path)  # First convert the file/directory name to a Path object.
                    # Nothing bad happens if path was already a Path object.

    # Useful methods:
    # p.is_dir() -- True if p is a directory, false if it is a file.
    # p.name -- The name of a file
    # p.iterdir() -- All of the entries in the directory p (files and directories).

if __name__ == "__main__":
    print(all_files("."))

Quiz Practice

Two Practice Canvas Quizzes: