Release 0.6.3

This commit is contained in:
Alexander Hess 2020-02-05 18:35:13 +01:00
commit 8d525ba1ac
9 changed files with 1648 additions and 724 deletions

View file

@ -1437,7 +1437,7 @@
}
},
"source": [
"### Value"
"### Value / \"Meaning\""
]
},
{
@ -1448,7 +1448,7 @@
}
},
"source": [
"Almost trivially, every object also has a value to which it **evaluates** when referenced. We think of the value as the **conceptual idea** of what the $0$s and $1$s in the bag mean to *humans*.\n",
"Almost trivially, every object also has a value to which it **evaluates** when referenced. We think of the value as the **conceptual idea** of what the $0$s and $1$s in the bag mean to *humans*. In other words, an object's value regards its *semantic* meaning.\n",
"\n",
"For built-in data types, Python prints out an object's value as a so-called **[literal](https://docs.python.org/3/reference/lexical_analysis.html#literals)**: This means that we may copy and paste the value back into a code cell and create a *new* object with the *same* value."
]
@ -2981,7 +2981,7 @@
}
},
"source": [
"Variable names may contain upper and lower case letters, numbers, and underscores (i.e., `_`) and be as long as we want them to be. However, they must not begin with a number. Also, they must not be any of Python's built-in **[keywords](https://docs.python.org/3/reference/lexical_analysis.html#keywords)**.\n",
"Variable names may contain upper and lower case letters, numbers, and underscores (i.e., `_`) and be as long as we want them to be. However, they must not begin with a number. Also, they must not be any of Python's built-in **[keywords](https://docs.python.org/3/reference/lexical_analysis.html#keywords)** like `for` or `if`.\n",
"\n",
"Variable names should be chosen such that they do not need any more documentation and are self-explanatory. A widespread convention is to use so-called **[snake\\_case](https://en.wikipedia.org/wiki/Snake_case)**: Keep everything lowercase and use underscores to separate words.\n",
"\n",
@ -3734,7 +3734,7 @@
" - include [built-in functions](https://docs.python.org/3/library/functions.html) like [print()](https://docs.python.org/3/library/functions.html#print), [sum()](https://docs.python.org/3/library/functions.html#sum), or [len()](https://docs.python.org/3/library/functions.html#len)\n",
"\n",
"\n",
"- flow control (cf., [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_00_lecture.ipynb))\n",
"- flow control (cf., [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_00_lecture.ipynb) and [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_lecture.ipynb))\n",
" - expression of **business logic** or an **algorithm**\n",
" - conditional execution of parts of a program (e.g., `if` statements)\n",
" - repetitive execution of parts of a program (e.g., `for`-loops)"

View file

@ -88,7 +88,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: Lastly, what does the `end=\"\\n\"` mean in the documentation? Use it in the `for`-loop and print the numbers 1 through 10 in just *one* line!"
"**Q3**: Lastly, what does the `end=\"\\n\"` mean in the documentation? Use it in the `for`-loop and print the numbers 1 through 10 in just *one* line of output!"
]
},
{

File diff suppressed because it is too large Load diff

View file

@ -67,7 +67,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: What does it mean for a variable to **go out of scope**?"
"**Q3**: What does it mean for a variable to go out of **scope**?"
]
},
{
@ -95,7 +95,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: Explain the concept of **forwarding** a function **call**."
"**Q5**: Explain the concept of **forwarding** a **function call**."
]
},
{
@ -119,6 +119,20 @@
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: What are **callables**? How do they relate to `function` objects?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -137,7 +151,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: A mere function **call** is just an **expression**."
"**Q8**: A mere function **call** is just an **expression**."
]
},
{
@ -151,7 +165,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: When using the `import` statement, we need to ensure that the imported attributes do **not** overwrite any already defined variables and functions."
"**Q9**: When using the `import` statement, we need to ensure that the imported attributes do *not* overwrite any already defined variables and functions."
]
},
{
@ -165,7 +179,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9:** Functions always have a name by which we can call them."
"**Q10:** Functions always have a name by which we can call them."
]
},
{
@ -179,7 +193,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: The [standard library](https://docs.python.org/3/library/index.html) is a collection of numerical tools often used in scientific computing, for example, advanced mathematical functions or utilities for simulation."
"**Q11**: The [standard library](https://docs.python.org/3/library/index.html) is a collection of numerical tools often used in scientific computing, for example, advanced mathematical functions or utilities for simulation."
]
},
{

View file

@ -32,7 +32,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.1**: The [volume of a sphere](https://en.wikipedia.org/wiki/Sphere) is defined as $\\frac{4}{3} * \\pi * r^3$. Calculate this value for $r=10.0$ and round it to 10 digits after the comma. Use the [standard library](https://docs.python.org/3/library/index.html) to obtain a good approximation of $\\pi$."
"**Q1**: The [volume of a sphere](https://en.wikipedia.org/wiki/Sphere) is defined as $\\frac{4}{3} * \\pi * r^3$. Calculate this value for $r=10.0$ and round it to 10 digits after the comma. Use the [standard library](https://docs.python.org/3/library/index.html) to obtain a good approximation of $\\pi$."
]
},
{
@ -66,7 +66,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.2**: Encapsulate the logic into a function `sphere_volume()` that takes one *positional* argument `radius` and one *keyword-only* argument `digits` defaulting to `5`. The volume should be returned as a `float` object under *all* circumstances. Document your work appropriately in a docstring according to [Google's Python Style Guide](https://github.com/google/styleguide/blob/gh-pages/pyguide.md)."
"**Q2**: Encapsulate the logic into a function `sphere_volume()` that takes one *positional* argument `radius` and one *keyword-only* argument `digits` defaulting to `5`. The volume should be returned as a `float` object under *all* circumstances. Document your work appropriately in a docstring according to [Google's Python Style Guide](https://github.com/google/styleguide/blob/gh-pages/pyguide.md)."
]
},
{
@ -83,7 +83,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.3**: Evaluate the function with `radius = 100.0` and 1, 5, 10, 15, and 20 digits respectively."
"**Q3**: Evaluate the function with `radius = 100.0` and 1, 5, 10, 15, and 20 digits respectively."
]
},
{
@ -144,7 +144,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.4**: What observation do you make?"
"**Q4**: What observation do you make?"
]
},
{
@ -158,7 +158,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.5**: Using the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in, write a `for`-loop and calculate the volume of a sphere with `radius = 42.0` for all `digits` from `1` through `20`. Print out each volume on a separate line.\n",
"**Q5**: Using the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in, write a `for`-loop and calculate the volume of a sphere with `radius = 42.0` for all `digits` from `1` through `20`. Print out each volume on a separate line.\n",
"\n",
"Note: This is the first task where you need to use the built-in [print()](https://docs.python.org/3/library/functions.html#print) function."
]
@ -186,7 +186,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.6**: What lesson do you learn about the `float` type?"
"**Q6**: What lesson do you learn about the `float` type?"
]
},
{

View file

@ -124,7 +124,7 @@
}
},
"source": [
"A `str` object evaluates to itself in a literal notation with enclosing **single quotes** `'` by default. In [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_lecture.ipynb#Value), we already specified the double quotes `\"` convention we stick to in this book. Yet, single quotes `'` and double quotes `\"` are *perfect* substitutes for all `str` objects that do *not* contain any of the two symbols in it. We could use the reverse convention, as well.\n",
"A `str` object evaluates to itself in a literal notation with enclosing **single quotes** `'` by default. In [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_lecture.ipynb#Value-/-\"Meaning\"), we already specified the double quotes `\"` convention we stick to in this book. Yet, single quotes `'` and double quotes `\"` are *perfect* substitutes for all `str` objects that do *not* contain any of the two symbols in it. We could use the reverse convention, as well.\n",
"\n",
"As [this discussion](https://stackoverflow.com/questions/56011/single-quotes-vs-double-quotes-in-python) shows, many programmers have *strong* opinions about that and make up *new* conventions for their projects. Consequently, the discussion was \"closed as not constructive\" by the moderators."
]

