Section 1

This commit is contained in:
David Beazley
2020-05-24 16:56:48 -05:00
parent 3f19c85ad7
commit ea25f0d39b
7 changed files with 2044 additions and 3 deletions

View File

@@ -183,6 +183,4 @@ exercise work. For example:
>>> >>>
``` ```
\[ **[Solution](soln1_1.html)** | **[Next](ex1_2.html)** | [Next]("02_Hello_World.html")
**[Index](index.html)** \]

View File

@@ -0,0 +1,506 @@
# 1.2 A First Python Program
## Notes
### Running Python
Python programs run inside an interpreter.
The interpreter is a simple "console-based" application that normally starts from a command shell.
```bash
python3
Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
```
Expert programmers usually have no problem using the interpreter in
this way, but it's not so user-friendly for beginners. That said,
you'll become a better Python programmer if you're able to use the
interpreter from the shell earlier rather than later.
### Interactive Mode
When you start Python, you get an *interactive* mode where you can experiment.
If you start typing statements, they will run immediately. There is no edit/compile/run/debug cycle.
```python
>>> print('hello world')
hello world
>>> 37*42
1554
>>> for i in range(5):
... print(i)
...
0
1
2
3
4
>>>
```
This *read-eval* loop is very useful for debugging and exploration.
Let's take a closer look at the elements:
- `>>>` is the interpreter prompt for starting a new statement.
- `...` is the interpreter prompt for continuing a statements. Enter a blank like to finish typing and run the statements.
The `...` prompt may or may not be shown depending on how you are using Python. For this course,
it is shown as blanks to make it easier to cut/paste code samples.
The underscore `_` holds the last result.
```pycon
>>> 37 * 42
1554
>>> _ * 2
3108
>>> _ + 50
3158
>>>
```
*This is only true in the interactive mode.* You never use `_` in a program.
Type `help(command)` to get information about `command`. Type `help()` with no name for interactive help.
```code
>>> help(range)
Help on class range in module builtins:
class range(object)
| range(stop) -> range object
| range(start, stop[, step]) -> range object
|
| Return an object that produces a sequence of integers from start (inclusive)
| to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
| start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
| These are exactly the valid indices for a list of 4 elements.
| When step is given, it specifies the increment (or decrement).
```
The official documentation is at [http://docs.python.org](http://docs.python.org).
### Creating programs
Programs are put in `.py` files.
```python
# hello.py
print('hello world')
```
You can create these files with your favorite text editor.
### Running Programs
To execute a program, run it in the terminal with the `python` command.
For example, in command-line Unix:
```bash
bash % python3 hello.py
hello world
bash %
```
Or from the Windows shell:
```shell
C:\SomeFolder>hello.py
hello world
C:\SomeFolder>c:\python36\python hello.py
hello world
```
Note: On Windows, you may need to specify a full path to the Python interpreter such as `c:\python36\python`.
### A Sample Program
Let's begin this part by trying to solve the following problem:
> One morning, you go out and place a dollar bill on the sidewalk by the Sears tower.
> Each day thereafter, you go out double the number of bills.
> How long does it take for the stack of bills to exceed the height of the tower?
Here's a solution:
```python
# sears.py
bill_thickness = 0.11 * 0.001 # Meters (0.11 mm)
sears_height = 442 # Height (meters)
num_bills = 1
day = 1
while num_bills * bill_thickness < sears_height:
print(day, num_bills, num_bills * bill_thickness)
day = day + 1
num_bills = num_bills * 2
print('Number of days', day)
print('Number of bills', num_bills)
print('Final height', num_bills * bill_thickness)
```
When we run it, we have the solution.
```bash
bash % python3 sears.py 1 1 0.00011
2 2 0.00022
3 4 0.00044
4 8 0.00088
5 16 0.00176
6 32 0.00352
...
21 1048576 115.34336
22 2097152 230.68672 Number of days 23 Number of bills 4194304 Final height 461.37344
```
Using this program as a guide, you can learn a few core concepts about Python.
### Statements
A python program is a sequence of statements:
```python
a = 3 + 4
b = a * 2
print(b)
```
Each statement is terminated by a newline. Statements are executed one after the other until you reach the end of the file.
### Comments
Comments are text that will not be executed.
```python
a = 3 + 4
# This is a comment
b = a * 2
print(b)
```
Comments are denoted by `#` and extend to the end of the line.
### Variables
A variable is a name for a value.
You can use letters (lower and upper-case) from a to z. As well as the character underscore `_`.
Numbers can also be part of the name of a variable, except as the first character.
```python
height = 442 # valid
_height = 442 # valid
height2 = 442 # valid
2height = 442 # invalid
```
### Types
Variables do not need to be declared with the type of the value. The type
is associated with the value on the right hand side, not name of the variable.
```python
height = 442 # An integer
height = 442 # Floating point
height = 'Really tall' # A string
```
### Case Sensitivity
Python is case sensitive. Upper and lower-case letters are considered different letters.
These are all different variables:
```python
name = 'Jake'
Name = 'Elwood'
NAME = 'Guido'
```
Language statements are always lower-case.
```python
while x < 0: # OK
WHILE x < 0: # ERROR
```
### Looping
Looping is a way to execute a set of instructions any number of times.
There are many ways to accomplish this in Python, one of them is the `while` statement:
```python
while num_bills * bill_thickness < sears_height:
print(day, num_bills, num_bills * bill_thickness)
day = day + 1
num_bills = num_bills * 2
print('Number of days', days)
```
The statements below the `while` will execute as long as the expression after the `while` is `true`.
### Indentation
Indentation in Python is used to denote a set of statements that go together.
From our previous example:
```python
while num_bills * bill_thickness < sears_height:
print(day, num_bills, num_bills * bill_thickness)
day = day + 1
num_bills = num_bills * 2
print('Number of days', days)
```
The indentation means that the following statements go together under the `while`.
```python
print(day, num_bills, num_bills * bill_thickness)
day = day + 1
num_bills = num_bills * 2
```
Because the next statement is not indented, it means that it does not belong to the previous set.
```python
print('Number of days', days)
```
The empty line is just for readability. It does not affect the execution.
### Blocks
A block is a set of statements grouped together.
In our previous example, the statements within the `while` form a *block*.
```python
print(day, num_bills, num_bills * bill_thickness)
day = day + 1
num_bills = num_bills * 2
```
Indentation within the block must be consistent.
```python
while num_bills * bill_thickness < sears_height:
print(day, num_bills, num_bills * bill_thickness)
day = day + 1 # ERROR
num_bills = num_bills * 2
```
The character colon `:` indicates the start of a block and must be present.
```python
while num_bills * bill_thickness < sears_height:
```
### Indentation best practices
* Use spaces instead of tabs.
* Use 4 spaces per level.
* Use a Python-aware editor.
### Conditionals
The `if` statement is used to execute a conditional:
```python
if a > b:
# `a` is greater than `b`
print('Computer says no')
else:
# `a` is lower or equal to `b`
print('Computer says yes')
```
Depending on the values of `a` and `b`, the execution will jump to `print('Computer says no')` or `print('Computer says yes')`.
You can check for multiple conditions with the `elif`.
```python
if a > b:
# `a` is greater than `b`
print('Computer says no')
elif a == b:
# `a` is equal to `b`
print('Computer says yes')
else:
# `a` is lower to `b`
print('Computer says maybe')
```
### Printing
The `print` function produces a single line of text with the values passed.
```python
print('Hello world!') # Prints the text 'Hello world!'
```
You can use variables. The text printed will be the value of the variable, not the name.
```python
x = 100
print(x) # Prints the text '100'
```
If you pass more than one item to `print` they are separated by spaces.
```python
name = 'Jake'
print('My name is', name) # Print the text 'My name is Jake'
```
`print()` always creates a new line at the end.
```python
print('Hello')
print('My name is', 'Jake')
```
This prints:
```code
Hello
My name is Jake
```
This can be avoided.
```python
print('Hello', end=' ')
print('My name is', 'Jake')
```
The previous code will print:
```code
Hello My name is Jake
```
### User input
To read a line of typed user input, use the `input()` function:
```python
name = input('Enter your name:')
print('Your name is', name)
```
`input` prints a prompt to the user and returns the response.
This is useful for small programs, learning exercises or simple debugging.
It is not widely used for real programs.
### `pass` statement
Sometimes you need to specify an empty block.
The keyword `pass` is used for it.
```python
if a > b:
pass
else:
print('Computer says false')
```
This is also called a "no-op" statement. It does nothing. It serves as a placeholder for statements. Possibly to be added later.
## Exercises 1.2
### (a) The Bouncing Ball
A rubber ball is dropped from a height of 100 meters and each time it hits the ground, it bounces back up to 3/5 the height it fell.
Write a program "bounce.py" that prints a table showing the height of the first 10 bounces.
Your program should make a table that looks something like this:
```code
1 60.0
2 36.0
3 21.599999999999998
4 12.959999999999999
5 7.775999999999999
6 4.6655999999999995
7 2.7993599999999996
8 1.6796159999999998
9 1.0077695999999998
10 0.6046617599999998
```
*Note: You can clean up the output a bit if you use the round() function. Try using it to round the output to 4 digits.*
```code
1 60.0
2 36.0
3 21.6
4 12.96
5 7.776
6 4.6656
7 2.7994
8 1.6796
9 1.0078
10 0.6047
```
### (b) Debugging
The following code fragment contains code from the Sears tower problem. It also has a bug in it.
```python
# sears.py
bill_thickness = 0.11 * 0.001 # Meters (0.11 mm)
sears_height = 442 # Height (meters)
num_bills = 1
day = 1
while num_bills * bill_thickness < sears_height:
print(day, num_bills, num_bills * bill_thickness)
day = days + 1
num_bills = num_bills * 2
print('Number of days', day)
print('Number of bills', num_bills)
print('Final height', num_bills * bill_thickness)
```
Copy and paste the code that appears above in a new program called `sears.py`.
When you run the code you will get an error message that causes the
program to crash like this:
```code
Traceback (most recent call last):
File "sears.py", line 10, in <module>
day = days + 1
NameError: name 'days' is not defined
```
Reading error messages is an important part of Python code. If your program
crashes, the very last line of the traceback message is the actual reason why the
the program crashed. Above that, you should see a fragment of source code and then
an identifying filename and line number.
* Which line is the error?
* What is the error?
* Fix the error
* Run the program successfully
[Next]("03_Numbers.html")

View File

@@ -0,0 +1,235 @@
# 1.3 Numbers and Booleans
## Notes
### Types of Numbers
Python has 4 types of numbers:
* Booleans
* Integers
* Floating point
* Complex (imaginary numbers)
### Booleans
Booleans have two values: `True`, `False`.
```python
a = True
b = False
```
Numerically, they're evaluated as integers with value `1`, `0`.
```python
c = 4 + True # 5
d = False
if d == 0:
print('d is False')
```
*Don't do that, it would be odd.*
### Integers
Signed values of arbitrary size and base:
```python
a = 37
b = -299392993727716627377128481812241231
c = 0x7fa8 # Hexadecimal
d = 0o253 # Octal
e = 0b10001111 # Binary
```
Common operations:
| | |
| ---- | ---- |
| + | Add |
| - | Subtract |
| * | Multiply |
| / | Divide |
| // | Floor divide |
| % | Modulo |
| ** | Power |
| << | Bit shift left |
| >> | Bit shift right |
| & | Big-wise AND |
| &#124; | Bit-wise OR |
| ^ | Bit-wise XOR |
| ~ | Bit-wise NOT |
| abs(x) | Absolute value |
### Comparisons
The following comparison / relational operators work with numbers:
`<`, `>`, `<=` `>=`, `==`, `!=`
You can form more complex boolean expressions using
`and`, `or`, `not`
Here are a few examples:
```python
if b >= a and b <= c:
print('b is between a and c')
if not (b < a or b > c):
print('b is still between a and c')
```
### Floating point (float)
Use a decimal or exponential notation to specify a floating point value:
```python
a = 37.45
b = 4e5 # 4 x 10**5 or 400,000
c = -1.345e-10
```
Floats are represented as double precision using the native CPU representation [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754).
> 17 digits or precision
> Exponent from -308 to 308
This is the same as the `double` type in the programming language C.
Be aware that floating point numbers are inexact when representing decimals.
```python
>>> a = 2.1 + 4.2
>>> a === 6.3
False
>>> a
6.300000000000001
>>>
```
This is **not a Python issue**, but the underlying floating point hardware on the CPU.
Common Operations:
| | |
| ---- | ---- |
| + | Add |
| - | Subtract |
| * | Multiply |
| / | Divide |
| // | Floor divide |
| % | Modulo (remainder) |
| ** | Power |
| abs(x) | Absolute value |
Theses are the same operators as Integers, except for the bit-wise operators.
Additional math functions are found in the `math` module.
```python
import math
a = math.sqrt(x)
b = math.sin(x)
c = math.cos(x)
d = math.tan(x)
e = math.log(x)
```
### Converting Numbers
The type name can be used to convert values:
```python
a = int(x) # Convert x to integer
b = float(x) # Convert x to float
```
Try it out.
```python
>>> a = 3.14159
>>> int(a)
3
>>> b = '3.14159' # It also works with strings containing numbers
>>> float(b)
3.15159
>>>
```
## Exercise 1.3
### (a) Dave's mortgage
Dave has decided to take out a 30-year fixed rate mortgage of $500,000 with Guidos Mortgage, Stock Investment, and Bitcoin trading corporation.
The interest rate is 5% and the monthly payment is $2684.11.
Here is a program that calculates the total amount that Dave will have to pay over the life of the mortgage:
```python
# mortgage.py
principal = 500000.0
rate = 0.05
payment = 2684.11
total_paid = 0.0
while principal > 0:
principal = principal * (1+rate/12) - payment
total_paid = total_paid + payment
print('Total paid', total_paid)
```
Enter this program and run it. You should get an answer of `966,279.6`.
### (b) Extra payments
Suppose Dave pays an extra $1000/month for the first 12 months of the mortgage?
Modify the program to incorporate this extra payment and have it print the total amount paid along with the number of months required.
When you run the new program, it should report a total payment of `929,965.62` over 342 months.
### (c) Making an Extra Payment Calculator
Modify the program so that extra payment information can be more generally handled.
Make it so that the user can set these variables:
```python
extra_payment_start_month = 60
extra_payment_end_month = 108
extra_payment = 1000
```
Make the program look at these variables and calculate the total paid appropriately.
How much will Dave pay if he pays an extra $1000/month for 4 years starting in year 5 of the mortgage?
### (d) Making a table
Modify the program to print out a table showing the month, total paid so far, and the remaining principal.
The output should look something like this:
```bash
1 2684.11 499399.22
2 5368.22 498795.94
3 8052.33 498190.15
4 10736.44 497581.83
5 13420.55 496970.98
...
308 875705.88 674.44
309 878389.99 -2006.86
Total paid 878389.99
Months 309
```
### (e) Bonus
While youre at it, fix the program to correct the for overpayment that occurs in the last month.
[Next]("04_Strings.html")

View File

@@ -0,0 +1,423 @@
# 1.4 Strings
## Notes
### Representing Text
String are text literals written in programs with quotes.
```python
# Single quote
a = 'Yeah but no but yeah but...'
# Double quote
b = "computer says no"
# Triple quotes
c = '''
Look into my eyes, look into my eyes, the eyes, the eyes, the eyes,
not around the eyes,
don't look around the eyes,
look into my eyes, you're under.
'''
```
Triple quotes capture all text enclosed in multiple lines.
### String escape codes
| | |
| ---- | ---- |
| `'\n'` | Line feed |
| `'\r'` | Carriage return |
| `'\t'` | Tab |
| `'\''` | Literal single quote |
| `'\"'` | Literal double quote |
| `'\\'` | Backslash |
These codes are inspired by C.
### String Representation
Each character represents a raw unicode code point.
<!-- TODO: Add Picture of following characters -->
```python
a = '\xf1' # a = 'ñ'
b = '\u2200' # b = '∀'
c = '\U0001D122' # c = '𝄢'
d = '\N{FORALL}' # d = '∀'
```
Strings work like an array for accessing its characters. You use an integer index, starting at 0.
```python
a = 'Hello world'
b = a[0] # 'H'
c = a[4] # 'o'
d = a[-1] # 'd' (end of string)
```
You can also slice or select substrings with `:`.
```python
d = a[:5] # 'Hello'
e = a[6:] # 'world'
f = a[3:8] # 'lowo'
g = a[-5:] # 'world'
```
### String operations
Concatenation, length, membership and replication.
```python
# Concatenation (+)
a = 'Hello' + 'World' # 'HelloWorld'
b = 'Say ' + a # 'Say HelloWorld'
# Length (len)
s = 'Hello'
len(s) # 5
# Membership test (`in`, `not in`)
t = 'e' in s # True
f = 'x' in s # False
tt = 'hi' not in s # True
# Replication (s * n)
rep = s * 5 # 'HelloHelloHelloHelloHello'
```
### String methods
Strings have methods that perform various operations with the string data.
Stripping any leading / trailing white space.
```python
s = ' Hello '
t = s.strip() # 'Hello'
```
Case conversion.
```python
s = 'Hello'
l = s.lower() # 'hello'
u = s.upper() # 'HELLO'
```
Replacing text.
```python
s = 'Hello world'
t = s.replace('Hello' , 'Hallo')
```
**More string methods:**
| | |
| ---- | ---- |
| s.endswith(suffix) | # Check if string ends with suffix |
| s.find(t) | # First occurrence of t in s |
| s.index(t) | # First occurrence of t in s |
| s.isalpha() | # Check if characters are alphabetic |
| s.isdigit() | # Check if characters are numeric |
| s.islower() | # Check if characters are lower-case |
| s.isupper() | # Check if characters are upper-case |
| s.join(slist) | # Joins lists using s as delimiter |
| s.lower() | # Convert to lower case |
| s.replace(old,new) | # Replace text |
| s.rfind(t) | # Search for t from end of string |
| s.rindex(t) | # Search for t from end of string |
| s.split([delim]) | # Split string into list of substrings |
| s.startswith(prefix) | # Check if string starts with prefix |
| s.strip() | # Strip leading/trailing space |
| s.upper() | # Convert to upper case |
### String Mutability
Strings are "immutable". They are read only.
Once created, the value can't be changed.
```python
>>> s = 'Hello World'
>>> s[1] = 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>>
```
**All operations and methods that manipulate string data, always create new strings.**
### String Conversions
Use `str()` to convert a value to a string.
```python
>>> x = 42
>>> str(x)
'42'
>>>
```
### Byte Strings
A string of 8-bit bytes.
```python
data = b'Hello World\r\n'
```
By putting a little b before our string literal we specify that it is a byte string as opposed to a text string.
Most of the usual string operations work.
```python
len(data) # 13
data[0:5] # b'Hello'
data.replace(b'Hello', b'Cruel') # b'Cruel World\r\n'
```
Indexing is a bit different because it returns byte values.
```python
data[0] # 72 (ASCII code for 'H')
```
Conversion to/from text.
```python
text = data.decode('utf-8') # bytes -> text
data = text.encode('utf-8') # text -> bytes
```
### Raw Strings
String with uninterpreted backslash.
```python
>>> rs = r'c:\newdata\test' # Raw (uninterpreted backslash)
>>> rs
'c:\\newdata\\test'
```
String is the literal text, exactly as typed.
This is useful in situations where the backslash has special significance. Example: filename, regular expressions, etc.
### f-Strings
String with formatted expression substitution.
```python
>>> name = 'IBM'
>>> shares = 100
>>> price = 91.1
>>> a = f'{name:>10s} {shares:10d} {price:10.2f}'
>>> a
' IBM 100 91.10'
>>> b = f'Cost = ${shares*price:0.2f}'
>>> b
'Cost = $9110.00'
>>>
```
**Note: Requires Python 3.6 or newer.**
## Exercises 1.4
In this exercise, we experiment with operations on Python's string type.
You may want to do most of this exercise at the Python interactive prompt where you can easily see the results.
Important note:
> In exercises where you are supposed to interact with the interpreter,
> `>>>` is the interpreter prompt that you get when Python wants
> you to type a new statement. Some statements in the exercise span
> multiple lines--to get these statements to run, you may have to hit
> 'return' a few times. Just a reminder that you *DO NOT* type
> the `>>>` when working these examples.
Start by defining a string containing a series of stock ticker symbols like this:
```pycon
>>> symbols = 'AAPL,IBM,MSFT,YHOO,SCO'
>>>
```
### (a): Extracting individual characters and substrings
Strings are arrays of characters. Try extracting a few characters:
```pycon
>>> symbols[0]
?
>>> symbols[1]
?
>>> symbols[2]
?
>>> symbols[-1] # Last character
?
>>> symbols[-2] # Negative indices are from end of string
?
>>>
```
### (b) Strings as read-only objects
In Python, strings are read-only.
Verify this by trying to change the first character of `symbols` to a lower-case 'a'.
```python
>>> symbols[0] = 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>>
```
### (c) String concatenation
Although string data is read-only, you can always reassign a variable
to a newly created string.
Try the following statement which concatenates a new symbol "GOOG" to
the end of `symbols`:
```pycon
>>> symbols = symbols + 'GOOG'
>>> symbols
'AAPL,IBM,MSFT,YHOO,SCOGOOG'
>>>
```
Oops! That's not what we wanted. Fix it so that the `symbols` variable holds the value `'HPQ,AAPL,IBM,MSFT,YHOO,SCO,GOOG'`.
In these examples, it might look like the original string is being
modified, in an apparent violation of strings being read only. Not
so. Operations on strings create an entirely new string each
time. When the variable name `symbols` is reassigned, it points to the
newly created string. Afterwards, the old string is destroyed since
it's not being used anymore.
### (d) Membership testing (substring testing)
Experiment with the `in` operator to check for substrings. At the interactive prompt, try these operations:
```pycon
>>> 'IBM' in symbols
?
>>> 'AA' in symbols
?
>>> 'CAT' in symbols
?
>>>
```
*Why did the check for "AA" return `True`?*
### (e) String Methods
At the Python interactive prompt, try experimenting with some of the string methods.
```pycon
>>> symbols.lower()
?
>>> symbols
?
>>>
```
Remember, strings are always read-only. If you want to save the result of an operation, you need to place it in a variable:
```pycon
>>> lowersyms = symbols.lower()
>>>
```
Try some more operations:
```pycon
>>> symbols.find('MSFT')
?
>>> symbols[13:17]
?
>>> symbols = symbols.replace('SCO','DOA')
>>> symbols
?
>>> name = ' IBM \n'
>>> name = name.strip() # Remove surrounding whitespace
>>> name
?
>>>
```
### (f) f-strings
Sometimes you want to create a string and embed the values of
variables into it.
To do that, use an f-string. For example:
```pycon
>>> name = 'IBM'
>>> shares = 100
>>> price = 91.1
>>> f'{shares} shares of {name} at ${price:0.2f}'
'100 shares of IBM at $91.10'
>>>
```
Modify the `mortgage.py` program from Exercise 1.3 to create its output using f-strings.
Try to make it so that output is nicely aligned.
### Commentary
As you start to experiment with the interpreter, you often want to know more about the operations supported by different objects.
For example, how do you find out what operations are available on a string?
Depending on your Python environment, you might be able to see a list
of available methods via tab-completion. For example, try typing
this:
```python
>>> s = 'hello world'
>>> s.<tab key>
>>>
```
If hitting tab doesn't do anything, you can fall back to the
builtin-in `dir()` function. For example:
```python
>>> s = 'hello'
>>> dir(s)
['__add__', '__class__', '__contains__', ..., 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>>
```
`dir()` produces a list of all operations that can appear after the `(.)`.
Use the `help()` command to get more information about a specific operation:
```python
>>> help(s.upper)
Help on built-in function upper:
upper(...)
S.upper() -> string
Return a copy of the string S converted to uppercase.
>>>
```
IDEs and alternative interactive shells often give you more help here.
For example, a popular alternative to Python's normal interactive mode
is IPython (http://ipython.org). IPython provides some nice features
such as tab-completion of method names, more integrated help and more.
[Next]("05_Lists.html")

View File

@@ -0,0 +1,405 @@
# 1.5 Lists
## Notes
### String Splitting
Strings can represent fields of data. We can work with each field by splitting the string into a list.
```pycon
>>> line = 'GOOG,100,490.10'
>>> row = line.split(',')
>>> row
['GOOG', '100', '490.10']
>>>
```
A common use case for this splitting is when reading data from a file. You might read each line as text and then split the text into columns.
### List operations
Use square brackets to create a list:
```python
names = [ 'Elwood', 'Jake', 'Curtis' ]
nums = [ 39, 38, 42, 65, 111]
```
It can hold items of any type. Add a new item using `append()`:
```python
names.append('Murphy') # Adds at end
names.insert(2, 'Aretha') # Inserts in middle
```
Use `+` to concatenate lists:
```python
s = [1, 2, 3]
t = ['a', 'b']
s + t # [1, 2, 3, 'a', 'b']
```
Lists are indexed by integers. Starting at 0.
```python
names = [ 'Elwood', 'Jake', 'Curtis' ]
names[0] # 'Elwood'
names[1] # 'Jake'
names[2] # 'Curtis'
```
Negative indices count from the end.
```python
names[-1] # 'Curtis'
```
You can change on element in the list.
```python
names[1] = 'Joliet Jake'
names # [ 'Elwood', 'Joliet Jake', 'Curtis' ]
```
Length of the list.
```python
names = ['Elwood','Jake','Curtis']
len(names) # 3
```
Membership test (`in`, `not in`).
```python
'Elwood' in names # True
'Britney' not in names # True
```
Replication (`s * n`).
```python
s = [1, 2, 3]
s * 3 # [1, 2, 3, 1, 2, 3, 1, 2, 3]
```
### List Iteration & Search
Iterating over the list contents.
```python
for name in names:
# use name
# e.g. print(name)
...
```
This is similar to a `foreach` statement from other programming languages.
To find something quickly, use `index()`.
```python
names = ['Elwood','Jake','Curtis']
names.index('Curtis') # 2
```
If the element is present more than one, it will return the index of the first occurrence.
If the element is not found, it will raise a `ValueError` exception.
### List Removal
You can remove either with the element value or the index number.
```python
# Using the value
names.remove('Curtis')
# Using the index
del names[1]
```
Removing results in items moving down to fill the space vacated. There are no holes in the list.
If there are more than one occurrence of the element, `.remove()` will remove only the first occurrence.
### List Sorting
Lists can be sorted 'in-place'.
```python
s = [10, 1, 7, 3]
s.sort() # [1, 3, 7, 10]
# Reverse order
s = [10, 1, 7, 3]
s.sort(reverse=True) # [10, 7, 3, 1]
# It works with any ordered data
s = ['foo', 'bar', 'spam']
s.sort() # ['bar', 'foo', 'spam']
```
### Lists and Math
*Caution: Lists were not designed for math operations.*
```pycon
>>> nums = [1, 2, 3, 4, 5]
>>> nums * 2
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
>>> nums + [10, 11, 12, 13, 14]
[1, 2, 3, 4, 5, 10, 11, 12, 13, 14] >>>
```
Specifically, lists don't represent vectors/matrices as in MATLAB, Octave, IDL, etc.
However, there are some packages to help you with that (e.g. numpy).
## Exercises 1.5
In this exercise, we experiment with Python's list datatype. In the last exercise, you worked with strings containing stock symbols.
```pycon
>>> symbols = 'HPQ,AAPL,IBM,MSFT,YHOO,DOA,GOOG'
```
Split it into a list of names using the `split()` operation of strings:
```pycon
>>> symlist = symbols.split(',')
```
### (a) Extracting and reassigning list elements
Try a few lookups:
```python
>>> symlist[0]
'HPQ'
>>> symlist[1]
'AAPL'
>>> symlist[-1]
'GOOG'
>>> symlist[-2]
'DOA'
>>>
```
Try reassigning one value:
```python
>>> symlist[2] = 'AIG'
>>> symlist
['HPQ', 'AAPL', 'AIG', 'MSFT', 'YHOO', 'DOA', 'GOOG']
>>>
```
Take a few slices:
```python
>>> symlist[0:3]
['HPQ', 'AAPL', 'AIG']
>>> symlist[-2:]
['DOA', 'GOOG']
>>>
```
Create an empty list and append an item to it.
```python
>>> mysyms = []
>>> mysyms.append('GOOG')
>>> mysyms
['GOOG']
```
You can reassign a portion of a list to another list. For example:
```python
>>> symlist[-2:] = mysyms
>>> symlist
['HPQ', 'AAPL', 'AIG', 'MSFT', 'YHOO', 'GOOG']
>>>
```
When you do this, the list on the left-hand-side (`symlist`) will be resized as appropriate to make the right-hand-side (`mysyms`) fit.
For instance, in the above example, the last two items of `symlist` got replaced by the single item in the list `mysyms`.
### (b) Looping over list items
The `for` loop works by looping over data in a sequence such as a list.
Check this out by typing the following loop and watching what happens:
```pycon
>>> for s in symlist:
print('s =', s)
# Look at the output
```
### (c) Membership tests
Use the `in` or `not in` operator to check if `'AIG'`,`'AA'`, and `'CAT'` are in the list of symbols.
```pycon
>>> # Is 'AIG' IN the `symlist`?
True
>>> # Is 'AA' IN the `symlist`?
False
>>> # Is 'CAT' NOT IN the `symlist`?
True
>>>
```
### (d) Appending, inserting, and deleting items
Use the `append()` method to add the symbol `'RHT'` to end of `symlist`.
```pycon
>>> # append 'RHT'
>>> symlist
['HPQ', 'AAPL', 'AIG', 'MSFT', 'YHOO', 'GOOG', 'RHT']
>>>
```
Use the `insert()` method to insert the symbol `'AA'` as the second item in the list.
```pycon
>>> # Insert 'AA' as the second item in the list
>>> symlist
['HPQ', 'AA', 'AAPL', 'AIG', 'MSFT', 'YHOO', 'GOOG', 'RHT']
>>>
```
Use the `remove()` method to remove `'MSFT'` from the list.
```pycon
>>> # Remove 'MSFT'
>>> symlist
['HPQ', 'AA', 'AAPL', 'AIG', 'YHOO', 'GOOG', 'RHT']
>>>
```
Append a duplicate entry for `'YHOO'` at the end of the list.
*Note: it is perfectly fine for a list to have duplicate values.*
```pycon
>>> # Append 'YHOO'
>>> symlist
['HPQ', 'AA', 'AAPL', 'AIG', 'YHOO', 'GOOG', 'RHT', 'YHOO']
>>>
```
Use the `index()` method to find the first position of `'YHOO'` in the list.
```pycon
>>> # Find the first index of 'YHOO'
4
>>> symlist[4]
'YHOO'
>>>
```
Count how many times `'YHOO'` is in the list:
```pycon
>>> symlist.count('YHOO')
2
>>>
```
Remove the first occurrence of `'YHOO'`.
```pycon
>>> # Remove first occurrence 'YHOO'
>>> symlist
['HPQ', 'AA', 'AAPL', 'AIG', 'GOOG', 'RHT', 'YHOO']
>>>
```
Just so you know, there is no method to find or remove all occurrences of an item.
However, we'll see an elegant way to do this in section 2.
### (e) Sorting
Want to sort a list? Use the `sort()` method. Try it out:
```pycon
>>> symlist.sort()
>>> symlist
['AA', 'AAPL', 'AIG', 'GOOG', 'HPQ', 'RHT', 'YHOO']
>>>
```
Want to sort in reverse? Try this:
```pycon
>>> symlist.sort(reverse=True)
>>> symlist
['YHOO', 'RHT', 'HPQ', 'GOOG', 'AIG', 'AAPL', 'AA']
>>>
```
Note: Sorting a list modifies its contents 'in-place'. That is, the elements of the list are shuffled around, but no new list is created as a result.
### (f) Putting it all back together
Want to take a list of strings and join them together into one string?
Use the `join()` method of strings like this (note: this looks funny at first).
```pycon
>>> a = ','.join(symlist)
>>> a
'YHOO,RHT,HPQ,GOOG,AIG,AAPL,AA'
>>> b = ':'.join(symlist)
>>> b
'YHOO:RHT:HPQ:GOOG:AIG:AAPL:AA'
>>> c = ''.join(symlist)
>>> c
'YHOORHTHPQGOOGAIGAAPLAA'
>>>
```
### (g) Lists of anything
Lists can contain any kind of object, including other lists (e.g., nested lists).
Try this out:
```pycon
>>> nums = [101, 102, 103]
>>> items = ['spam', symlist, nums]
>>> items
['spam', ['YHOO', 'RHT', 'HPQ', 'GOOG', 'AIG', 'AAPL', 'AA'], [101, 102, 103]]
```
Pay close attention to the above output. `items` is a list with three elements.
The first element is a string, but the other two elements are lists.
You can access items in the nested lists by using multiple indexing operations.
```pycon
>>> items[0]
'spam'
>>> items[0][0]
's'
>>> items[1]
['YHOO', 'RHT', 'HPQ', 'GOOG', 'AIG', 'AAPL', 'AA']
>>> items[1][1]
'RHT'
>>> items[1][1][2]
'T'
>>> items[2]
[101, 102, 103]
>>> items[2][1]
102
>>>
```
Even though it is technically possible to make very complicated list
structures, as a general rule, you want to keep things simple.
Usually lists hold items that are all the same kind of value. For
example, a list that consists entirely of numbers or a list of text
strings. Mixing different kinds of data together in the same list is
often a good way to make your head explode so it's best avoided.
[Next]("06_Files.html")

View File

@@ -0,0 +1,217 @@
# 1.6 File Management
## Notes
### File Input and Output
Open a file.
```python
f = open('foo.txt', 'rt') # Open for reading (text)
g = open('bar.txt', 'wt') # Open for writing (text)
```
Reading data.
```python
data = f.read()
# Read only up to 'maxbytes' bytes
data = f.read([maxbytes])
```
Writing text to a file.
```python
g.write('some text')
```
Close when you are done.
```python
f.close()
g.close()
```
Files should be properly closed. This is why the preferred approach is to use the `with` statement.
```python
with open(filename, 'rt') as f:
# Use the file `f`
...
# No need to close explicitly
...statements
```
This automatically closes the file when control leaves the indented code block.
### Common Idioms for Reading File Data
Reading an entire file all at once as a string.
```python
with open('foo.txt', 'rt') as f:
data = f.read()
# `data` is a string with all the text in `foo.txt`
```
Reading a file line-by-line
```python
with open(filename, 'rt') as f:
for line in f:
# Process the line `f`
```
Writing string data.
```python
with open('outfile', 'wt') as f:
f.write('Hello World\n')
...
```
Redirecting the print function.
```python
with open('outfile', 'wt') as f:
print('Hello World', file=f)
...
```
## Exercises 1.6
This exercise depends on a file `Data/portfolio.csv`. The file contains a list of lines with information on a portfolio of stocks.
Locate the file and look at its contents:
### (a) File Preliminaries
*Note: Make sure you are running Python in a location where you can access the `portfolio.csv` file.
You can find out where Python thinks it's running by doing this:
```python
>>> import os
>>> os.getcwd()
'/Users/beazley/Desktop/practical-python' # Output vary
>>>
```
First, try reading the entire file all at once as a big string:
```pycon
>>> with open('Data/portfolio.csv', 'rt') as f:
data = f.read()
>>> data
'name,shares,price\n"AA",100,32.20\n"IBM",50,91.10\n"CAT",150,83.44\n"MSFT",200,51.23\n"GE",95,40.37\n"MSFT",50,65.10\n"IBM",100,70.44\n'
>>> print(data)
name,shares,price
"AA",100,32.20
"IBM",50,91.10
"CAT",150,83.44
"MSFT",200,51.23
"GE",95,40.37
"MSFT",50,65.10
"IBM",100,70.44
>>>
```
In the above example, it should be noted that Python has two modes of output.
In the first mode where you type `data` at the prompt, Python shows you the raw string representation including quotes and escape codes.
When you type `print(data)`, you get the actual formatted output of the string.
Although reading a file all at once is simple, it is often not the
most appropriate way to do it—especially if the file happens to be
huge or if contains lines of text that you want to handle one at a
time.
To read a file line-by-line, use a for-loop like this:
```pycon
>>> with open('Data/portfolio.csv', 'rt') as f:
for line in f:
print(line, end='')
name,shares,price
"AA",100,32.20
"IBM",50,91.10
...
>>>
```
When you use this code as shown, lines are read until the end of the file is reached at which point the loop stops.
On certain occasions, you might want to manually read or skip a *single* line of text (e.g., perhaps you want to skip the first line of column headers).
```pycon
>>> f = open('Data/portfolio.csv', 'rt')
>>> headers = next(f)
>>> headers
'name,shares,price\n'
>>> for line in f:
print(line, end='')
"AA",100,32.20
"IBM",50,91.10
...
>>> f.close()
>>>
```
`next()` returns the next line of text in the file. If you were to call it repeatedly, you would get successive lines.
However, just so you know, the `for` loop already uses `next()` to obtain its data.
Thus, you normally wouldnt call it directly unless youre trying to explicitly skip or read a single line as shown.
Once youre reading lines of a file, you can start to perform more processing such as splitting.
For example, try this:
```pycon
>>> f = open('Data/portfolio.csv', 'rt')
>>> headers = next(f).split(',')
>>> headers
['name', 'shares', 'price\n']
>>> for line in f:
row = line.split(',')
print(row)
['"AA"', '100', '32.20\n']
['"IBM"', '50', '91.10\n']
...
>>> f.close()
```
*Note: In these examples, `f.close()` is being called explicitly because the `with` statement isnt being used.*
### (b) Reading a data file
Now that you know how to read a file, lets write a program to perform a simple calculation.
The columns in `portfolio.csv` correspond to the stock name, number of
shares, and purchase price of a single share. Write a program called
`pcost.py` that opens this file, reads all lines, and calculates how
much it cost to purchase all of the shares in the portfolio.
*Hint: to convert a string to an integer, use `int(s)`. To convert a string to a floating point, use `float(s)`.*
Your program should print output such as the following:
```bash
Total cost 44671.15
```
### (c) Other kinds of 'files'
What if you wanted to read a non-text file such as a gzip-compressed datafile?
The builtin `open()` function wont help you here, but Python has a library module `gzip` that can read gzip compressed files.
Try it:
```pycon
>>> import gzip
>>> with gzip.open('Data/portfolio.csv.gz') as f:
for line in f:
print(line, end='')
... look at the output ...
>>>
```
[Next]("07_Functions.html")

View File

@@ -0,0 +1,257 @@
# 1.7 Introduction to Functions
## Notes
### Custom Functions
Use functions for code you want to reuse. Here is a function definition:
```python
def sumcount(n):
'''
Returns the sum of the first n integers
'''
total = 0
while n > 0:
total += n
n -= 1
return total
```
Calling a function.
```python
# Use parenthesis to call the function
a = sumcount(100)
```
A function is a series of statements that perform some task and return a result.
The `return` keyword is needed to explicitly specify the return value of the function.
### Library Functions
Python comes with a large standard library.
Library modules are accessed using `import`.
```python
# `math` module
import math
x = math.sqrt(10)
# `urllib.request` module
import urllib.request
u = urllib.request.urlopen('http://www.python.org/') data = u.read()
```
We will cover libraries and modules in more detail later.
### Errors and exceptions
Errors are reported as exceptions. An exception causes the program to stop.
Try this in your python REPL.
```pycon
>>> int('N/A')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'N/A'
>>>
```
For debugging purposes, the message describes what happened, where the error occurred and the traceback.
### Catching and Handling Exceptions
Exceptions can be caught and handled.
To catch, use `try - except` statement.
```python
for line in f:
fields = line.split()
try:
shares = int(fields[1])
except ValueError:
print("Couldn't parse", line)
...
```
The name `ValueError` must match the kind of error you are trying to catch.
### Raising Exceptions
To raise an exception, use the `raise` statement.
```python
raise RuntimeError('What a kerfuffle')
```
This will cause the program to abord with an exception traceback. Unless caught by a `try-except` block.
```bash
% python3 foo.py
Traceback (most recent call last):
File "foo.py", line 21, in <module>
raise RuntimeError("What a kerfuffle")
RuntimeError: What a kerfuffle
```
## Exercises 1.7
### (a) Defining a function
You can define a simple function using the `def` statement. For example,
```python
>>> def greeting(name):
'Issues a greeting'
print('Hello', name)
>>> greeting('Guido')
Hello Guido
>>> greeting('Paula')
Hello Paula
>>>
```
If the first statement of a function is a string, it serves as documentation.
Try typing a command such as `help(greeting)` to see it displayed.
### (b) Turning a script into a function
Take the code you wrote for the `pcost.py` program in the last exercise and turn it into a function `portfolio_cost(filename)`.
The function takes a filename as input, reads the portfolio data in that file, and returns the total cost of the portfolio.
To use your function, change your program so that it looks something like this:
```python
def portfolio_cost(filename):
...
# Your code here
...
cost = portfolio_cost('Data/portfolio.csv')
print('Total cost:', cost)
```
When you run your program, you should see the same output as before.
After youve run your program, you can also call your function interactively by typing this:
```bash
bash $ python3 -i pcost.py
```
This will allow you to call your function from the interactive mode.
```python
>>> portfolio_cost('Data/portfolio.csv')
44671.15
>>>
```
Being able to experiment with your code interactively is useful for testing and debugging.
What happens if you try your function on a file with some missing fields?
```pycon
>>> portfolio_cost('Data/missing.csv')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pcost.py", line 11, in portfolio_cost
nshares = int(fields[1])
ValueError: invalid literal for int() with base 10: ''
>>>
```
At this point, youre faced with a decision. To make the program work
you can either sanitize the original input file by eliminating bad
lines or you can modify your code to handle the bad lines in some
manner.
Modify the `pcost.py` program to catch the exception, print a warning message,
and continue processing the rest of the file.
### (c) Using a library function
Python comes with a large standard library of useful functions.
One library that might be useful here is the `csv` module. You should use it whenever you have to work with CSV data files.
Here is an example of how it works:
```pycon
>>> import csv
>>> f = open('Data/portfolio.csv')
>>> rows = csv.reader(f)
>>> headers = next(rows)
>>> headers
['name', 'shares', 'price']
>>> for row in rows:
print(row)
['AA', '100', '32.20']
['IBM', '50', '91.10']
['CAT', '150', '83.44']
['MSFT', '200', '51.23']
['GE', '95', '40.37']
['MSFT', '50', '65.10']
['IBM', '100', '70.44']
>>> f.close()
>>>
```
One nice thing about the `csv` module is that it deals with a variety of low-level details such as quoting and proper comma splitting.
In the above output, youll notice that it has stripped the double-quotes away from the names in the first column.
Modify your `pcost.py` program so that it uses the `csv` module for parsing and try running earlier examples.
### (d) Reading from the command line
In the `pcost.py` program, the name of the input file has been hardwired into the code:
```python
# pcost.py
def portfolio_cost(filename):
...
# Your code here
...
cost = portfolio_cost('Data/portfolio.csv')
print('Total cost:', cost)
```
Thats fine for learning and testing, but in a real program you probably wouldnt do that.
Instead, you might pass the name of the file in as an argument to a script. Try changing the bottom part of the program as follows:
```python
# pcost.py
import sys
def portfolio_cost(filename):
...
# Your code here
...
if len(sys.argv) == 2:
filename = sys.argv[1]
else:
filename = 'portfolio.csv'
cost = portfolio_cost(filename)
print('Total cost:', cost)
```
`sys.argv` is a list that contains passed arguments on the command line (if any).
To run your program, youll need to run Python from the
terminal.
For example, from bash on Unix:
```bash
bash % python3 pcost.py Data/portfolio.csv
Total cost: 44671.15
bash %
```