\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[a4paper, margin=0.75in]{geometry}

% set up hyperlink coloring
\usepackage{hyperref}
\hypersetup{
    colorlinks=true,
    linkcolor=blue,
    filecolor=magenta,
    urlcolor=cyan
}

\setlength{\parindent}{0pt} % no indentation

% checkbox list: https://tex.stackexchange.com/questions/247681/how-to-create-checkbox-todo-list
\usepackage{enumitem,amssymb}
\newlist{boxlist}{itemize}{2}
\setlist[boxlist]{label=$\square$}

% code support: listings and fancy verbatim
\usepackage{listings}
\lstset{basicstyle=\ttfamily\footnotesize}
\usepackage{fancyvrb}

\renewcommand{\familydefault}{\sfdefault} % default to sans serif

\usepackage{xcolor}
\newcommand{\code}[1]{\colorbox{lightgray}{\texttt{#1}}}
\newcommand{\sh}[1]{\code{\$ #1}}

\usepackage{graphicx}

%%%%%%%%%%%%%%%%
% python prompt macro
\newcommand{\py}[1]{\code{>{}>{}> #1}}

\begin{document}

\title{Basic 8\\Python}
\author{EECS 201 Fall 2020}
\date{}
\maketitle

\section*{Submission Instructions}
This assignment will be submitted as a repository on the \href{https://gitlab.umich.edu}{UMich GitLab server}.
Create a Project on it with the name/path \code{eecs201-basic8} and add \code{brng} as a Reporter.

\section*{Preface}
In this homework you'll be provided yet another zipped archive containing some starter files.

\begin{Verbatim}[fontsize=\footnotesize]
wget https://www.eecs.umich.edu/courses/eecs201/files/assignments/basic8.tar.gz
\end{Verbatim}

Initialize a Git repository in the extracted \code{basic8} directory.
Create a file called \code{report.txt} in this directory.
Add all of the present files and commit them.
\\\\
Create a \textbf{private} project named \code{eecs201-basic8} on the UMich GitLab (\url{gitlab.umich.edu})
and add the instructor \code{brng} as a \textbf{Reporter}.
Set this UMich GitLab project as your remote: you'll be pushing to it in order to submit.
\\\\
For this assignment you're going to need \textbf{Python 3}.
The package name for it on Ubuntu is \code{python3} (the ``normal'' \code{python} package is for Python 2.7).


\section*{Ramping up}
In this section you'll be getting familiar with forming Python expressions.
This section has no submission component and is purely for exploring
the syntax.
If you are already familiar with Python, you may skip this section.
\begin{enumerate}
  \item First we're going to work in Python's interactive shell.
        Run \sh{python3} (or \sh{python} if your system's default Python is Python 3).
  \item In the interactive shell, much like MATLAB if you have used that,
        the value of the result of an entered expression will be printed out
        (remember from lecture that expressions can be statements!).
  \item \py{ } will be used to indicate Python interactive shell prompts.
  \item Run \py{6 * 7}. This will multiply 6 with 7.
  \item Run \py{"Hello " + "world!"}. This will produce a new \code{str} that concatenates the two.
  \item Run \py{len("Hello")}. This is an example of the built-in function \code{len()} being used on a \code{str},
        which is a sequence.
  \item Messing around with types is cool, but let's now save the values we create.
  \item Run \py{x = 6 * 7}. We are now binding variable/identifier \code{x} to an \code{int} object of value 42
        (i.e. \code{x} equals 42).
  \item We can print out an object as well (provided it has implemented a \code{\_\_str\_\_} function, which
        the built-in types have).
        Run \py{print(x)}.
  \item We can get information about the object \code{x} is bound to.
        Run \py{type(x)}: this gets type of the object bound to \code{x}.
  \item Run \py{id(x)}: this gets the ID of the object bound to \code{x}.
  \item Let's use \code{x} in an expression.
        Run \py{y = x - 42}. Print out \code{y}.
  \item Run \py{z = "Hello world!"}
  \item Run \py{print(z)}. Here's our obligatory ``Hello world!''
  \item Let's now play with another built-in type: the list.
        Run \py{l = [x, y, z]}. This will construct a list using the objects bound by
        x, y, and z.
        Note how we can stuff arbitrary objects into a list!
  \item Run \py{print(l)}. As mentioned before, the built-in types can be nicely printed.
  \item A list can be indexed by an integer position: run \py{print(l[0])}
  \item Let's check if the objects referred to by \code{x} and \code{l[0]} are the same:
        run \py{x is l[0]}.
        This performs an ID check between the two objects referred to by \code{x} and \code{l[0]}
        and returns a boolean (alternatively, \py{id(x) == id(l[0])} works as well).
  \item Try verifying that \code{y} and \code{z} are the same as \code{l[1]} and \code{l[2]}.
  \item Let's manipulate this list (lists are mutable after all).
        Run \py{l.append(3.14)}. Try printing out \code{l} again.
        With \code{append()} we have added a \code{float} to list \code{l}.
  \item Lastly, let's play with dictionaries.
        Initialize an empty dictionary with \py{dictionary = \{\}}.
  \item Let's set the key-value pairs ``foo''=0 and ``bar''=1:\\
        \py{dictionary['foo']=0}\\
        \py{dictionary['bar']=1}
  \item Let's retrieve the values associated with the keys:\\
        \py{print(dictionary['foo']}\\
        \py{print(dictionary['bar']}
  \item To quit the interactive shell, run \py{quit()} or send an EOT/EOF
        by hitting Ctrl-D (\code{\^{}D})
\end{enumerate}

If you had 0 experience with Python going in, hopefully this small intro
put you more at ease: Python has a fairly simple syntax, free from a lot of cruft.
While it can serve as a scripting language, it definitely is a lot more familiar
and intuitive compared to something like Bash.

\newpage
\section{Jotting things down}
Much like Bash, we can put statements in at the interactive shell or we can
put down our statements in a script to be run at our convenience.

\begin{enumerate}
  \item Create a file named \code{loops.py}
  \item If you want to, put: \code{\#!/usr/bin/env python3}.
        This shebang will use the \code{env} executable
        to find \code{python3} and use that as the interpreter
        if you decide to execute the file directly after \code{chmod}ing it.
        I'm going to explicitly run these scripts under \code{python3}, so
        you don't actually have to do this step.
  \item In the script, \code{import} the \code{sys} module.
        This module provides info about the current interpreter,
        such as the command-line arguments.
  \item \code{sys.argv} is a list of command-line arguments provided to the script.
        Like many programming languages, the list contains the script file's name
        as the 0th argument.
  \item Add a check to see that at least one additional command-line argument was added.
        If there isn't, exit with a status code of 1 via \code{exit()}
  \item The 1st argument will serve as an integer: assign a variable to be that integer value.
        The built-in \code{int()} function is able to perform conversions of various types
        to integer.
  \item In the script, add a \code{while}-loop to \code{print()} out the integers from 1 to the
        script's command-line argument.
  \item Add a \code{for}-loop with \code{range()} to \code{print()} out the integers from 1 to the
        script's command-line argument.
  \item Try running \sh{python3 loops.py 10}.
        As a result of both loops, you should see 1 to 10
        printed out twice with each number on its own line.
\end{enumerate}


\section{``Fun'' is in ``function''}
We'll now play around with functions. Much like in Bash, functions can be
declared and then called, albeit the calling syntax is a lot more familiar.
For you folk who are used to Python, feel free to take full advantage of
some of the more Pythonic expressions for these ;)

\begin{enumerate}
  \item Create a file named \code{functions.py}.
  \item Create and implement a function called \code{lower\_list} that takes
        in a string (\code{str}) a returns a list of the string's characters that are lowercase,
        in the order that they were in from the string.
        For example, \code{lower\_list("HEllo")} returns \code{['l', 'l', 'o']}.
  \item Create and implement a function called \code{list\_to\_string\_dict} that
        takes in a \code{list} of \code{tuples} representing
        key-value pairs where the 0th element is a key and the 1st element is a value
        (beyond being an immutable sequence, tuples, like in some other languages,
        are often used to act as an object with unnamed variables).
        The function returns a \code{dict} made up of the key-value pairs in the input list
        that have \textbf{keys that are strings}.
        For example, \code{list\_to\_string\_dict([('hello', 1), ('world', 42), (1234, 5)])} would return
        a \code{dict} that is representable by \code{\{'hello':1, 'world':42\}}.
  \item You can use the provided \code{test-functions.py} file to test out your functions.
        You can also try them out in the interpreter shell :)
\end{enumerate}


\newpage
\section{Classes}
Python also is object-oriented: so much so that everything is an object.
We can define our own classes as well!
\begin{enumerate}
  \item Create a file named \code{classes.py}.
  \item Define a \code{Student} class whose instances are
        composed of the member variables \code{name}(\code{str}) and \code{grade}(\code{float}).
        The \code{\_\_init\_\_()} function should, after the object instance argument,
        have the arguments \code{name} and \code{grade} in that order.
  \item Add a method to \code{Student} called \code{passing()} that returns \code{True}
        if their \code{grade} is greater than or equal to \code{70.0} and
        \code{False} if their grade is less than \code{70.0}.
  \item There are also methods that you can define for your class that'll
        interface with some built-in functions like \code{str()}.
        For \code{str()} to work on your class, you'll have to implement
        the \code{\_\_str\_\_()} function.
        Implement it so that when you call \code{str()} on a \code{Student},
        it will return \code{<Name> - <Grade>} e.g. \code{Bob - 84}.
        Try running \code{print()} on a \code{Student} now :)\\\\
        {\footnotesize{}On a sidenote, there's also \code{\_\_repr\_\_()} for
         ``formal'' string representations of a class.
         \href{https://stackoverflow.com/questions/1436703/difference-between-str-and-repr}
              {This StackOverflow post} has a nice summary.}
  \item You can use the provided \code{test-classes.py} file to test out your functions.
        You can also try them out in the interpreter shell :)
\end{enumerate}


\section{The filesystem}
Things aren't as interesting when we can't interact with anything.
\begin{enumerate}
  \item Create a file named \code{files.py}.
  \item In this script open the file named \code{data.txt} for reading.
        Try using the \code{with...as...} mechanism.
        If you go for the plain-old \code{open()...close()} paradigm,
        don't forget to close the file at the end.
  \item Read and print out each line in the file.
        The \code{readline()} and \code{readlines()} functions
        may be helpful. Also note that you can iterate over
        a file with a \code{for}-loop.
  \item Make sure that you don't double-print newlines:
        the \code{strip()} function for \code{str}
        objects that gets rid of whitespace at the beginning
        and end of a string may help out here.
\end{enumerate}


\newpage
\section{Some extras}
This section will be more for exploring things.
No submission for these, but they're some things to keep in mind.

\subsection*{Running other commands}
There's two relatively easy ways to run some other
program or command from Python.
From the \code{os} module we have \code{os.system()},
which allows you to shell commands (i.e. the C \code{system()} function).
For example: \code{os.system("ls -ltr somedir")}.
The downside is that there isn't a way to capture the output with this.
\\\\
The \code{subprocess} module, however, has a rich set of utilities for this purpose.
The \code{subprocess.run()} function is a high level function that allows
you to run commands, capture their outputs, and check their statuses.
For example: \code{subprocess.run(['ls', '-ltr', 'somedir'], capture\_output=True)}
will run the command specified by a list of arguments as well as capturing
the output for the returned object.
The object it returns is a \code{CompletedObject} which has a
\code{stdout} attribute that is a \code{bytes} containing the output of the command.
This \code{bytes} can then be encoded (e.g. via UTF-8) to give you a \code{str}.
\\
Putting it together:\\
\code{subprocess.run(['ls', '-ltr', 'somedir'], capture\_output=True).stdout.encode('utf-8')}
\\\\
Alternatively, you can provide an encoding to \code{subprocess.run}.
Try looking at the documentation for more details :)

\subsection*{Being Pythonic with comprehensions}
A word that comes up often is ``Pythonic'': this
refers to the taking advantage of features and things
built into Python that help clean up and express ideas
that would otherwise be messier in other languages
due to some quirk of syntax.
For instance, you may be used to using an iterating
index variable in C/C++ to index into an array,
but the ``Pythonic'' way would be to just directly
iterate over it.
Sure, you could do \code{for i in range(len(somelist)):},
but unless you absolutely need an integer index for something,
why not express it as \code{for item in somelist:}?
\\\\
One of the neat features of Python that we brought up in lecture are
``comprehensions''. They allow you to easily build things like lists, sets,
and dictionaries with iterable objects.
For instance, if I wanted to get a list of the grades squared
from a list of \code{Student}s named \code{students}:\\
\code{grades = [student.grade ** 2 for student in students]}
\\\\
or maybe you want the names of students who are passing:\\
\code{passing\_students = [student.name for student in students if student.passing()]}
\\\\
Dictionaries have a similar syntax.
Perhaps you have a dictionary but want to keep only
pairs whose keys are strings:\\
\code{only\_strings = \{k:v for k,v in somedict.items() if type(k) is str\}}
\\\\
Try tackling \#2 using comprehensions!

\section{Conclusion}
\begin{enumerate}
  \item Add and commit the files you created.
  \item Fill out the \code{report.txt} file in the following steps:
  \item On the first line provide an integer time in minutes of how long it took
        for you to complete this assignment. It should just be an integer: no letters or words.
  \item On the second line and beyond, write down what you learned while doing this assignment.
        If you already knew how to do all of this, put down ``N/A''.
  \item Commit your \code{report.txt} file and push your commits to your remote.
\end{enumerate}

\end{document}
