Skip to content

Commit 125a128

Browse files
committed
Adding disfunction
1 parent bf8880e commit 125a128

5 files changed

Lines changed: 106 additions & 6 deletions

File tree

book/book.tex

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
\newcommand{\thetitle}{Modeling and Simulation in Python}
1414
\newcommand{\thesubtitle}{}
1515
\newcommand{\theauthors}{Allen B. Downey}
16-
\newcommand{\theversion}{1.0}
16+
\newcommand{\theversion}{1.0.1}
1717

1818

1919
%%%% Both LATEX and PLASTEX
@@ -1417,9 +1417,10 @@ \section{Comparison operators}
14171417
Not equal & \py{!=} \\
14181418
\end{tabular}
14191419

1420-
The equals operator, \py{==}, compares two values and returns \py{True} if they are equal and \py{False} otherwise. It is easy to confuse with the {\bf assignment} operator, \py{=}, which assigns a value to a variable. For example, the following statement uses the assignment operator, which creates \py{x} if it doesn't already exist and gives it the value \py{5}
1420+
The equals operator, \py{==}, compares two values and returns \py{True} if they are equal and \py{False} otherwise. It is easy to confuse with the {\bf assignment operator}, \py{=}, which assigns a value to a variable. For example, the following statement uses the assignment operator, which creates \py{x} if it doesn't already exist and gives it the value \py{5}
14211421
\index{equality}
1422-
\index{assignment}
1422+
\index{assignment operator}
1423+
\index{operator!assignment}
14231424

14241425
\begin{python}
14251426
x = 5
@@ -1486,7 +1487,7 @@ \section{Metrics}
14861487

14871488
\begin{python}
14881489
bikeshare = System(olin=10, wellesley=2,
1489-
olin_empty=0, wellesley_empty=0)
1490+
olin_empty=0, wellesley_empty=0)
14901491
\end{python}
14911492

14921493
Now we can run a simulation like this:
@@ -1756,7 +1757,7 @@ \section{World population data}
17561757
\index{Series}
17571758
\index{DataFrame}
17581759

1759-
The Pandas function we'll use is \py{read_html}, which can read a web page and extract data from any tables it contains. Before we can use it, we have to {\bf import} it. You have already seen this import statement:
1760+
The Pandas function we'll use is \py{read_html}, which can read a web page and extract data from any tables it contains. Before we can use it, we have to import it. You have already seen this import statement:
17601761
\index{\py{read_html}}
17611762
\index{import statement}
17621763
\index{statement!import}
@@ -2039,6 +2040,8 @@ \section{Now with System objects}
20392040
\index{plot}
20402041
\index{decorate}
20412042

2043+
%TODO: We actually use decorate in chap01.ipynb, so move this earlier.
2044+
20422045
Finally, we can run it like this.
20432046

20442047
\begin{python}
@@ -2286,6 +2289,101 @@ \section{Equilibrium}
22862289
In the next chapter we use the models we have developed to generate predictions.
22872290

22882291

