mutable objects as default arguments

This commit is contained in:
rasbt 2014-04-15 18:33:51 -04:00
parent be6a8db8cf
commit f8ebfc8dd0
2 changed files with 64 additions and 35 deletions

View File

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:5c0e4a56352cc8a60aa6e2ced2611bc186078af3c849647256f0c4a810004ee9"
"signature": "sha256:b6e7356842906c447ef3c7520aac098e7fe4f888e46fdd5ae06905f1ebe68e27"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -48,7 +48,8 @@
"- [`bool` is a subclass of `int`](#bool_int)\n",
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)\n",
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)\n",
"- [When immutable Tuples aren't so immutable](#immutable_tuple)"
"- [When immutable Tuples aren't so immutable](#immutable_tuple)\n",
"- [List comprehensions are fast, but generators are faster!?](#list_generator)"
]
},
{
@ -966,7 +967,15 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## List comprehensions are fast, but generators are faster!\n"
"<br>\n",
"<br>\n",
"<a name='list_generator'></a>\n",
"\n",
"## List comprehensions are fast, but generators are faster!?\n",
"\n",
"Not, really (or significantly, see the benchmarks below). So what's the reason to prefer one over the other?\n",
"- use lists if you want to use list methods \n",
"- use generators when you are dealing with huge collections to avoid memory issues"
]
},
{
@ -975,30 +984,30 @@
"input": [
"import timeit\n",
"\n",
"def plainlist():\n",
"def plainlist(n=100000):\n",
" my_list = []\n",
" for i in range(1,1000000):\n",
" for i in range(n):\n",
" if i % 5 == 0:\n",
" my_list.append(i)\n",
" return my_list\n",
"\n",
"def listcompr():\n",
" my_list = [i for i in range(1,1000000) if i % 5 == 0]\n",
"def listcompr(n=100000):\n",
" my_list = [i for i in range(n) if i % 5 == 0]\n",
" return my_list\n",
"\n",
"def generator():\n",
" my_gen = (i for i in range(1,1000000) if i % 5 == 0)\n",
"def generator(n=100000):\n",
" my_gen = (i for i in range(n) if i % 5 == 0)\n",
" return my_gen\n",
"\n",
"def generator_yield():\n",
" for i in range(1,1000000):\n",
"def generator_yield(n=100000):\n",
" for i in range(n):\n",
" if i % 5 == 0:\n",
" yield i"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 60
"prompt_number": 75
},
{
"cell_type": "markdown",
@ -1027,10 +1036,13 @@
" for i in listcompr:\n",
" print(i)\n",
"\n",
"print('plain_list', end = '')\n",
"print('plain_list: ', end = '')\n",
"%timeit test_plainlist\n",
"print('\\nlistcompr: ', end = '')\n",
"%timeit test_listcompr\n",
"print('\\ngenerator: ', end = '')\n",
"%timeit test_generator\n",
"print('\\ngenerator_yield: ', end = '')\n",
"%timeit test_generator_yield"
],
"language": "python",
@ -1040,28 +1052,45 @@
"output_type": "stream",
"stream": "stdout",
"text": [
"plain_list"
"plain_list: 10000000 loops, best of 3: 26.2 ns per loop"
]
},
{
"ename": "NameError",
"evalue": "global name 'test_plainlist' is not defined",
"output_type": "pyerr",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-62-a2bedd84850f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'plain_list'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 18\u001b[0;31m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmagic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'timeit test_plainlist'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 19\u001b[0m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmagic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'timeit test_listcompr'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmagic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'timeit test_generator'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/IPython/core/interactiveshell.py\u001b[0m in \u001b[0;36mmagic\u001b[0;34m(self, arg_s)\u001b[0m\n\u001b[1;32m 2203\u001b[0m \u001b[0mmagic_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmagic_arg_s\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0marg_s\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpartition\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m' '\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2204\u001b[0m \u001b[0mmagic_name\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmagic_name\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlstrip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprefilter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mESC_MAGIC\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2205\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_line_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmagic_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmagic_arg_s\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2206\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2207\u001b[0m \u001b[0;31m#-------------------------------------------------------------------------\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/IPython/core/interactiveshell.py\u001b[0m in \u001b[0;36mrun_line_magic\u001b[0;34m(self, magic_name, line)\u001b[0m\n\u001b[1;32m 2124\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'local_ns'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_getframe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstack_depth\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf_locals\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2125\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2126\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2127\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2128\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/IPython/core/magics/execution.py\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, line, cell)\u001b[0m\n",
"\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/IPython/core/magic.py\u001b[0m in \u001b[0;36m<lambda>\u001b[0;34m(f, *a, **k)\u001b[0m\n\u001b[1;32m 191\u001b[0m \u001b[0;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 192\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 193\u001b[0;31m \u001b[0mcall\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 194\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 195\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/IPython/core/magics/execution.py\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, line, cell)\u001b[0m\n\u001b[1;32m 1011\u001b[0m \u001b[0mnumber\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1012\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0m_\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1013\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mtimer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimeit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnumber\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0;36m0.2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1014\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1015\u001b[0m \u001b[0mnumber\u001b[0m \u001b[0;34m*=\u001b[0m \u001b[0;36m10\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/timeit.py\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, number)\u001b[0m\n\u001b[1;32m 188\u001b[0m \u001b[0mgc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdisable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 189\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 190\u001b[0;31m \u001b[0mtiming\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minner\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 191\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 192\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mgcold\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m<magic-timeit>\u001b[0m in \u001b[0;36minner\u001b[0;34m(_it, _timer)\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: global name 'test_plainlist' is not defined"
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"\n",
"listcompr: 10000000 loops, best of 3: 26.1 ns per loop"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"\n",
"generator: 10000000 loops, best of 3: 25.9 ns per loop"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"\n",
"generator_yield: 10000000 loops, best of 3: 26 ns per loop"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
}
],
"prompt_number": 62
"prompt_number": 76
},
{
"cell_type": "code",

View File

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:a2c062243bccabbfe46e6f62bbc9d6dd5b10fe44d091727781108ba5b87b9e28"
"signature": "sha256:b6e7356842906c447ef3c7520aac098e7fe4f888e46fdd5ae06905f1ebe68e27"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -48,7 +48,8 @@
"- [`bool` is a subclass of `int`](#bool_int)\n",
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)\n",
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)\n",
"- [When immutable Tuples aren't so immutable](#immutable_tuple)"
"- [When immutable Tuples aren't so immutable](#immutable_tuple)\n",
"- [List comprehensions are fast, but generators are faster!?](#list_generator)"
]
},
{
@ -967,9 +968,10 @@
"metadata": {},
"source": [
"<br>\n",
"<br>\n",
"<a name='list_generator'></a>\n",
"\n",
"\n",
"## List comprehensions are fast, but generators are faster!\n",
"## List comprehensions are fast, but generators are faster!?\n",
"\n",
"Not, really (or significantly, see the benchmarks below). So what's the reason to prefer one over the other?\n",
"- use lists if you want to use list methods \n",
@ -1018,8 +1020,6 @@
"cell_type": "code",
"collapsed": false,
"input": [
"\n",
"\n",
"def test_plainlist(plain_list):\n",
" for i in plain_list:\n",
" print(i)\n",