View file

@ -45,7 +45,7 @@
"source": [
"A *mapping* is a one-to-one correspondence from a set of **keys** to a set of **values**. In other words, a *mapping* is a *collection* of **key-value pairs**, also called **items** for short.\n",
"\n",
"In the context of mappings, the term *value* has a meaning different from the general *value* that *every* object has: In the \"bag\" analogy from [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_lecture.ipynb#Value), we descibe an object's value to be the concrete $0$s and $1$s it contains. Here, the terms *key* and *value* mean the *role* an object takes within a mapping. Both, *keys* and *values*, are real *objects* with a distinct *value*. So, the student should always remember the double meaning of the term *value* in this chapter!\n",
"In the context of mappings, the term *value* has a meaning different from the general *value* that *every* object has: In the \"bag\" analogy from [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_lecture.ipynb#Value-/-\"Meaning\"), we descibe an object's value to be the concrete $0$s and $1$s it contains. Here, the terms *key* and *value* mean the *role* an object takes within a mapping. Both, *keys* and *values*, are real *objects* with a distinct *value*. So, the student should always remember the double meaning of the term *value* in this chapter!\n",
"\n",
"Let's continue with an example. To create a `dict` object, we commonly use the literal notation, `{..: .., ..: .., ...}`, and list all the items. `to_words` below maps the `int` objects `0`, `1`, and `2` to their English word equivalents, `\"zero\"`, `\"one\"`, and `\"two\"`, and `from_words` does the opposite. A stylistic side note: Pythonistas often expand `dict` or `list` definitions by writing each item or element on a line on their own. The commas `,` after the *last* items are *not* a mistake, as well, although they *may* be left out. Besides easier reading, such style has actual technical advantages (cf., [source](https://www.python.org/dev/peps/pep-0008/#when-to-use-trailing-commas)) that we do not go into detail about here."
]
@ -707,7 +707,7 @@
}
},
"source": [
"The [glossary](https://docs.python.org/3/glossary.html#term-hashable) states a second requirement for hashability, namely that \"objects which *compare equal* must have the *same* hash value.\" The purpose of this is to ensure that if we put, for example, `1` as a key in a `dict` object, we can look it up later with `1.0`. In other words, we can look up keys by their object's value (i.e., in the meaning of [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_lecture.ipynb#Value)). The converse statement does *not* hold: Two objects *may* (accidentally) have the *same* hash value and *not* compare equal."
"The [glossary](https://docs.python.org/3/glossary.html#term-hashable) states a second requirement for hashability, namely that \"objects which *compare equal* must have the *same* hash value.\" The purpose of this is to ensure that if we put, for example, `1` as a key in a `dict` object, we can look it up later with `1.0`. In other words, we can look up keys by their object's value (i.e., in the meaning of [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_lecture.ipynb#Value-/-\"Meaning\")). The converse statement does *not* hold: Two objects *may* (accidentally) have the *same* hash value and *not* compare equal."
]
},
{

View file

@ -1,6 +1,6 @@
[tool.poetry]
name = "intro-to-python"
version = "0.6.2"
version = "0.6.3"
description = "An introduction to Python and programming for wanna-be data scientists"
authors = ["Alexander Hess <alexander@webartifex.biz>"]
license = "MIT"

View file

@ -15,16 +15,17 @@ be used outside the module with a single underscore "_". This way, we can
design the code within a module in a modular fashion and only "export" what we
want.
Here, all three functions internally forward the computation to an internal
utility function _scaled_average() that contains all the logic common to the
three functions. Also, we define one _default_scalar variable that is used as
the default for the scalar parameter in each of the functions.
Here, all three functions internally forward parts of their computations
to the utility functions _round_all() and _scaled_average() that contain all
the logic common to the three functions.
While this example is stylized, it shows how Python modules are often
designed.
"""
_default_scalar = 1
def _round_all(numbers):
"""Internal utility function to round all numbers in a list."""
return [round(n) for n in numbers]
def _scaled_average(numbers, scalar):
@ -33,43 +34,43 @@ def _scaled_average(numbers, scalar):
return scalar * average
def average(numbers, *, scalar=_default_scalar):
def average(numbers, *, scalar=1):
"""Calculate the average of all numbers in a list.
Args:
numbers (list): list of numbers; may be integers or floats
scalar (float, optional): the scalar that multiplies the
average of the even numbers
numbers (list of int's/float's): numbers to be averaged;
if non-whole numbers are provided, they are rounded
scalar (float, optional): multiplies the average; defaults to 1
Returns:
float: (scaled) average
"""
return _scaled_average(numbers, scalar)
return _scaled_average(_round_all(numbers), scalar)
def average_evens(numbers, *, scalar=_default_scalar):
def average_evens(numbers, *, scalar=1):
"""Calculate the average of all even numbers in a list.
Args:
numbers (list): list of numbers; may be integers or floats
scalar (float, optional): the scalar that multiplies the
average of the even numbers
numbers (list of int's/float's): numbers to be averaged;
if non-whole numbers are provided, they are rounded
scalar (float, optional): multiplies the average; defaults to 1
Returns:
float: (scaled) average
"""
return _scaled_average([n for n in numbers if n % 2 == 0], scalar)
return _scaled_average([n for n in _round_all(numbers) if n % 2 == 0], scalar)
def average_odds(numbers, *, scalar=_default_scalar):
def average_odds(numbers, *, scalar=1):
"""Calculate the average of all odd numbers in a list.
Args:
numbers (list): list of numbers; may be integers or floats
scalar (float, optional): the scalar that multiplies the
average of the even numbers
numbers (list of int's/float's): numbers to be averaged;
if non-whole numbers are provided, they are rounded
scalar (float, optional): multiplies the average; defaults to 1
Returns:
float: (scaled) average
"""
return _scaled_average([n for n in numbers if n % 2 != 0], scalar)
return _scaled_average([n for n in _round_all(numbers) if n % 2 != 0], scalar)