Due at 9:00pm on 02/03/2019.

Starter Files

Download lab01.zip. Inside the archive, you will find starter files for the questions in this lab, along with a copy of the OK autograder.

Submission

By the end of this lab, you should have submitted the lab with python3 ok --submit. You may submit more than once before the deadline; only the final submission will be graded. Check that you have successfully submitted your code on okpy.org. See this article for more instructions on okpy and submitting assignments.

  • To receive full credit for this lab, all questions must be attempted.

When you are ready to submit, run ok with the --submit option:

python3 ok --submit

After submitting, ok will display a submission URL, with which you can view your submission on okpy.org.

Setting up Okpy

Please navigate to this website and follow the instruction on there to set up okpy. Note: we follow the 61a procedure, so it's a link page from 61a. Steps are the same though.

Running Python Basics

Open up your terminal on your local computer. For Windows, use gitbash.

In your terminal window, you can run Python using the command below. We will be using the default version of Python 3.6.

  python3

You should see something like

  Python 3.6.5 (default, Apr  1 2018, 05:46:30)
  [GCC 7.3.0] on linux
  Type "help", "copyright", "credits" or "license" for more information.
  >>>

The '>>>' is the prompt. If you type an python expression, it will evaluate it and print the answer. Since you have already seen cells in a jupyter notebook, you may think of this as a super duper cell. (Well, actually its the other way around - the shell came first.) Type some expressions at it and see what it does.

  >>> 2016
  2016
  >>> 2016+1
  2017
  >>> 2016*2
  4032

To exit, type exit() into the interpreter prompt. You can also use the keyboard shortcut Ctrl-D on Linux/Mac machines or Ctrl-Z Enter on Windows.

  >>> exit() 

However, what happens if you want to save your code? Notice that if you start another session of Python interpreter after exiting, all the code you typed in the previous interpreter session will disappear. This is where text editors come in—text editors allow you to write a piece of code and save it, so you can revisit it for the future. A text editor creates a file—in order to run Python code written in text editors, you have to save it as a python file, by adding a “.py” extension.

To run the code on a .py file, type

  python3 [filename.py]

Make sure you are in the folder that actually contains the file. For example, try running the command python3 lab01.py from your lab01 folder, or directory. What happened?

Nothing much. That's because the command runs the file and automatically exits the intepreter. To interact with the file and all its variable and functions, add a "-i", for interactive mode after python.

   python3 -i [filename.py]

Now, you can see that you remain in the Python intepreter and can access any variable or function defined in the particular file.

Again, use exit() to exit out of the interpreter.

Be sure that you are running python 3. On macs you may need to run python3.

Data Types

Use you python interpreter to try out each of the steps that you see in this lab.

We talked about data types and expressions in class.

A data type is a specific type of value, and by knowing a value’s data type we know what operations we can perform on them. In Python, there are several common data types:

  • Strings: represented by quotation marks (“ “) around certain text. For example, “hello”, “abc”, “?.!”#$$” are all strings
  • integers: whole numbers. For example, 1, 3, 10000 are all integers
  • floats: all real numbers with a decimal point. For example, 2.0, 3.14159, 9.88 are all floats
  • booleans: True or False value.

In Python, you can find out the data type of a specific value by using type([value]). Try typing into your Python interpreter this piece of code: type(“123”). What was shown? Why?

Let’s go into the details of each one and see what operations we can use for each data type. Before that, a quick note on assigning values to a variable. In Python, a value is assigned to a variable by a “=” sign. For example:

>>> x = 2
>>> y = "hello Friday"
>>> type(y)      # What would this return? 
<class 'str'>

A “=” sign is different from a “==” sign. The “==” sign checks for equality and will return a boolean. For example, if you type in 2==3 into the Python Interpreter, this will return a False. 2 is not equal to 3.
Equality should never be confused with assignment. To assign a value to a variable we use =:

>>> 2 = 3
SyntaxError: can't assign to literal
>>> two
NameError: name 'two' is not defined
>>> two = 2
>>> two
2
>>> two == 2
True
>>> two = 3     # don't let the name confuse you
>>> two
3
>>> two == 2
False
>>> x = 2 == 3  # This assigns a value to x.  Which?
>>> x
False

Please notice that the results above depended on the sequence of operations. We assigned the value 2 to the variable named two and then we later assigned the value 3 to this same variable.

We also have logic operators on booleans: and, or, and not:

>>> x = 2
>>> x > 1 or x != 0
True
>>> x == 2 and 3 > 4
False
>>> not x < 3
False

Python also has some handy operators that make expressions read more like prose:

