2 new sections

This commit is contained in:
rasbt 2014-05-03 14:51:53 -04:00
parent cb5853e6da
commit 34175c785a
2 changed files with 1112 additions and 8 deletions

View File

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:3b7a6d43400c23d25d965b726e6fba3db0b9b0d2d0bbad73c96b8857f8eaa7ee"
"signature": "sha256:0e1c6e74b301e23ea4146d660afb3f07765686c6c7fa4752f3a4495da7949787"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -13,7 +13,7 @@
"metadata": {},
"source": [
"Sebastian Raschka \n",
"last updated: 05/02/2014 ([Changelog](#changelog))\n",
"last updated: 05/03/2014 ([Changelog](#changelog))\n",
"\n",
"[Link to this IPython Notebook on GitHub](https://github.com/rasbt/python_reference/blob/master/not_so_obvious_python_stuff.ipynb)\n",
"\n",
@ -83,7 +83,9 @@
"- [Assigning types to variables as values](#variable_types)\n",
"- [Only the first clause of generators is evaluated immediately](#generator_rhs)\n",
"- [Keyword argument unpacking syntax - `*args` and `**kwargs`](#splat_op)\n",
"- [Metaclasses - What creates a new instance of a class?](#new_instance)"
"- [Metaclasses - What creates a new instance of a class?](#new_instance)\n",
"- [Else-clauses: \"conditional else\" and \"completion else\"](#else_clauses)\n",
"- [Interning of compile-time constants vs. run-time expressions](#string_interning)"
]
},
{
@ -3278,6 +3280,13 @@
"## Metaclasses - What creates a new instance of a class?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[[back to top](#sections)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -3361,6 +3370,545 @@
],
"prompt_number": 54
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in range(5):\n",
" if i == 1:\n",
" print('in for')\n",
"else:\n",
" print('in else')\n",
"print('after for-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"in for\n",
"in else\n",
"after for-loop\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in range(5):\n",
" if i == 1:\n",
" break\n",
"else:\n",
" print('in else')\n",
"print('after for-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"after for-loop\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a name=\"else_clauses\"></a>\n",
"<br>\n",
"<br>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Else-clauses: \"conditional else\" and \"completion else\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[[back to top](#sections)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I would claim that the conditional \"else\" is every programmer's daily bread and butter. However, there is a second flavor of \"else\"-clauses in Python, which I will call \"completion else\" (for reason that will become clear later). \n",
"But first, let us take a look at our \"traditional\" conditional else that we all are familiar with. \n",
"### Conditional else:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# conditional else\n",
"\n",
"a_list = [1,2]\n",
"if a_list[0] == 1:\n",
" print('Hello, World!')\n",
"else:\n",
" print('Bye, World!')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Hello, World!\n"
]
}
],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# conditional else\n",
"\n",
"a_list = [1,2]\n",
"if a_list[0] == 2:\n",
" print('Hello, World!')\n",
"else:\n",
" print('Bye, World!')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Bye, World!\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Why am I showing those simple examples? I think they are good to highlight some of the key points: It is **either** the code under the `if` clause that is executed, **or** the code under the `else` block, but not both. \n",
"If the condition of the `if` clause evaluates to `True`, the `if`-block is exectured, and if it evaluated to `False`, it is the `else` block. \n",
"\n",
"### Completion else\n",
"**In contrast** to the **either...or*** situation that we know from the conditional `else`, the completion `else` is executed if a code block finished. \n",
"To show you an example, let us use `else` for error-handling:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Completion else (try-except)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"try:\n",
" print('first element:', a_list[0])\n",
"except IndexError:\n",
" print('raised IndexError')\n",
"else:\n",
" print('no error in try-block')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"first element: 1\n",
"no error in try-block\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"try:\n",
" print('third element:', a_list[2])\n",
"except IndexError:\n",
" print('raised IndexError')\n",
"else:\n",
" print('no error in try-block')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"raised IndexError\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"In the code above, we can see that the code under the **`else`-clause is only executed if the `try-block` was executed without encountering an error, i.e., if the `try`-block is \"complete\".** \n",
"The same rule applies to the \"completion\" `else` in while- and for-loops, which you can confirm in the following samples below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Completion else (while-loop)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"i = 0\n",
"while i < 2:\n",
" print(i)\n",
" i += 1\n",
"else:\n",
" print('in else')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0\n",
"1\n",
"in else\n"
]
}
],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"i = 0\n",
"while i < 2:\n",
" print(i)\n",
" i += 1\n",
" break\n",
"else:\n",
" print('completed while-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0\n"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Completion else (for-loop)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in range(2):\n",
" print(i)\n",
"else:\n",
" print('completed for-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0\n",
"1\n",
"completed for-loop\n"
]
}
],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in range(2):\n",
" print(i)\n",
" break\n",
"else:\n",
" print('completed for-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0\n"
]
}
],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a name=\"string_interning\"></a>\n",
"<br>\n",
"<br>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Interning of compile-time constants vs. run-time expressions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[[back to top](#sections)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This might not be particularly useful, but it is nonetheless interesting: Python's interpreter is interning compile-time constants but not run-time expressions (note that this is implementation-specific).\n",
"\n",
"(Original source: [Stackoverflow](http://stackoverflow.com/questions/15541404/python-string-interning))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us have a look at the simple example below. Here we are creating 3 variables and assign the value \"Hello\" to them in different ways before we test them for identity."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"hello1 = 'Hello'\n",
"\n",
"hello2 = 'Hell' + 'o'\n",
"\n",
"hello3 = 'Hell'\n",
"hello3 = hello3 + 'o'\n",
"\n",
"print('hello1 is hello2:', hello1 is hello2)\n",
"print('hello1 is hello3:', hello1 is hello3)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"hello1 is hello2: True\n",
"hello1 is hello3: False\n"
]
}
],
"prompt_number": 34
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, how does it come that the first expression evaluates to true, but the second does not? To answer this question, we need to take a closer look at the underlying byte codes:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import dis\n",
"def hello1_func():\n",
" s = 'Hello'\n",
" return s\n",
"dis.dis(hello1_func)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 3 0 LOAD_CONST 1 ('Hello')\n",
" 3 STORE_FAST 0 (s)\n",
"\n",
" 4 6 LOAD_FAST 0 (s)\n",
" 9 RETURN_VALUE\n"
]
}
],
"prompt_number": 38
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def hello2_func():\n",
" s = 'Hell' + 'o'\n",
" return s\n",
"dis.dis(hello2_func)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 2 0 LOAD_CONST 3 ('Hello')\n",
" 3 STORE_FAST 0 (s)\n",
"\n",
" 3 6 LOAD_FAST 0 (s)\n",
" 9 RETURN_VALUE\n"
]
}
],
"prompt_number": 39
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def hello3_func():\n",
" s = 'Hell'\n",
" s = s + 'o'\n",
" return s\n",
"dis.dis(hello3_func)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 2 0 LOAD_CONST 1 ('Hell')\n",
" 3 STORE_FAST 0 (s)\n",
"\n",
" 3 6 LOAD_FAST 0 (s)\n",
" 9 LOAD_CONST 2 ('o')\n",
" 12 BINARY_ADD\n",
" 13 STORE_FAST 0 (s)\n",
"\n",
" 4 16 LOAD_FAST 0 (s)\n",
" 19 RETURN_VALUE\n"
]
}
],
"prompt_number": 40
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"It looks like that `'Hello'` and `'Hell'` + `'o'` are both evaluated and stored as `'Hello'` at compile-time, whereas the third version \n",
"`s = 'Hell'` \n",
"`s = s + 'o'` seems to be not interned. Let us quickly confirm the behavior with the following code:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print(hello1_func() is hello2_func())\n",
"print(hello1_func() is hello3_func())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"True\n",
"False\n"
]
}
],
"prompt_number": 42
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, to show that this hypothesis is the answer to this rather unexpected observation, let us `intern` the value manually:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import sys\n",
"\n",
"print(hello1_func() is sys.intern(hello3_func()))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"True\n"
]
}
],
"prompt_number": 45
},
{
"cell_type": "markdown",
"metadata": {},
@ -3390,8 +3938,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 05/03/2014\n",
"- new section: else clauses: conditional vs. completion\n",
"- new section: Interning of compile-time constants vs. run-time expressions\n",
"\n",
"#### 05/02/2014\n",
"- new section in Python 3.x and Python 2.x key differences: for-loop leak<\n",
"- new section in Python 3.x and Python 2.x key differences: for-loop leak\n",
"- new section: Metaclasses - What creates a new instance of a class? \n",
"\n",
"#### 05/01/2014\n",

View File

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:3b7a6d43400c23d25d965b726e6fba3db0b9b0d2d0bbad73c96b8857f8eaa7ee"
"signature": "sha256:0e1c6e74b301e23ea4146d660afb3f07765686c6c7fa4752f3a4495da7949787"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -13,7 +13,7 @@
"metadata": {},
"source": [
"Sebastian Raschka \n",
"last updated: 05/02/2014 ([Changelog](#changelog))\n",
"last updated: 05/03/2014 ([Changelog](#changelog))\n",
"\n",
"[Link to this IPython Notebook on GitHub](https://github.com/rasbt/python_reference/blob/master/not_so_obvious_python_stuff.ipynb)\n",
"\n",
@ -83,7 +83,9 @@
"- [Assigning types to variables as values](#variable_types)\n",
"- [Only the first clause of generators is evaluated immediately](#generator_rhs)\n",
"- [Keyword argument unpacking syntax - `*args` and `**kwargs`](#splat_op)\n",
"- [Metaclasses - What creates a new instance of a class?](#new_instance)"
"- [Metaclasses - What creates a new instance of a class?](#new_instance)\n",
"- [Else-clauses: \"conditional else\" and \"completion else\"](#else_clauses)\n",
"- [Interning of compile-time constants vs. run-time expressions](#string_interning)"
]
},
{
@ -3278,6 +3280,13 @@
"## Metaclasses - What creates a new instance of a class?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[[back to top](#sections)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -3361,6 +3370,545 @@
],
"prompt_number": 54
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in range(5):\n",
" if i == 1:\n",
" print('in for')\n",
"else:\n",
" print('in else')\n",
"print('after for-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"in for\n",
"in else\n",
"after for-loop\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in range(5):\n",
" if i == 1:\n",
" break\n",
"else:\n",
" print('in else')\n",
"print('after for-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"after for-loop\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a name=\"else_clauses\"></a>\n",
"<br>\n",
"<br>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Else-clauses: \"conditional else\" and \"completion else\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[[back to top](#sections)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I would claim that the conditional \"else\" is every programmer's daily bread and butter. However, there is a second flavor of \"else\"-clauses in Python, which I will call \"completion else\" (for reason that will become clear later). \n",
"But first, let us take a look at our \"traditional\" conditional else that we all are familiar with. \n",
"### Conditional else:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# conditional else\n",
"\n",
"a_list = [1,2]\n",
"if a_list[0] == 1:\n",
" print('Hello, World!')\n",
"else:\n",
" print('Bye, World!')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Hello, World!\n"
]
}
],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# conditional else\n",
"\n",
"a_list = [1,2]\n",
"if a_list[0] == 2:\n",
" print('Hello, World!')\n",
"else:\n",
" print('Bye, World!')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Bye, World!\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Why am I showing those simple examples? I think they are good to highlight some of the key points: It is **either** the code under the `if` clause that is executed, **or** the code under the `else` block, but not both. \n",
"If the condition of the `if` clause evaluates to `True`, the `if`-block is exectured, and if it evaluated to `False`, it is the `else` block. \n",
"\n",
"### Completion else\n",
"**In contrast** to the **either...or*** situation that we know from the conditional `else`, the completion `else` is executed if a code block finished. \n",
"To show you an example, let us use `else` for error-handling:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Completion else (try-except)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"try:\n",
" print('first element:', a_list[0])\n",
"except IndexError:\n",
" print('raised IndexError')\n",
"else:\n",
" print('no error in try-block')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"first element: 1\n",
"no error in try-block\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"try:\n",
" print('third element:', a_list[2])\n",
"except IndexError:\n",
" print('raised IndexError')\n",
"else:\n",
" print('no error in try-block')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"raised IndexError\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"In the code above, we can see that the code under the **`else`-clause is only executed if the `try-block` was executed without encountering an error, i.e., if the `try`-block is \"complete\".** \n",
"The same rule applies to the \"completion\" `else` in while- and for-loops, which you can confirm in the following samples below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Completion else (while-loop)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"i = 0\n",
"while i < 2:\n",
" print(i)\n",
" i += 1\n",
"else:\n",
" print('in else')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0\n",
"1\n",
"in else\n"
]
}
],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"i = 0\n",
"while i < 2:\n",
" print(i)\n",
" i += 1\n",
" break\n",
"else:\n",
" print('completed while-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0\n"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Completion else (for-loop)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in range(2):\n",
" print(i)\n",
"else:\n",
" print('completed for-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0\n",
"1\n",
"completed for-loop\n"
]
}
],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in range(2):\n",
" print(i)\n",
" break\n",
"else:\n",
" print('completed for-loop')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0\n"
]
}
],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a name=\"string_interning\"></a>\n",
"<br>\n",
"<br>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Interning of compile-time constants vs. run-time expressions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[[back to top](#sections)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This might not be particularly useful, but it is nonetheless interesting: Python's interpreter is interning compile-time constants but not run-time expressions (note that this is implementation-specific).\n",
"\n",
"(Original source: [Stackoverflow](http://stackoverflow.com/questions/15541404/python-string-interning))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us have a look at the simple example below. Here we are creating 3 variables and assign the value \"Hello\" to them in different ways before we test them for identity."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"hello1 = 'Hello'\n",
"\n",
"hello2 = 'Hell' + 'o'\n",
"\n",
"hello3 = 'Hell'\n",
"hello3 = hello3 + 'o'\n",
"\n",
"print('hello1 is hello2:', hello1 is hello2)\n",
"print('hello1 is hello3:', hello1 is hello3)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"hello1 is hello2: True\n",
"hello1 is hello3: False\n"
]
}
],
"prompt_number": 34
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, how does it come that the first expression evaluates to true, but the second does not? To answer this question, we need to take a closer look at the underlying byte codes:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import dis\n",
"def hello1_func():\n",
" s = 'Hello'\n",
" return s\n",
"dis.dis(hello1_func)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 3 0 LOAD_CONST 1 ('Hello')\n",
" 3 STORE_FAST 0 (s)\n",
"\n",
" 4 6 LOAD_FAST 0 (s)\n",
" 9 RETURN_VALUE\n"
]
}
],
"prompt_number": 38
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def hello2_func():\n",
" s = 'Hell' + 'o'\n",
" return s\n",
"dis.dis(hello2_func)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 2 0 LOAD_CONST 3 ('Hello')\n",
" 3 STORE_FAST 0 (s)\n",
"\n",
" 3 6 LOAD_FAST 0 (s)\n",
" 9 RETURN_VALUE\n"
]
}
],
"prompt_number": 39
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def hello3_func():\n",
" s = 'Hell'\n",
" s = s + 'o'\n",
" return s\n",
"dis.dis(hello3_func)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
" 2 0 LOAD_CONST 1 ('Hell')\n",
" 3 STORE_FAST 0 (s)\n",
"\n",
" 3 6 LOAD_FAST 0 (s)\n",
" 9 LOAD_CONST 2 ('o')\n",
" 12 BINARY_ADD\n",
" 13 STORE_FAST 0 (s)\n",
"\n",
" 4 16 LOAD_FAST 0 (s)\n",
" 19 RETURN_VALUE\n"
]
}
],
"prompt_number": 40
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"It looks like that `'Hello'` and `'Hell'` + `'o'` are both evaluated and stored as `'Hello'` at compile-time, whereas the third version \n",
"`s = 'Hell'` \n",
"`s = s + 'o'` seems to be not interned. Let us quickly confirm the behavior with the following code:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print(hello1_func() is hello2_func())\n",
"print(hello1_func() is hello3_func())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"True\n",
"False\n"
]
}
],
"prompt_number": 42
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, to show that this hypothesis is the answer to this rather unexpected observation, let us `intern` the value manually:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import sys\n",
"\n",
"print(hello1_func() is sys.intern(hello3_func()))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"True\n"
]
}
],
"prompt_number": 45
},
{
"cell_type": "markdown",
"metadata": {},
@ -3390,8 +3938,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 05/03/2014\n",
"- new section: else clauses: conditional vs. completion\n",
"- new section: Interning of compile-time constants vs. run-time expressions\n",
"\n",
"#### 05/02/2014\n",
"- new section in Python 3.x and Python 2.x key differences: for-loop leak<\n",
"- new section in Python 3.x and Python 2.x key differences: for-loop leak\n",
"- new section: Metaclasses - What creates a new instance of a class? \n",
"\n",
"#### 05/01/2014\n",