Previous: 03-IntroPython.html

```
**Q**: In hexadecimal, in Canada, why is 6 afraid of 7?
**A**: Because 7, 8, 9, A?
```

- Password for the Vimeo videos is in Zulip chat.
- Lecture 1: https://vimeo.com/508153540
- Lecture 2: https://vimeo.com/508759087
- Tip: If anyone want to speed up the lecture videos a little, inspect
the page, go to the browser console, and paste this in:

`document.querySelector('video').playbackRate = 1.2`

Extra reading 1:

* https://automatetheboringstuff.com/2e/chapter0/

* https://automatetheboringstuff.com/2e/chapter1/

* https://inventwithpython.com/invent4thed/chapter0.html

* https://inventwithpython.com/invent4thed/chapter1.html

* https://inventwithpython.com/invent4thed/chapter2.html

* http://scipy-lectures.org/intro/intro.html

* http://scipy-lectures.org/intro/language/python_language.html

* http://scipy-lectures.org/intro/language/first_steps.html

* http://scipy-lectures.org/intro/language/basic_types.html

* https://books.trinket.io/pfe/01-intro.html

* https://books.trinket.io/pfe/02-variables.html

* https://docs.python.org/3/library/constants.html

* https://docs.python.org/3/library/functions.html (built in python
functions, not how to write your own)

* https://docs.python.org/3/library/stdtypes.html

* https://www.python-course.eu/python3_variables.php

* https://www.python-course.eu/python3_operators.php

* https://www.learnpython.org/en/Variables_and_Types

* https://www.learnpython.org/en/Basic_Operators

* https://python.swaroopch.com/basics.html

* https://python.swaroopch.com/op_exp.html

* https://www.tutorialspoint.com/python3/python_basic_syntax.htm

* https://www.tutorialspoint.com/python3/python_variable_types.htm

* https://www.tutorialspoint.com/python3/python_numbers.htm

* https://www.tutorialspoint.com/python3/python_basic_operators.htm

How do we represent data in the computer?

https://en.wikipedia.org/wiki/Binary_number

- Complete this
tutorial (it’s good, and I mean you should actually read it!):

https://ryanstutorials.net/binary-tutorial/

Text encoding (above the numeric/binary layer):

Note: There are some non-numeric characters, like ‘’

Hidden characters exist invisibly at the end of lines, as tabs,
etc.

Watch out, because hidden characters differ by operating system, and can
break code (do your work in the class VM when we get there)!

Types of built-in “object” in Python3 include:

Numbers

- Integers
- Floats
- Complex numbers

Strings

Containers

- Lists, Tuples, Sets, FrozenSets, and Dictionaries

Note: there can hypothetically be more types, but you would import them as extra modules.

Variable names are aliases assigned to objects.