>>> 2 is 1
False
>>> 2 is not 1
True

Develop your understanding of Expressions

Like getting to Carnegie Hall, becoming proficient in programming takes practice. The start of this assignment is intended to give you practice working with values and expressions while pointing out some of the subtleties that are good to have tucked away in your brain somewhere.

Please note that while those of you with some programming experience may find this to be a rather basic review, others may find it completely new. Either way, bear with us; we want everyone to have the basics.

Primitive expressions

A primitive expression requires only a single evaluation step: use the literal value directly. For example, numbers, names, and strings are all primitive expressions.

>>> 2
2
>>> 'Hello World!'
'Hello World!'

Arithmetic operations on integers

>>> 5 + 3
8
>>> 5 - 3
2
>>> 5 * 3  # comments look like this
15
>>> -47  # unary minus
-47
>>> 2 ** 3 # exponentiation
8

All of these operators took integers as inputs and produced integers as outputs. There are other operators that take integers as inputs and produce other data types, such as booleans or decimal numbers (called floats), as outputs.

>>> 2 == 1
False
>>> 5 - 3 == 2
True
>>> 5 / 3  # will this produce an integer?
1.6666666666666667
>>> 5 // 3 # here's another kind of division that has an integer result
1
>>> 5 % 3  # what's this crazy looking operation?
2

Floats and precedence

Floating point numbers (floats) behave a lot like real numbers. You can identify a float by the decimal point. All floats have decimal points. To write a floating point number (as a literal) you must add a decimal point!

>>> 3.141592
3.141592
>>> 2*3.141592 # you can mix ints and floats 
6.283184
>>> pie = 3.141592 # you can assign values to variables
>>> pie
3.141592
>>> pie/pie
1.0
>>> pie/pie == 1 # a float can be equal in value to an int
True
>>> from math import pi   # here is a better pi
>>> pi
3.141592653589793
>>> 5.0/3.0  # this is division of floats, not ints
1.6666666666666667
>>> 2**(1/2) # square root - isn't that transcendental?
1.4142135623730951

Expressions follow operator precedence (just like in math). Operations are performed one at a time in a specific order. Parenthesis are used to specify order (again, just like in math - remember PEMDAS?).

>>> 2 + 3 - 4 + 5   # equal precedence, left to right
6
>>> 2 + 3 - (4 + 5) # order matters - parentheses are your friend
-4
>>> (((2 + 3) - 4) + 5) # explicit order of the first example
6
>>> 2 + 3 * 4   # * and / bind more tightly than + or - 
14
>>> 2 + (3 * 4) 
14
>>> (2 + 3) * 4  
20
>>> 2 + 3 / 4 * 5  # what about * and / ?
5.75

An expression can have multiple return values, called a tuple:

>>> 2, 3
(2, 3)
>>> x, y = 1, pi
>>> y
3.141592653589793

Simple expressions

Question 1: What would Python print?

Use OK to test your knowledge with the some "What Would Python Print?" questions:

python3 ok -q primitive-expressions -u

Note: If you think any of the expressions would cause Python to throw an error, type "Error" (without quotes) when prompted.

>>> 3
______
3
>>> 2 + 3
______
5
>>> -16 - -16
______
0
>>> 3 * 4 + 1
______
13
>>> 3 * (4 + 1)
______
15
>>> 2 ** 3
______
8

Now let's try using variables:

>>> x = 4
>>> 3 + x
______
7
>>> x + y
______
Error
>>> x, y = 1, 2 >>> 3 + x
______
4
>>> x + y
______
3

Operations on Strings

It is very useful to be able to write programs that operate on strings, not just numbers. Without strings, web browsers and word processors would be like the matrix! Just as with ints, floats, and booleans, strings are a data type and have certain operators defined on them:

>>> 'cal'           # a string literal is a sequence of characters in quotes
'cal'
>>> "rocks"         # either kind of quote, but they need to match
'rocks'
>>> "cal" + "rocks"   # + is concatenation
'calrocks'
>>> 'cal' * 3         # * is replication
'calcalcal'
>>> 'cal' == "cal"  # equality is if they are the same string (notice the single and double quotes)
True
>>> 'Cal' == 'cal'  # case sensitive
False
>>> 'Cal' < 'cal'   # lexicographic ordering, with upper before lower case
True
>>> 'you' is not 'me'
True

Operations on Booleans

Like "==", which checks for equality, we can also use "not equal", "less than", "less than or equal", etc.:

>>> 2 == 3
False
>>> 2 != 3
True
>>> 2 < 2
False
>>> 2 <= 2
True

We also have logic operators on booleans: and, or, and not:

