ktongue/docker_container / numerical-mooc /lessons /04_spreadout /04_00_Python_Function_Quirks.ipynb
download
raw
13.8 kB
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### Content under Creative Commons Attribution license CC-BY 4.0, code under MIT license (c)2015 G.F. Forsyth."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Python Names"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We introduced functions way back in Module 1 and they have served us well (and will continue to do so!). There are a few behaviors that bear closer examination before we dive too deeply into the next lessons. These are all common Python gotchas! that will continue to rear their heads, so it's better that you know about them now to avoid a large amount of hair-pulling when they crop up. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There is a [fantastic talk](https://www.youtube.com/watch?v=_AEJHKGk9ns) from PyCon 2015 by Ned Batchelder on YouTube that will walk you through all of the things below and more, but we'll also include a short summary of some of the issues."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Assigning variables"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When we want a variable `x` to have a value of 5, we assign the *name* `x` to the *value* `5`."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5\n"
]
}
],
"source": [
"x = 5\n",
"print(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Integers are immutable. They don't change. If we assign another name `y` to be equal to `x`, there is no operation we can perform on `y` that will change `x` (or the 5). "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5\n",
"5\n"
]
}
],
"source": [
"y = x\n",
"print(y)\n",
"print(x)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6\n",
"5\n"
]
}
],
"source": [
"y += 1\n",
"print(y)\n",
"print(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Some datatypes *are* mutable, however, and that's where the trouble can start. If instead of an integer, `x` points to a list (lists are mutable), then things are different."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 2, 3, 5]\n"
]
}
],
"source": [
"x = [1, 2, 3]\n",
"y = x\n",
"y.append(5)\n",
"print(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What happened? We created a list `[1, 2, 3]` and pointed the name `x` at it. Then we pointed the name `y` at the *same* list. When we add a value to the list, there is only the one list, so the changes to it are reflected whether we ask for it by its first name, `x`, or its second name, `y`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## What does this have to do with functions?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A reasonable question. When you call a function and send it a few names (inputs), that action doesn't create copies of the objects that those names point to. It just creates a *new* name that points at the *same* data.\n",
"\n",
"Let's create a simple function that adds a value to a list and then returns a \"copy\" of that list."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def add_to_list(mylist):\n",
" mylist.append(7)\n",
" \n",
" newlist = mylist.copy()\n",
" \n",
" return newlist"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"mylist = [1, 2, 3]\n",
"newlist = add_to_list(mylist)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We send in `mylist`, make a change to it, then make a copy of it and return the copy. But we didn't return `mylist` so those changes are discarded, right?"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 2, 3, 7]\n"
]
}
],
"source": [
"print(newlist)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 2, 3, 7]\n"
]
}
],
"source": [
"print(mylist)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wrong. We sent in the name `mylist` and then appended a value to it. At that point, the list has been changed. We used the `copy()` command to create `newlist`, so it points to a different list than `mylist`, but `mylist` has still been altered by the function. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## What if we change the names?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Is this because the function expects a list named `mylist` and that is what we sent? Alas, no. "
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2, 4, 2, 7]\n"
]
}
],
"source": [
"T = [2, 4, 2]\n",
"newlist = add_to_list(T)\n",
"print(T)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When we send the name `T` to the function `add_to_list`, the function creates the new name `mylist` and points it to the same list that `T` points to."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## What do we do?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The most important thing is to be aware of this behavior. It's a feature of the language and it doesn't often cause problems, but you need to know about it for when it does cause problems. "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<link href='http://fonts.googleapis.com/css?family=Alegreya+Sans:100,300,400,500,700,800,900,100italic,300italic,400italic,500italic,700italic,800italic,900italic' rel='stylesheet' type='text/css'>\n",
"<link href='http://fonts.googleapis.com/css?family=Arvo:400,700,400italic' rel='stylesheet' type='text/css'>\n",
"<link href='http://fonts.googleapis.com/css?family=PT+Mono' rel='stylesheet' type='text/css'>\n",
"<link href='http://fonts.googleapis.com/css?family=Shadows+Into+Light' rel='stylesheet' type='text/css'>\n",
"<link href='http://fonts.googleapis.com/css?family=Nixie+One' rel='stylesheet' type='text/css'>\n",
"<link href='https://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'>\n",
"<style>\n",
"\n",
"@font-face {\n",
" font-family: \"Computer Modern\";\n",
" src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');\n",
"}\n",
"\n",
"#notebook_panel { /* main background */\n",
" background: rgb(245,245,245);\n",
"}\n",
"\n",
"div.cell { /* set cell width */\n",
" width: 750px;\n",
"}\n",
"\n",
"div #notebook { /* centre the content */\n",
" background: #fff; /* white background for content */\n",
" width: 1000px;\n",
" margin: auto;\n",
" padding-left: 0em;\n",
"}\n",
"\n",
"#notebook li { /* More space between bullet points */\n",
" margin-top:0.8em;\n",
"}\n",
"\n",
"/* draw border around running cells */\n",
"div.cell.border-box-sizing.code_cell.running { \n",
" border: 1px solid #111;\n",
"}\n",
"\n",
"/* Put a solid color box around each cell and its output, visually linking them*/\n",
"div.cell.code_cell {\n",
" background-color: rgb(256,256,256); \n",
" border-radius: 0px; \n",
" padding: 0.5em;\n",
" margin-left:1em;\n",
" margin-top: 1em;\n",
"}\n",
"\n",
"div.text_cell_render{\n",
" font-family: 'Alegreya Sans' sans-serif;\n",
" line-height: 140%;\n",
" font-size: 125%;\n",
" font-weight: 400;\n",
" width:600px;\n",
" margin-left:auto;\n",
" margin-right:auto;\n",
"}\n",
"\n",
"\n",
"/* Formatting for header cells */\n",
".text_cell_render h1 {\n",
" font-family: 'Nixie One', serif;\n",
" font-style:regular;\n",
" font-weight: 400; \n",
" font-size: 45pt;\n",
" line-height: 100%;\n",
" color: rgb(0,51,102);\n",
" margin-bottom: 0.5em;\n",
" margin-top: 0.5em;\n",
" display: block;\n",
"}\n",
"\n",
".text_cell_render h2 {\n",
" font-family: 'Nixie One', serif;\n",
" font-weight: 400;\n",
" font-size: 30pt;\n",
" line-height: 100%;\n",
" color: rgb(0,51,102);\n",
" margin-bottom: 0.1em;\n",
" margin-top: 0.3em;\n",
" display: block;\n",
"}\t\n",
"\n",
".text_cell_render h3 {\n",
" font-family: 'Nixie One', serif;\n",
" margin-top:16px;\n",
" font-size: 22pt;\n",
" font-weight: 600;\n",
" margin-bottom: 3px;\n",
" font-style: regular;\n",
" color: rgb(102,102,0);\n",
"}\n",
"\n",
".text_cell_render h4 { /*Use this for captions*/\n",
" font-family: 'Nixie One', serif;\n",
" font-size: 14pt;\n",
" text-align: center;\n",
" margin-top: 0em;\n",
" margin-bottom: 2em;\n",
" font-style: regular;\n",
"}\n",
"\n",
".text_cell_render h5 { /*Use this for small titles*/\n",
" font-family: 'Nixie One', sans-serif;\n",
" font-weight: 400;\n",
" font-size: 16pt;\n",
" color: rgb(163,0,0);\n",
" font-style: italic;\n",
" margin-bottom: .1em;\n",
" margin-top: 0.8em;\n",
" display: block;\n",
"}\n",
"\n",
".text_cell_render h6 { /*use this for copyright note*/\n",
" font-family: 'PT Mono', sans-serif;\n",
" font-weight: 300;\n",
" font-size: 9pt;\n",
" line-height: 100%;\n",
" color: grey;\n",
" margin-bottom: 1px;\n",
" margin-top: 1px;\n",
"}\n",
"\n",
".CodeMirror{\n",
" font-family: \"Source Code Pro\";\n",
" font-size: 90%;\n",
"}\n",
"\n",
".alert-box {\n",
" padding:10px 10px 10px 36px;\n",
" margin:5px;\n",
"}\n",
"\n",
".success {\n",
" color:#666600;\n",
" background:rgb(240,242,229);\n",
"}\n",
"</style>\n",
"\n",
"<script>\n",
" MathJax.Hub.Config({\n",
" TeX: {\n",
" extensions: [\"AMSmath.js\"],\n",
" equationNumbers: { autoNumber: \"AMS\", useLabelIds: true}\n",
" },\n",
" tex2jax: {\n",
" inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ],\n",
" displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ]\n",
" },\n",
" displayAlign: 'center', // Change this to 'center' to center equations.\n",
" \"HTML-CSS\": {\n",
" styles: {'.MathJax_Display': {\"margin\": 4}}\n",
" }\n",
" });\n",
" MathJax.Hub.Queue(\n",
" [\"resetEquationNumbers\", MathJax.InputJax.TeX],\n",
" [\"PreProcess\", MathJax.Hub],\n",
" [\"Reprocess\", MathJax.Hub]\n",
" );\n",
"</script>\n"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from IPython.core.display import HTML\n",
"css_file = '../../styles/numericalmoocstyle.css'\n",
"HTML(open(css_file, 'r').read())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (MOOC)",
"language": "python",
"name": "py36-mooc"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

Xet Storage Details

Size:
13.8 kB
·
Xet hash:
18d7ebbd3d2e387c9836297ba373af0692f1216bb6a7513dfdeeda2625e7c0e9

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.