04-ExpressionsTypes/00_variables.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
Variables
"""
# There are no declarations in python3, only assignments.
# Use lower_case_with_underscores for variable names.
some_var = 5
some_var # => 5
# Accessing a previously unassigned variable names is an error / exception.
# >>> print(some_unknown_var)
# If we ran the line above, it raises a NameError, learn to read errors!!!!
# NameError: name 'some_unknown_var' is not defined
my_string = "This is a string"
my_string = 'This is a string too with an " in it'
my_string2: str = (
"The : str part is optional, and for now is just a helpful note, called a type hint"
)
my_string3: str = "The thing below isn't a number, but a string"
my_string4: str = "4"
my_int: int = 4 # This is a real int
my_string = "We're re-using the above name (my_string) for a new object. Variables (labels) can be re-assigned to new objects"
# They can also be assigned to new objects of different type, but that's usualyl not good style.
my_string = 4
# Variables are just references to objects stored in memory
# These references are like numeric addresses
# The variable name does not have a type, but the object being referenced does.
myint: int = 7
print(type(myint))
print(id(myint))
print(myint)
myfloat: float = 7.0
print(type(myfloat))
print(id(myfloat))
print(myfloat)
myfloat = float(myint)
print(type(myfloat))
print(id(myfloat))
print(myfloat)
mystring = "hello"
print(type(mystring))
print(id(mystring))
print(mystring)
```

- The left side of
**assignment**using = must be a variable. - The right side must be some
**expression**that returns a value (hint expression is a pretty broad category). - Assignment binds a variable name(s) to the object, the thing in memory.
**Objects**have:- A
**type**(their category/class; see above) - A
**value**(the thing they store; see above) - A unique
**identifier**(something like their real memory address; see above)

- A
- Some objects are changeable (
**mutable**) and others are not changeable (**immutable**).

https://docs.python.org/3/reference/lexical_analysis.html#identifiers

* Variables can be named uppercase and lowercase letters A through Z,
the underscore _ and, except for the first character, the digits 0
through 9.

* Naming is case-sensitive, as it is in Linux.

* Starting with _ has special purpose (more to come later)

* The following identifiers are used as reserved words, or keywords of
the language, and cannot be used as ordinary identifiers. They must be
spelled exactly as written here:

~~~

False await else import pass

None break except in raise

True class finally is return

and continue for lambda try

as def from nonlocal while

assert del global not with

async elif if or yield

~~~

Name your variables using snake case, for example:

slithering_reptile

As a preview (more to come), name your classes using camel case, for
example:

DesertAnimal

How to get input from the user (during run-time of your
program)?

How to print output to the screen for the user during run-time?

04-ExpressionsTypes/01_input.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
print("Type something in please:")
x: str = input()
print(x)
y: str = input("Type something in please:")
print(y)
```

Notes:

* Command line arguments are another way to get input from users, but
they only work before/at run-time, not during the actual run of the
program.

* Files are another way.

Example: http://inventwithpython.com/invent4thed/chapter4.html

You can just discard input (or take enter alone) by calling input()
without storing the result. Print by itself just prints a newline.

04-ExpressionsTypes/02_jokes.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
print("What do you get when you cross a snowman with a vampire?")
input()
print("Frostbite!")
print()
print("What do dentists call an astronaut's cavity?")
input()
print("A black hole!")
print()
print("Knock knock.")
input()
print("Who's there?")
input()
print("Interrupting cow.")
input()
print("Interrupting cow wh", end="")
print("-MOO!")
```

https://en.wikipedia.org/wiki/Boolean_data_type

`The best thing about a boolean is even if you are wrong, you are only off by a bit...`

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Boolean values are special primitives
# Note: the capitalization
True # => True
False # => False
# They're actual objects
var = True
var = False
```

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# A special value indicating null
None
# None is an actual object.
var = None
```

https://realpython.com/null-in-python/

https://en.wikipedia.org/wiki/Integer

* An integer (from the Latin integer meaning “whole”) is a number that
can be written without a fractional component.

* The set of integers consists of:

* zero (0),

* the positive natural numbers (1, 2, 3, …), also called whole numbers
or counting numbers, and

* their additive inverses (the negative integers, i.e., -1, -2, -3,
…).

* In python, integers can be arbitrarily big (this is nice, especially
compare to other languages like C or C++ where you need to use a library
or write it yourself)!

https://en.wikipedia.org/wiki/Floating-point_arithmetic

* Floating-point arithmetic (FP) is arithmetic using formulaic
representation of real numbers as an approximation, so as to support a
trade-off between range and precision.

* For this reason, floating-point computation is often found in systems
which include very small and very large real numbers, which require fast
processing times.

* A number is, in general, represented approximately to a fixed number
of significant digits (the significand), and scaled using an exponent in
some fixed base.

* You may get slightly off answers, so watch out for things like x ==
2.0!

*
https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

* **Floating point number** example: 3.2

* **Floating point literal** number example: 4 / 5

An **operator** performs an action, e.g., the
`+`

in `4 + 5`

An **operand** is operated upon, e.g., the `4`

and `5`

in `4 + 5`

Operands and operators can be combined into
**expressions**, which themselves are evaluated and then
“return” objects.

04-ExpressionsTypes/03_numeric.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
x = 4
print(type(x))
print(id(x))
print(x)
y = 4.0
print(type(y))
print(id(y))
print(y)
# If I type 7, what is the type of z???
z: str = input()
print(type(z))
print(id(z))
print(z)
# Type-hint comment, optional for now, but recommended
# Explicit is better than implicit!!
a: int = 4
b: float = 4.0
# Assignment statements
# An assignment statement assigns a variable with the value of an expression.
# [var] = [arithexpr]
# Left must be a variable, right an arithmetic expression.
# Below, the third statement assigns a with 2 times a's current value.
# If a was 4, the statement assigns a with 2 * 4, or 8.
print(a)
# variables can be re-assigned to themselves
a = 2 * a
# variables can be re-assigned to other values
b = (4 + 3) / 2
print(b)
```

Expressions produce (return) values upon evaluation.

04-ExpressionsTypes/04_loan.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Left must be a variable, right an arithmetic expression.
# Arithmetic operators: +, -, *, /, %
# An assignment statement’s right side can be an arithmetic expression:
# Ex: x = (3 * y) + (z / 2).
# This over-simplified program below computes the total cost of a loan,
# given the loan amount and interest.
loan_amount: float = float(input())
interest_rate: float = float(input())
total_cost: float = loan_amount + (loan_amount * interest_rate)
print(total_cost)
```

https://en.wikipedia.org/wiki/Division_(mathematics)#Of_integers

https://en.wikipedia.org/wiki/Division_(mathematics)#Of_real_numbers

++++++++++++++++++++

Cahoot-04.1

https://mst.instructure.com/courses/58101/quizzes/55317

04-ExpressionsTypes/05_convert_bad.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Integer versus float division
fahr: int = int(input())
# despite calling celc a float, it labels an int.
celc: float = (5 // 9) * (fahr - 32)
print(celc)
```

- When an int (integer type) is divided with // by another int, the result is an int.
- See program to convert Fahrenheit to Celsius above.
- Regardless of the value of fahr that is used, celc will be assigned 0.
- Both of the literal constants 5 and 9 are stored by the compiler as integers.
- Integer division (//) will give you 0 (9 goes into 5 zero times), and 0 times anything is 0.
- The solution is to use the expected float division (/)

04-ExpressionsTypes/06_convert_good.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Integer versus float division
fahr: float = float(input())
celc: float = (5.0 / 9.0) * (fahr - 32)
print(celc)
```

Note: Watch out for deprecated python2 code, where this // vs. / pattern is reversed.

Some implicit conversions are automatically performed:

04-ExpressionsTypes/07_conversions.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
integer1: int = 3
print(type(integer1))
float1: float = 4.0
print(type(float1))
print(type(float1 + integer1)) # gives a float
print(type(float1 - integer1)) # gives a float
print(type(float1 * integer1)) # gives a float
print(type(float1 / integer1)) # gives a float
print(type(integer1 / float1)) # gives a float
print(type(float1 % integer1)) # gives a float
print(type(integer1 % float1)) # gives a float
print(type(float(integer1))) # gives a float
print(type(int(float1))) # gives an int, truncatitng decimal points
```

If conversion is from a floating-point type to an integer type, the value is truncated (the decimal part is removed).

++++++++++++++++++++

Cahoot-04.2

https://mst.instructure.com/courses/58101/quizzes/55318

https://en.wikipedia.org/wiki/Division_by_zero

Typically “undefined” and to be avoided!

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
print(5 / 0)
# produces an error in python
# >>> print(5/0)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# ZeroDivisionError: division by zero
```

++++++++++++++++++++

Cahoot-04.3

https://mst.instructure.com/courses/58101/quizzes/55319

https://en.wikipedia.org/wiki/Modular_arithmetic

In mathematics, modular arithmetic is a system of arithmetic for
integers, where numbers “wrap around” upon reaching a certain value, the
modulus.

(11 + 4) % 12 = 3

**mod The mod operator, %, works this way:**

a mod b produces the remainder after a is divided by b.

4 % 7 is 4 (since 4 / 7 is 0 with remainder 4)

7 % 3 is 1 (since 7 / 3 is 2 with remainder 1)

27 % 3 is 0 (since 27 / 3 is 9 with remainder 0)

For a positive integer n, two numbers a and b are said to be congruent modulo n, if their difference a - b is an integer multiple of n (that is, if there is an integer k such that a − b = kn). This congruence relation is typically considered when a and b are integers, and is denoted:

\(a\equiv b \pmod {n}\)The number n is called the modulus of the congruence.

The congruence relation may be rewritten as \(a=kn + b\)

\(a\equiv b \pmod {n}\)

asserts is that a and b have the same remainder when divided by n. That is,- \(a = p n + r\)
- \(b = q n + r\)

Example: \(38 \equiv 14 \pmod {12}\)

- because 38 - 14 = 24, which is a multiple of 12, or,
- equivalently, because both 38 and 14 have the same remainder 2 when divided by 12.

Example of mod 9:

**mod and division by 10s to choose place**

- Suppose you read in an integer from a user into a variable named x.
- Assume x is 5 digits long, and let’s represent it as x=abcde.
- So, e is the “ones” digit, d is the “tens” digit, etc.
- Thus, we don’t know any of these digits at initial run.
- But suppose that we need to know, for example, the tens digit, d, during run-time.
- How can we extract that from the value x, entered by the user at run-time?
- Well, x % 100 is the integer de.
- This is because 100 goes into x abc times with a remainder of de.
- Now, de // 10 is d. That is, 10 goes into de d times.

```
x = int(input())
tens_digit: int (x % 100) / 10 # assigns tens digit of x to variable tens_digit
```

When python evaluates mathematical expressions for their resulting value, the following defines order of precedence, where higher/earlier in the list takes precedence over lower/later:

`()`

Parentheses

`**`

Exponentiation (raise to the power)

`~ + -`

Complement, unary plus, and minus (method names for
the last two are +@ and -@)

`* / % //`

Multiply, divide, modulo, and floor division

`+ -`

Addition and subtraction

`>> <<`

Right and left bitwise shift

`&`

Bitwise ‘AND’

`^ |`

Bitwise exclusive `OR' and regular`

OR’

`<= < > >=`

Comparison operators

`== !=`

Equality operators (<> is like != in
python2)

`= %= /= //= -= += *= **=`

Assignment operators

`is is not`

Identity operators

`in not in`

Membership operators

`not or and`

Logical operators

However, you should use () even when you don’t need to.

Explicit is better than implicit!

++++++++++++++++++++

Cahoot-04.4

https://mst.instructure.com/courses/58101/quizzes/55320

A function is like a named block of code that can be “called” (a.k.a. executed) by referencing its name as follows:

`function(arguments)`

These are some pre-written importable functions in Python:

04-ExpressionsTypes/08_random.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# using someone else's code:
import random
# Built-in functions generate random numbers.
# Each call specifies a range and returns a new random number within that range.
print(random.randint(0, 5))
print(random.randint(0, 5))
print(random.randint(0, 5))
print()
# To enable reproducible programs,
# a programmer can set a seed,
# as in random.seed(7),
# prior to any calls to random.randint().
# Then, for any run of the program,
# the sequence of "random" numbers is always the same for that seed.
# If no seed is provided, Python3 uses the what as the seed,
# yielding the expected “randomness” for each run of the program?
random.seed(7)
print(random.randint(0, 5))
print(random.randint(0, 5))
print(random.randint(0, 5))
print()
random.seed(7)
print(random.randint(0, 5))
print(random.randint(0, 5))
print(random.randint(0, 5))
# Setting seed first is optional.
# Seed typically only set once, at start of program (if at all)
```

+++++ Lecture 1 ends here +++++

+++++ Lecture 2 starts here +++++

https://en.wikipedia.org/wiki/Caesar_cipher

The mod operation is important (and actually worth mastering)!

- History of Wheel Cipher (more than 2000 years old)

- Wheel cipher is also called Caesar cipher
- It was developed more than two thousand years ago
- It is also called “shift cipher” or “rot cipher” (rotation)

**The Outer Wheel**

* English alphabet of 26 letters

* Do we start at 0 or 1?

**The Inner Wheel**

The inner wheel is used to determine the number of shifts

**Spin the Inner Wheel**

For an animation, see:

https://inventwithpython.com/cipherwheel/

- Each spin gives an encryption/decryption mapping
- A mapping is equivalent to shifting each letter a fixed number of times

1. Take each letter from the plain-text and match it with the letter on
the outer wheel

2. Replace the letter with the corresponding letter on the inner
wheel

1. Take each letter from the cipher-text and match it with the letter on
the inner wheel

2. Replace the letter with the corresponding letter on the outer
wheel

This is the Caesar encoding: each letter gets a number, like ASCII, but
simpler.

**There are two different bugs in the below programs, that only
occurs sometimes, related to one of the more confusing operators we’ve
covered above! **

**Can you find them??**

04-ExpressionsTypes/09_keygen.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import random
print("Your randomly chosen Caesar cipher key is: ")
print(random.randint(0, 25))
print("\n Share securily with your communication partner, and don't tell anyone else\n")
```

Caesar encoding is similar to ASCII encoding, but

~~~

a is 0,

b is 1,

c is 2,

…

z is 25

~~~

The letters of “hi” in Caesar encoding are what?

Q: “hi” encrypted with a key of 1 is what?

A: “ij”

Q: “hi” encrypted with a key of 1 is what?

A: “jk”

- There is an actual logic error, a type of bug, which produces
incorrect encryption, but only sometimes!
**Lesson**:- Test with lots of different input types!
- Just because it works on one set of inputs, does not mean your program is correct.

04-ExpressionsTypes/10_encrypt.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
print("You have to run this program, once for every character of your message")
key: int = int(input("\nEnter your Caesar key in numeric form (1-25): "))
encoded_char: int = int(
input(
"\nEnter Caesar encoded number corresponding to one character of your message:"
)
)
print("\nThe translation of your character is:")
# To encrypt:
print(encoded_char + key)
```

04-ExpressionsTypes/11_decrypt.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-
print("You have to run this program, once for every character of your message")
key: int = int(input("\nEnter your Caesar key in numeric form (1-25): "))
encoded_char: int = int(
input(
"\nEnter Caesar encoded number corresponding to one character of your message:"
)
)
print("\nThe translation of your character is:")
# To decrypt:
print(encoded_char - key)
```

**Ask:**

* Besides the 2 above intentional bugs, what are some missing features
with this version of the Caesar cipher?

* Are there any features you’d like for this to be more usable,
convenient, easy, or functional?

To be stepped through in the python3-spyder IDE and/or python3-pudb
debugger:

04-ExpressionsTypes/12_expressions.py

++++++++++++++++++++

Cahoot-04.5

https://mst.instructure.com/courses/58101/quizzes/55384

04-ExpressionsTypes/13_logic.py

++++++++++++++++++++

Cahoot-04.6

https://mst.instructure.com/courses/58101/quizzes/55385

04-ExpressionsTypes/14_string_literals.py

++++++++++++++++++++

Cahoot-04.7

https://mst.instructure.com/courses/58101/quizzes/55386

04-ExpressionsTypes/15_conversions.py

++++++++++++++++++++

Cahoot-04.8

https://mst.instructure.com/courses/58101/quizzes/55387

04-ExpressionsTypes/16_assignment.py

++++++++++++++++++++

Cahoot-04.9

https://mst.instructure.com/courses/58101/quizzes/55388

Next: 05-Branches.html