Skip to content

Commit 9f5e9e9

Browse files
authored
Merge pull request #204 from QuantEcon/lec-review-5
Chapter 5: Adding Subtitles, Step in Indexing, and More Concise Solution.
2 parents 1f649c2 + b155433 commit 9f5e9e9

File tree

1 file changed

+141
-94
lines changed

1 file changed

+141
-94
lines changed

lectures/python_essentials.md

Lines changed: 141 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ Let's learn a bit more about them.
6161

6262
### Primitive Data Types
6363

64+
65+
#### Boolean Values
66+
6467
One simple data type is **Boolean values**, which can be either `True` or `False`
6568

6669
```{code-cell} python3
@@ -109,7 +112,13 @@ bools = [True, True, False, True] # List of Boolean values
109112
sum(bools)
110113
```
111114

112-
Complex numbers are another primitive data type in Python
115+
#### Numeric Types
116+
117+
Numeric types are also important primitive data types.
118+
119+
We have seen `integer` and `float` types before.
120+
121+
**Complex numbers** are another primitive data type in Python
113122

114123
```{code-cell} python3
115124
x = complex(1, 2)
@@ -185,13 +194,13 @@ Tuple unpacking is convenient and we'll use it often.
185194
```{index} single: Python; Slicing
186195
```
187196

188-
To access multiple elements of a list or tuple, you can use Python's slice
197+
To access multiple elements of a sequence (a list, a tuple or a string), you can use Python's slice
189198
notation.
190199

191200
For example,
192201

193202
```{code-cell} python3
194-
a = [2, 4, 6, 8]
203+
a = ["a", "b", "c", "d", "e"]
195204
a[1:]
196205
```
197206

@@ -207,6 +216,18 @@ Negative numbers are also permissible
207216
a[-2:] # Last two elements of the list
208217
```
209218

219+
You can also use the format `[start:end:step]` to specify the step
220+
221+
```{code-cell} python3
222+
a[::2]
223+
```
224+
225+
Using a negative step, you can return the sequence in a reversed order
226+
227+
```{code-cell} python3
228+
a[-2::-1] # Walk backwards from the second last element to the first element
229+
```
230+
210231
The same slice notation works on tuples and strings
211232