>>> x = 2
>>> x > 1 or x != 0
True
>>> x == 2 and 3 > 4
False
>>> not x < 3
False

and returns True when both conditions are True, whereas or returns True as long as one condition is True.

Something interesting in Python is that all values are assigned a True or False value—0, empty strings, False, None, and all other empty items (empty lists, empty tuples, etc.) are 'False', whereas everything else is 'True'.

There is a concept of 'short-circuiting' in evaluating logic operators on booleans. The idea is that we don't want to do unnecessary evaluations. For example, in andstatements, if the first value proves to be False, we don't have to evaluate the second value—we know that the whole statement will return False either way. In or statements, however, it's the opposite—if the first value evaluates to True, we don't have to evaluate the second value, because we know that the whole statement will return True regardless of what the second statement is.

Python also has some handy operators that make expressions read more like prose:

>>> 2 is 1
False
>>> 2 is not 1
True
>>> "you" is not "me"
True

Call expressions

A call expression applies a function, which may or may not accept arguments. The call expression evaluates to the function's return value. It has a familiar notation borrowed from Math.

The syntax of a function call:

  add   (    2   ,    3   )
   |         |        |
operator  operand  operand

Every call expression requires a set of parentheses delimiting its comma-separated operands.

To evaluate a function call:

  1. Evaluate the operator
  2. Evaluate the operands (from left to right).
  3. Apply the operator to the operands (the values of the operands).

If an operand is a nested call expression, then these two steps are applied to that operand in order to evaluate it.

To get ahold of the basic operators, import them with this magic incantation: from operator import *. Type add. What is it? How about add(2,3)?

Try out some of the basic arithmetic functions. Some that you met in data8. Others that come to mind.

Question 2: What Would Python Print?

Let's import the functions that correspond to the arithmetic operators you are already familiar with. (You can learn more here.) Don't worry too much about the import statement just yet. The fancy sounding idea is that these functions have names that reside in a namespace outside of our own. We can bring those names into our local namespace using an import statement.

Use OK to test your knowledge with the some "What Would Python Print?" questions:

python3 ok -q call-expressions -u
>>> from operator import mul, add
>>> mul(3, 4)
______
12
>>> mul(3, add(4, 1))
______
15
>>> pow(2, 3)
______
8
>>> pow(pow(2, 3), abs(-2))
______
64
>>> from math import sqrt
>>> sqrt(144)
______
12.0
>>> pi
______
Error
>>> from math import pi >>> pi
______
3.141592653589793
>>> print(add(9, 1))
______
10
>>> print(print(2))
______
2 None

Now take a look at the following examples. Make sure you understand them before moving on!

>>> def welcome():
...     print('welcome to')
...     return 'hello'
...
>>> def cs88():
...     print('cs88')
...     return 'world'
...
>>> print(welcome(), cs88())
______
welcome to cs88 hello world
>>> from operator import add
>>> def double(x):
...     return x + x
...
>>> def square(y):
...     return y * y
...
>>> def f(z):
...     add(square(double(z)), 1)
...
>>> f(4)
______
# Nothing shows up because the return value is None. # How do you fix this?

Questions

Question 3: Temperature Converter

Define temperature_converter, which takes a temperature in Fahrenheit f_temp and returns the same temperature in Celsius.

The equation for converting from Fahrenheit to Celsius is:

  1. Temperature in Fahrenheit minus 32
  2. Times 5
  3. Divided by 9

Below we have provided an outline of the function. The example in the """ ... """ block shows how it is supposed to work. We will learn more about defining functions next week. You job is to replace the expression in the assignment statement to compute the correct conversion.

def temperature_converter(f_temp):
    """
    >>> temperature_converter(32)
    0.0
    """
    # BEGIN SOLUTION
    celsius_temp = "replace this"
    # END SOLUTION
    return celsius_temp

Use OK to test your code:

python3 ok -q temperature_converter

Question 4: Pythagorean Triple

Try this one on your local computer if you haven't already. Open up the lab01.py file in sublime (or the text editor of your choice), and fill in the solution there. Then, run the file using your local terminal.

Define pythagorean_triple, which takes a three numbers, a, b, and c and returns True if and only if these numbers form a Pythagorean Triplet, ie., the sum of the squares of the first two is equal to the square of the last.

def pythagorean_triple(a,b,c):
    """
    >>> pythagorean_triple(3,4,5)
    True
    >>> pythagorean_triple(3,4,6)
    False
    """
    # BEGIN SOLUTION
    return "Replace this"
    # END SOLUTION

Use OK to test your code:

python3 ok -q pythagorean_triple