2292+
\section{Disfunctions}
2293+
2294+
When people first learn about functions, there are a few things they often find confusing. In this section I present and explain some common problems with functions.
2295+
2296+
As an example, suppose you want a function that takes a \py{System} object with variables \py{alpha} and \py{beta} as a parameter and computes the carrying capacity, \py{-alpha/beta}. Here's a good solution:
2297+
2298+
\begin{python}
2299+
def carrying_capacity(system):
2300+
K = -system.alpha / system.beta
2301+
return K
2302+
2303+
sys1 = System(alpha=0.025, beta=-0.0018)
2304+
pop = carrying_capacity(sys1)
2305+
print(pop)
2306+
\end{python}
2307+
2308+
Now let's see all the ways that can go wrong.
2309+
2310+
Disfunction \#1: Not using parameters. In the following version, the function doesn't take any parameters; when \py{system} appears inside the function, it refers to the object we created outside the function.
2311+
2312+
\begin{python}
2313+
# WRONG
2314+
def carrying_capacity():
2315+
K = -system.alpha / system.beta
2316+
return K
2317+
2318+
system = System(alpha=0.025, beta=-0.0018)
2319+
pop = carrying_capacity()
2320+
print(pop)
2321+
\end{python}
2322+
2323+
This version actually works, but it is not very versatile. If there are several \py{System} object, this function can only work with one of them; that is, as long as one of them is named \py{System}.
2324+
2325+
Disfunction \#2: Clobbering the parameters. When people first learn about parameters, they often write functions like this:
2326+
2327+
\begin{python}
2328+
# WRONG
2329+
def carrying_capacity(system):
2330+
system = System(alpha=0.025, beta=-0.0018)
2331+
K = -system.alpha / system.beta
2332+
return K
2333+
2334+
sys1 = System(alpha=0.025, beta=-0.0018)
2335+
pop = carrying_capacity(sys1)
2336+
print(pop)
2337+
\end{python}
2338+
2339+
In this example, we have a \py{System} object named \py{sys1} that gets passed as an argument to \py{carrying_capacity}. But when the function run, it ignores the argument and immediately replaces it with a new \py{System} object. As a result, this function always returns the same value, no matter what argument is passed.
2340+
2341+
When you write a function, you generally don't know what the values of the parameters will be. Your job is to write a function that works for any valid values. If you assign your own values to the parameters, you defeat the whole purpose of functions.
2342+
2343+
2344+
Disfunction \#3: No return value. Here's a version that computes the value of \py{K} but doesn't return it.
2345+
2346+
\begin{python}
2347+
# WRONG
2348+
def carrying_capacity(system):
2349+
K = -system.alpha / system.beta
2350+
2351+
sys1 = System(alpha=0.025, beta=-0.0018)
2352+
pop = carrying_capacity(sys1)
2353+
print(pop)
2354+
\end{python}
2355+
2356+
A function that doesn't have a return statement always returns \py{None}, so in this example the value of \py{pop} is \py{None}.
2357+
2358+
2359+
Disfunction \#4: Ignoring the return value. Finally, here's a version where the function is correct, but the way it's used is not.
2360+
2361+
\begin{python}
2362+
# WRONG
2363+
def carrying_capacity(system):
2364+
K = -system.alpha / system.beta
2365+
return K
2366+
2367+
sys1 = System(alpha=0.025, beta=-0.0018)
2368+
carrying_capacity(sys1)
2369+
print(K)
2370+
\end{python}
2371+
2372+
If you call a function that returns a value, you should do something with the return value. Often you assign it to a variable, as in the previous examples, but you can also use it as part of an expression. For example, you could eliminate the temporary variable \py{pop} like this:
2373+
2374+
\begin{python}
2375+
print(carrying_capacity(sys1))
2376+
\end{python}
2377+
2378+
Or if you had more than one system, you could compute the total carrying capacity like this:
2379+
2380+
\begin{python}
2381+
total = carrying_capacity(sys1) + carrying_capacity(sys2)
2382+
\end{python}
2383+
2384+
In the notebook for this chapter, you can try out each of these examples and see what happens.
2385+
2386+
22892387
\chapter{Prediction}
22902388

22912389
In the previous chapter we developed a quadratic model of world population growth from 1950 to 2015. It is a simple model, but it fits the data well and the mechanisms it's based on are plausible.
@@ -2689,7 +2787,7 @@ \section{Differential equations in SymPy}
26892787
%
26902788
\[ f{\left (t \right )} = C_{1} \exp(\alpha t) \]
26912789
%
2692-
This is the general solution, which still contains an unspecified constant, $C_1$. To get the particular solution where $f(0) = p_0$, we substitute \py{p0} for \py{C1}. First, we have to create two more symbols:
2790+
This is the {\bf general solution}, which still contains an unspecified constant, $C_1$. To get the {\bf particular solution} where $f(0) = p_0$, we substitute \py{p0} for \py{C1}. First, we have to create two more symbols:
26932791
\index{general solution}
26942792
\index{particular solution}
26952793

@@ -5736,6 +5834,8 @@ \section{Finishing off the problem}
57365834

57375835
The notebook provides some additional hints, but at this point you should have everything you need. Good luck!
57385836

5837+
If you enjoy this exercise, you might be interested in this paper: ``How to hit home runs: Optimum baseball bat swing parameters for maximum range trajectories", by Sawicki, Hubbard, and Stronge, at \url{http://aapt.scitation.org/doi/abs/10.1119/1.1604384}.
5838+
57395839

57405840
\chapter{Rotation}
57415841

book/figs/api_cheat_shee.odg

15.9 KB
Binary file not shown.

book/figs/github_work_flow.odg

43.4 KB
Binary file not shown.

book/figs/github_work_flow.pdf

39.3 KB
Binary file not shown.

book/figs/github_work_flow.png

111 KB
Loading

0 commit comments

Comments
 (0)