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": { "metadata": {
"name": "", "name": "",
"signature": "sha256:5c0e4a56352cc8a60aa6e2ced2611bc186078af3c849647256f0c4a810004ee9" "signature": "sha256:b6e7356842906c447ef3c7520aac098e7fe4f888e46fdd5ae06905f1ebe68e27"
}, },
"nbformat": 3, "nbformat": 3,
"nbformat_minor": 0, "nbformat_minor": 0,
@ -48,7 +48,8 @@
"- [`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)\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", "- [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", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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": [ "input": [
"import timeit\n", "import timeit\n",
"\n", "\n",
"def plainlist():\n", "def plainlist(n=100000):\n",
" my_list = []\n", " my_list = []\n",
" for i in range(1,1000000):\n", " for i in range(n):\n",
" if i % 5 == 0:\n", " if i % 5 == 0:\n",
" my_list.append(i)\n", " my_list.append(i)\n",
" return my_list\n", " return my_list\n",
"\n", "\n",
"def listcompr():\n", "def listcompr(n=100000):\n",
" my_list = [i for i in range(1,1000000) if i % 5 == 0]\n", " my_list = [i for i in range(n) if i % 5 == 0]\n",
" return my_list\n", " return my_list\n",
"\n", "\n",
"def generator():\n", "def generator(n=100000):\n",
" my_gen = (i for i in range(1,1000000) if i % 5 == 0)\n", " my_gen = (i for i in range(n) if i % 5 == 0)\n",
" return my_gen\n", " return my_gen\n",
"\n", "\n",
"def generator_yield():\n", "def generator_yield(n=100000):\n",
" for i in range(1,1000000):\n", " for i in range(n):\n",
" if i % 5 == 0:\n", " if i % 5 == 0:\n",
" yield i" " yield i"
], ],
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"prompt_number": 60 "prompt_number": 75
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
@ -1027,10 +1036,13 @@
" for i in listcompr:\n", " for i in listcompr:\n",
" print(i)\n", " print(i)\n",
"\n", "\n",
"print('plain_list', end = '')\n", "print('plain_list: ', end = '')\n",
"%timeit test_plainlist\n", "%timeit test_plainlist\n",
"print('\\nlistcompr: ', end = '')\n",
"%timeit test_listcompr\n", "%timeit test_listcompr\n",
"print('\\ngenerator: ', end = '')\n",
"%timeit test_generator\n", "%timeit test_generator\n",
"print('\\ngenerator_yield: ', end = '')\n",
"%timeit test_generator_yield" "%timeit test_generator_yield"
], ],
"language": "python", "language": "python",
@ -1040,28 +1052,45 @@
"output_type": "stream", "output_type": "stream",
"stream": "stdout", "stream": "stdout",
"text": [ "text": [
"plain_list" "plain_list: 10000000 loops, best of 3: 26.2 ns per loop"
] ]
}, },
{ {
"ename": "NameError", "output_type": "stream",
"evalue": "global name 'test_plainlist' is not defined", "stream": "stdout",
"output_type": "pyerr", "text": [
"traceback": [ "\n",
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\n",
"\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", "listcompr: 10000000 loops, best of 3: 26.1 ns per loop"
"\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", "output_type": "stream",
"\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", "stream": "stdout",
"\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", "text": [
"\u001b[0;32m<magic-timeit>\u001b[0m in \u001b[0;36minner\u001b[0;34m(_it, _timer)\u001b[0m\n", "\n",
"\u001b[0;31mNameError\u001b[0m: global name 'test_plainlist' is not defined" "\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", "cell_type": "code",

View File

@ -1,7 +1,7 @@
{ {
"metadata": { "metadata": {
"name": "", "name": "",
"signature": "sha256:a2c062243bccabbfe46e6f62bbc9d6dd5b10fe44d091727781108ba5b87b9e28" "signature": "sha256:b6e7356842906c447ef3c7520aac098e7fe4f888e46fdd5ae06905f1ebe68e27"
}, },
"nbformat": 3, "nbformat": 3,
"nbformat_minor": 0, "nbformat_minor": 0,
@ -48,7 +48,8 @@
"- [`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)\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", "- [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": {}, "metadata": {},
"source": [ "source": [
"<br>\n", "<br>\n",
"<br>\n",
"<a name='list_generator'></a>\n",
"\n", "\n",
"\n", "## List comprehensions are fast, but generators are faster!?\n",
"## List comprehensions are fast, but generators are faster!\n",
"\n", "\n",
"Not, really (or significantly, see the benchmarks below). So what's the reason to prefer one over the other?\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 lists if you want to use list methods \n",
@ -1018,8 +1020,6 @@
"cell_type": "code", "cell_type": "code",
"collapsed": false, "collapsed": false,
"input": [ "input": [
"\n",
"\n",
"def test_plainlist(plain_list):\n", "def test_plainlist(plain_list):\n",
" for i in plain_list:\n", " for i in plain_list:\n",
" print(i)\n", " print(i)\n",