212233
```{code-cell} python3
@@ -340,7 +361,7 @@ To give an example, let's write the file us_cities.txt, which lists US cities an
340361

341362
(us_cities_data)=
342363
```{code-cell} ipython
343-
%%file us_cities.txt
364+
%%writefile us_cities.txt
344365
new york: 8244910
345366
los angeles: 3819702
346367
chicago: 2707120
@@ -352,7 +373,7 @@ san diego: 1326179
352373
dallas: 1223229
353374
```
354375

355-
Here %%file is an [IPython cell magic](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cell-magics).
376+
Here `%%writefile` is an [IPython cell magic](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cell-magics).
356377

357378
Suppose that we want to make the information more readable, by capitalizing names and adding commas to mark thousands.
358379

@@ -562,6 +583,23 @@ Remember
562583
* `P and Q` is `True` if both are `True`, else `False`
563584
* `P or Q` is `False` if both are `False`, else `True`
564585

586+
We can also use `all()` and `any()` to test a sequence of expressions
587+
588+
```{code-cell} python3
589+
all([1 <= 2 <= 3, 5 <= 6 <= 7])
590+
```
591+
```{code-cell} python3
592+
all([1 <= 2 <= 3, "a" in "letter"])
593+
```
594+
```{code-cell} python3
595+
any([1 <= 2 <= 3, "a" in "letter"])
596+
```
597+
598+
Note:
599+
600+
* `all()` returns `True` when *all* boolean values/expressions in the sequence are `True`
601+
* `any()` returns `True` when *any* boolean values/expressions in the sequence are `True`
602+
565603
## More Functions
566604

567605
```{index} single: Python; Functions
@@ -739,92 +777,6 @@ Part 3: Given `pairs = ((2, 5), (4, 2), (9, 8), (12, 10))`, count the number of
739777
such that both `a` and `b` are even.
740778
```
741779

742-
743-
```{exercise-start}
744-
:label: pyess_ex2
745-
```
746-
747-
Consider the polynomial
748-
749-
```{math}
750-
:label: polynom0
751-
752-
p(x)
753-
= a_0 + a_1 x + a_2 x^2 + \cdots a_n x^n
754-
= \sum_{i=0}^n a_i x^i
755-
```
756-
757-
Write a function `p` such that `p(x, coeff)` that computes the value in {eq}`polynom0` given a point `x` and a list of coefficients `coeff`.
758-
759-
Try to use `enumerate()` in your loop.
760-
761-
```{exercise-end}
762-
```
763-
764-
765-
```{exercise}
766-
:label: pyess_ex3
767-
768-
Write a function that takes a string as an argument and returns the number of capital letters in the string.
769-
770-
Hint: `'foo'.upper()` returns `'FOO'`.
771-
```
772-
773-
774-
```{exercise}
775-
:label: pyess_ex4
776-
777-
Write a function that takes two sequences `seq_a` and `seq_b` as arguments and
778-
returns `True` if every element in `seq_a` is also an element of `seq_b`, else
779-
`False`.
780-
781-
* By "sequence" we mean a list, a tuple or a string.
782-
* Do the exercise without using [sets](https://docs.python.org/3/tutorial/datastructures.html#sets) and set methods.
783-
```
784-
785-
786-
```{exercise}
787-
:label: pyess_ex5
788-
789-
When we cover the numerical libraries, we will see they include many
790-
alternatives for interpolation and function approximation.
791-
792-
Nevertheless, let's write our own function approximation routine as an exercise.
793-
794-
In particular, without using any imports, write a function `linapprox` that takes as arguments
795-
796-
* A function `f` mapping some interval $[a, b]$ into $\mathbb R$.
797-
* Two scalars `a` and `b` providing the limits of this interval.
798-
* An integer `n` determining the number of grid points.
799-
* A number `x` satisfying `a <= x <= b`.
800-
801-
and returns the [piecewise linear interpolation](https://en.wikipedia.org/wiki/Linear_interpolation) of `f` at `x`, based on `n` evenly spaced grid points `a = point[0] < point[1] < ... < point[n-1] = b`.
802-
803-
Aim for clarity, not efficiency.
804-
```
805-
806-
```{exercise-start}
807-
:label: pyess_ex6
808-
```
809-
810-
Using list comprehension syntax, we can simplify the loop in the following
811-
code.
812-
813-
```{code-cell} python3
814-
import numpy as np
815-
816-
n = 100
817-
ϵ_values = []
818-
for i in range(n):
819-
e = np.random.randn()
820-
ϵ_values.append(e)
821-
```
822-
823-
```{exercise-end}
824-
```
825-
826-
## Solutions
827-
828780
```{solution-start} pyess_ex1
829781
:class: dropdown
830782
```
@@ -884,10 +836,31 @@ sum([x % 2 == 0 and y % 2 == 0 for x, y in pairs])
884836
```{solution-end}
885837
```
886838

839+
```{exercise-start}
840+
:label: pyess_ex2
841+
```
842+
843+
Consider the polynomial
844+
845+
```{math}
846+
:label: polynom0
847+
848+
p(x)
849+
= a_0 + a_1 x + a_2 x^2 + \cdots a_n x^n
850+
= \sum_{i=0}^n a_i x^i
851+
```
852+
853+
Write a function `p` such that `p(x, coeff)` that computes the value in {eq}`polynom0` given a point `x` and a list of coefficients `coeff` ($a_1, a_2, \cdots a_n$).
854+
855+
Try to use `enumerate()` in your loop.
856+
857+
```{exercise-end}
858+
```
887859

888860
```{solution-start} pyess_ex2
889861
:class: dropdown
890862
```
863+
Here’s a solution:
891864

892865
```{code-cell} python3
893866
def p(x, coeff):
@@ -902,6 +875,14 @@ p(1, (2, 4))
902875
```
903876

904877

878+
```{exercise}
879+
:label: pyess_ex3
880+
881+
Write a function that takes a string as an argument and returns the number of capital letters in the string.
882+
883+
Hint: `'foo'.upper()` returns `'FOO'`.
884+
```
885+
905886
```{solution-start} pyess_ex3
906887
:class: dropdown
907888
```
@@ -932,6 +913,18 @@ count_uppercase_chars('The Rain in Spain')
932913
```
933914

934915

916+
917+
```{exercise}
918+
:label: pyess_ex4
919+
920+
Write a function that takes two sequences `seq_a` and `seq_b` as arguments and
921+
returns `True` if every element in `seq_a` is also an element of `seq_b`, else
922+
`False`.
923+
924+
* By "sequence" we mean a list, a tuple or a string.
925+
* Do the exercise without using [sets](https://docs.python.org/3/tutorial/datastructures.html#sets) and set methods.
926+
```
927+
935928
```{solution-start} pyess_ex4
936929
:class: dropdown
937930
```
@@ -940,14 +933,27 @@ Here's a solution:
940933

941934
```{code-cell} python3
942935
def f(seq_a, seq_b):
943-
is_subset = True
944936
for a in seq_a:
945937
if a not in seq_b:
946-
is_subset = False
947-
return is_subset
938+
return False
939+
return True
948940
949941
# == test == #
942+
print(f("ab", "cadb"))
943+
print(f("ab", "cjdb"))
944+
print(f([1, 2], [1, 2, 3]))
945+
print(f([1, 2, 3], [1, 2]))
946+
```
947+
948+
An alternative, more pythonic solution using `all()`:
949+
950+
```{code-cell} python3
951+
def f(seq_a, seq_b):
952+
return all([i in seq_b for i in seq_a])
950953
954+
# == test == #
955+
print(f("ab", "cadb"))
956+
print(f("ab", "cjdb"))
951957
print(f([1, 2], [1, 2, 3]))
952958
print(f([1, 2, 3], [1, 2]))
953959
```
@@ -963,9 +969,30 @@ def f(seq_a, seq_b):
963969
```
964970

965971

972+
```{exercise}
973+
:label: pyess_ex5
974+
975+
When we cover the numerical libraries, we will see they include many
976+
alternatives for interpolation and function approximation.
977+
978+
Nevertheless, let's write our own function approximation routine as an exercise.
979+
980+
In particular, without using any imports, write a function `linapprox` that takes as arguments
981+
982+
* A function `f` mapping some interval $[a, b]$ into $\mathbb R$.
983+
* Two scalars `a` and `b` providing the limits of this interval.
984+
* An integer `n` determining the number of grid points.
985+
* A number `x` satisfying `a <= x <= b`.
986+
987+
and returns the [piecewise linear interpolation](https://en.wikipedia.org/wiki/Linear_interpolation) of `f` at `x`, based on `n` evenly spaced grid points `a = point[0] < point[1] < ... < point[n-1] = b`.
988+
989+
Aim for clarity, not efficiency.
990+
```
991+
966992
```{solution-start} pyess_ex5
967993
:class: dropdown
968994
```
995+
Here’s a solution:
969996

970997
```{code-cell} python3
971998
def linapprox(f, a, b, n, x):
@@ -1008,6 +1035,26 @@ def linapprox(f, a, b, n, x):
10081035
```
10091036

10101037

1038+
```{exercise-start}
1039+
:label: pyess_ex6
1040+
```
1041+
1042+
Using list comprehension syntax, we can simplify the loop in the following
1043+
code.
1044+
1045+
```{code-cell} python3
1046+
import numpy as np
1047+
1048+
n = 100
1049+
ϵ_values = []
1050+
for i in range(n):
1051+
e = np.random.randn()
1052+
ϵ_values.append(e)
1053+
```
1054+
1055+
```{exercise-end}
1056+
```
1057+
10111058
```{solution-start} pyess_ex6
10121059
:class: dropdown
10131060
```

0 commit comments

Comments
 (0)