mirror of
https://github.com/rasbt/python_reference.git
synced 2025-02-21 15:52:10 +00:00
mutable objects as default arguments
This commit is contained in:
parent
38092ac583
commit
c177a57002
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"name": "",
|
"name": "",
|
||||||
"signature": "sha256:faa74a34746bf250ef2d72e308074083ee5e60789203d70f630f8c67a709e6fe"
|
"signature": "sha256:06e485535e22c756262f09d4477108b57d0fa1029f9831ee77a177267f5afc7f"
|
||||||
},
|
},
|
||||||
"nbformat": 3,
|
"nbformat": 3,
|
||||||
"nbformat_minor": 0,
|
"nbformat_minor": 0,
|
||||||
|
@ -46,7 +46,8 @@
|
||||||
"- [Don't use mutable objects as default arguments for functions!](#def_mutable_func)\n",
|
"- [Don't use mutable objects as default arguments for functions!](#def_mutable_func)\n",
|
||||||
"- [Be aware of the consuming generator](#consuming_generator)\n",
|
"- [Be aware of the consuming generator](#consuming_generator)\n",
|
||||||
"- [`bool` is a subclass of `int`](#bool_int)\n",
|
"- [`bool` is a subclass of `int`](#bool_int)\n",
|
||||||
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)"
|
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)\n",
|
||||||
|
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -594,7 +595,9 @@
|
||||||
"\n",
|
"\n",
|
||||||
"## About lambda and closures-in-a-loop pitfall\n",
|
"## About lambda and closures-in-a-loop pitfall\n",
|
||||||
"\n",
|
"\n",
|
||||||
"The following example illustrates how the (last) `lambda` is being reused:"
|
"The following example illustrates how the (last) `lambda` is being reused:\n",
|
||||||
|
"\n",
|
||||||
|
"(Original source: [http://openhome.cc/eGossip/Blog/UnderstandingLambdaClosure3.html](http://openhome.cc/eGossip/Blog/UnderstandingLambdaClosure3.html))"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -654,13 +657,167 @@
|
||||||
],
|
],
|
||||||
"prompt_number": 25
|
"prompt_number": 25
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"<br>\n",
|
||||||
|
"<br>\n",
|
||||||
|
"<a name='python_legb'></a>\n",
|
||||||
|
"\n",
|
||||||
|
"## Python's LEGB scope resolution and the keywords `global` and `nonlocal`"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"There is nothing particularly surprising about Python's LEGB scope resolution (Local -> Enclosed -> Global -> Built-in), but it is still useful to take a look at some examples!"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### `global` vs. `local`\n",
|
||||||
|
"\n",
|
||||||
|
"According to the LEGB rule, Python will first look for a variable in the local scope. So if we set the variable `x = 1` in the `local`ly in the function's scope, it won't have an effect on the `global` `x`."
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"collapsed": false,
|
"collapsed": false,
|
||||||
"input": [],
|
"input": [
|
||||||
|
"x = 0\n",
|
||||||
|
"def in_func():\n",
|
||||||
|
" x = 1\n",
|
||||||
|
" print('in_func:', x)\n",
|
||||||
|
" \n",
|
||||||
|
"in_func()\n",
|
||||||
|
"print('global:', x)"
|
||||||
|
],
|
||||||
"language": "python",
|
"language": "python",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": []
|
"outputs": [
|
||||||
|
{
|
||||||
|
"output_type": "stream",
|
||||||
|
"stream": "stdout",
|
||||||
|
"text": [
|
||||||
|
"in_func: 1\n",
|
||||||
|
"global: 0\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prompt_number": 33
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"If we want to modify the `global` x via a function, we can simply use the `global` keyword to import the variable into the function's scope:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"collapsed": false,
|
||||||
|
"input": [
|
||||||
|
"x = 0\n",
|
||||||
|
"def in_func():\n",
|
||||||
|
" global x\n",
|
||||||
|
" x = 1\n",
|
||||||
|
" print('in_func:', x)\n",
|
||||||
|
" \n",
|
||||||
|
"in_func()\n",
|
||||||
|
"print('global:', x)"
|
||||||
|
],
|
||||||
|
"language": "python",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"output_type": "stream",
|
||||||
|
"stream": "stdout",
|
||||||
|
"text": [
|
||||||
|
"in_func: 1\n",
|
||||||
|
"global: 1\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prompt_number": 34
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### `local` vs. `enclosed`\n",
|
||||||
|
"\n",
|
||||||
|
"Now, let us take a look at `local` vs. `enclosed`. Here, we set the variable `x = 1` in the `outer` function and set `x = 1` in the enclosed function `inner`. Since `inner` looks in the local scope first, it won't modify `outer`'s `x`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"collapsed": false,
|
||||||
|
"input": [
|
||||||
|
"def outer():\n",
|
||||||
|
" x = 1\n",
|
||||||
|
" print('outer before:', x)\n",
|
||||||
|
" def inner():\n",
|
||||||
|
" x = 2\n",
|
||||||
|
" print(\"inner:\", x)\n",
|
||||||
|
" inner()\n",
|
||||||
|
" print(\"outer after:\", x)\n",
|
||||||
|
"outer()"
|
||||||
|
],
|
||||||
|
"language": "python",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"output_type": "stream",
|
||||||
|
"stream": "stdout",
|
||||||
|
"text": [
|
||||||
|
"outer before: 1\n",
|
||||||
|
"inner: 2\n",
|
||||||
|
"outer after: 1\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prompt_number": 36
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Here is where the `nonlocal` keyword comes in handy - it allows us to modify the `x` variable in the `enclosed` scope:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"collapsed": false,
|
||||||
|
"input": [
|
||||||
|
"def outer():\n",
|
||||||
|
" x = 1\n",
|
||||||
|
" print('outer before:', x)\n",
|
||||||
|
" def inner():\n",
|
||||||
|
" nonlocal x\n",
|
||||||
|
" x = 2\n",
|
||||||
|
" print(\"inner:\", x)\n",
|
||||||
|
" inner()\n",
|
||||||
|
" print(\"outer after:\", x)\n",
|
||||||
|
"outer()"
|
||||||
|
],
|
||||||
|
"language": "python",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"output_type": "stream",
|
||||||
|
"stream": "stdout",
|
||||||
|
"text": [
|
||||||
|
"outer before: 1\n",
|
||||||
|
"inner: 2\n",
|
||||||
|
"outer after: 2\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prompt_number": 35
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {}
|
"metadata": {}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"name": "",
|
"name": "",
|
||||||
"signature": "sha256:faa74a34746bf250ef2d72e308074083ee5e60789203d70f630f8c67a709e6fe"
|
"signature": "sha256:06e485535e22c756262f09d4477108b57d0fa1029f9831ee77a177267f5afc7f"
|
||||||
},
|
},
|
||||||
"nbformat": 3,
|
"nbformat": 3,
|
||||||
"nbformat_minor": 0,
|
"nbformat_minor": 0,
|
||||||
|
@ -46,7 +46,8 @@
|
||||||
"- [Don't use mutable objects as default arguments for functions!](#def_mutable_func)\n",
|
"- [Don't use mutable objects as default arguments for functions!](#def_mutable_func)\n",
|
||||||
"- [Be aware of the consuming generator](#consuming_generator)\n",
|
"- [Be aware of the consuming generator](#consuming_generator)\n",
|
||||||
"- [`bool` is a subclass of `int`](#bool_int)\n",
|
"- [`bool` is a subclass of `int`](#bool_int)\n",
|
||||||
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)"
|
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)\n",
|
||||||
|
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -594,7 +595,9 @@
|
||||||
"\n",
|
"\n",
|
||||||
"## About lambda and closures-in-a-loop pitfall\n",
|
"## About lambda and closures-in-a-loop pitfall\n",
|
||||||
"\n",
|
"\n",
|
||||||
"The following example illustrates how the (last) `lambda` is being reused:"
|
"The following example illustrates how the (last) `lambda` is being reused:\n",
|
||||||
|
"\n",
|
||||||
|
"(Original source: [http://openhome.cc/eGossip/Blog/UnderstandingLambdaClosure3.html](http://openhome.cc/eGossip/Blog/UnderstandingLambdaClosure3.html))"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -654,13 +657,167 @@
|
||||||
],
|
],
|
||||||
"prompt_number": 25
|
"prompt_number": 25
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"<br>\n",
|
||||||
|
"<br>\n",
|
||||||
|
"<a name='python_legb'></a>\n",
|
||||||
|
"\n",
|
||||||
|
"## Python's LEGB scope resolution and the keywords `global` and `nonlocal`"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"There is nothing particularly surprising about Python's LEGB scope resolution (Local -> Enclosed -> Global -> Built-in), but it is still useful to take a look at some examples!"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### `global` vs. `local`\n",
|
||||||
|
"\n",
|
||||||
|
"According to the LEGB rule, Python will first look for a variable in the local scope. So if we set the variable `x = 1` in the `local`ly in the function's scope, it won't have an effect on the `global` `x`."
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"collapsed": false,
|
"collapsed": false,
|
||||||
"input": [],
|
"input": [
|
||||||
|
"x = 0\n",
|
||||||
|
"def in_func():\n",
|
||||||
|
" x = 1\n",
|
||||||
|
" print('in_func:', x)\n",
|
||||||
|
" \n",
|
||||||
|
"in_func()\n",
|
||||||
|
"print('global:', x)"
|
||||||
|
],
|
||||||
"language": "python",
|
"language": "python",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": []
|
"outputs": [
|
||||||
|
{
|
||||||
|
"output_type": "stream",
|
||||||
|
"stream": "stdout",
|
||||||
|
"text": [
|
||||||
|
"in_func: 1\n",
|
||||||
|
"global: 0\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prompt_number": 33
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"If we want to modify the `global` x via a function, we can simply use the `global` keyword to import the variable into the function's scope:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"collapsed": false,
|
||||||
|
"input": [
|
||||||
|
"x = 0\n",
|
||||||
|
"def in_func():\n",
|
||||||
|
" global x\n",
|
||||||
|
" x = 1\n",
|
||||||
|
" print('in_func:', x)\n",
|
||||||
|
" \n",
|
||||||
|
"in_func()\n",
|
||||||
|
"print('global:', x)"
|
||||||
|
],
|
||||||
|
"language": "python",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"output_type": "stream",
|
||||||
|
"stream": "stdout",
|
||||||
|
"text": [
|
||||||
|
"in_func: 1\n",
|
||||||
|
"global: 1\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prompt_number": 34
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### `local` vs. `enclosed`\n",
|
||||||
|
"\n",
|
||||||
|
"Now, let us take a look at `local` vs. `enclosed`. Here, we set the variable `x = 1` in the `outer` function and set `x = 1` in the enclosed function `inner`. Since `inner` looks in the local scope first, it won't modify `outer`'s `x`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"collapsed": false,
|
||||||
|
"input": [
|
||||||
|
"def outer():\n",
|
||||||
|
" x = 1\n",
|
||||||
|
" print('outer before:', x)\n",
|
||||||
|
" def inner():\n",
|
||||||
|
" x = 2\n",
|
||||||
|
" print(\"inner:\", x)\n",
|
||||||
|
" inner()\n",
|
||||||
|
" print(\"outer after:\", x)\n",
|
||||||
|
"outer()"
|
||||||
|
],
|
||||||
|
"language": "python",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"output_type": "stream",
|
||||||
|
"stream": "stdout",
|
||||||
|
"text": [
|
||||||
|
"outer before: 1\n",
|
||||||
|
"inner: 2\n",
|
||||||
|
"outer after: 1\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prompt_number": 36
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Here is where the `nonlocal` keyword comes in handy - it allows us to modify the `x` variable in the `enclosed` scope:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"collapsed": false,
|
||||||
|
"input": [
|
||||||
|
"def outer():\n",
|
||||||
|
" x = 1\n",
|
||||||
|
" print('outer before:', x)\n",
|
||||||
|
" def inner():\n",
|
||||||
|
" nonlocal x\n",
|
||||||
|
" x = 2\n",
|
||||||
|
" print(\"inner:\", x)\n",
|
||||||
|
" inner()\n",
|
||||||
|
" print(\"outer after:\", x)\n",
|
||||||
|
"outer()"
|
||||||
|
],
|
||||||
|
"language": "python",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"output_type": "stream",
|
||||||
|
"stream": "stdout",
|
||||||
|
"text": [
|
||||||
|
"outer before: 1\n",
|
||||||
|
"inner: 2\n",
|
||||||
|
"outer after: 2\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prompt_number": 35
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {}
|
"metadata": {}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user