Section 1
This commit is contained in:
@@ -183,6 +183,4 @@ exercise work. For example:
|
||||
>>>
|
||||
```
|
||||
|
||||
\[ **[Solution](soln1_1.html)** | **[Next](ex1_2.html)** |
|
||||
**[Index](index.html)** \]
|
||||
|
||||
[Next]("02_Hello_World.html")
|
||||
|
||||
506
Notes/01_Introduction/02_Hello_world.md
Normal file
506
Notes/01_Introduction/02_Hello_world.md
Normal 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")
|
||||
235
Notes/01_Introduction/03_Numbers.md
Normal file
235
Notes/01_Introduction/03_Numbers.md
Normal 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 |
|
||||
| | | 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 Guido’s 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 you’re at it, fix the program to correct the for overpayment that occurs in the last month.
|
||||
|
||||
[Next]("04_Strings.html")
|
||||
423
Notes/01_Introduction/04_Strings.md
Normal file
423
Notes/01_Introduction/04_Strings.md
Normal 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")
|
||||
405
Notes/01_Introduction/05_Lists.md
Normal file
405
Notes/01_Introduction/05_Lists.md
Normal 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")
|
||||
217
Notes/01_Introduction/06_Files.md
Normal file
217
Notes/01_Introduction/06_Files.md
Normal 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 wouldn’t call it directly unless you’re trying to explicitly skip or read a single line as shown.
|
||||
|
||||
Once you’re 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 isn’t being used.*
|
||||
|
||||
### (b) Reading a data file
|
||||
|
||||
Now that you know how to read a file, let’s 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 won’t 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")
|
||||
257
Notes/01_Introduction/07_Functions.md
Normal file
257
Notes/01_Introduction/07_Functions.md
Normal 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 you’ve 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, you’re 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, you’ll 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)
|
||||
```
|
||||
|
||||
That’s fine for learning and testing, but in a real program you probably wouldn’t 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, you’ll 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 %
|
||||
```
|
||||
Reference in New Issue
Block a user