Skip to content

Commit 7b07896

Browse files
committed
mutable objects as default arguments
1 parent c177a57 commit 7b07896

2 files changed

Lines changed: 286 additions & 4 deletions

File tree

.ipynb_checkpoints/not_so_obvious_python_stuff-checkpoint.ipynb

Lines changed: 143 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"metadata": {
33
"name": "",
4-
"signature": "sha256:06e485535e22c756262f09d4477108b57d0fa1029f9831ee77a177267f5afc7f"
4+
"signature": "sha256:1b145c7412627e0fa1c08e3b663174712154077c8d8b7740f66d3021a06216a4"
55
},
66
"nbformat": 3,
77
"nbformat_minor": 0,
@@ -47,7 +47,8 @@
4747
"- [Be aware of the consuming generator](#consuming_generator)\n",
4848
"- [`bool` is a subclass of `int`](#bool_int)\n",
4949
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)\n",
50-
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)"
50+
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)\n",
51+
"- [When immutable Tuples aren't so immutable](#immutable_tuple)"
5152
]
5253
},
5354
{
@@ -818,6 +819,146 @@
818819
}
819820
],
820821
"prompt_number": 35
822+
},
823+
{
824+
"cell_type": "markdown",
825+
"metadata": {},
826+
"source": [
827+
"<br>\n",
828+
"<br>\n",
829+
"<a name='immutable_tuple'></a>\n",
830+
"## When immutable Tuples aren't so immutable"
831+
]
832+
},
833+
{
834+
"cell_type": "markdown",
835+
"metadata": {},
836+
"source": [
837+
"As we all know, tuples are immutable objects in Python, right!?"
838+
]
839+
},
840+
{
841+
"cell_type": "code",
842+
"collapsed": false,
843+
"input": [
844+
"tup = (1,)\n",
845+
"tup[0] += 1"
846+
],
847+
"language": "python",
848+
"metadata": {},
849+
"outputs": [
850+
{
851+
"ename": "TypeError",
852+
"evalue": "'tuple' object does not support item assignment",
853+
"output_type": "pyerr",
854+
"traceback": [
855+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
856+
"\u001b[0;32m<ipython-input-41-c3bec6c3fe6f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mtup\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mtup\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
857+
"\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment"
858+
]
859+
}
860+
],
861+
"prompt_number": 41
862+
},
863+
{
864+
"cell_type": "markdown",
865+
"metadata": {},
866+
"source": [
867+
"#### But what if we put a mutable object into the immutable tuple? Well, modification works, but we **also** get a type error, funny, isn't it?"
868+
]
869+
},
870+
{
871+
"cell_type": "code",
872+
"collapsed": false,
873+
"input": [
874+
"tup = ([],)\n",
875+
"print('tup before: ', tup)\n",
876+
"tup[0] += [1]"
877+
],
878+
"language": "python",
879+
"metadata": {},
880+
"outputs": [
881+
{
882+
"output_type": "stream",
883+
"stream": "stdout",
884+
"text": [
885+
"tup before: ([],)\n"
886+
]
887+
},
888+
{
889+
"ename": "TypeError",
890+
"evalue": "'tuple' object does not support item assignment",
891+
"output_type": "pyerr",
892+
"traceback": [
893+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
894+
"\u001b[0;32m<ipython-input-42-aebe9a31dbeb>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mtup\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m[\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 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'tup before: '\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtup\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mtup\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
895+
"\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment"
896+
]
897+
}
898+
],
899+
"prompt_number": 42
900+
},
901+
{
902+
"cell_type": "code",
903+
"collapsed": false,
904+
"input": [
905+
"print('tup after: ', tup)"
906+
],
907+
"language": "python",
908+
"metadata": {},
909+
"outputs": [
910+
{
911+
"output_type": "stream",
912+
"stream": "stdout",
913+
"text": [
914+
"tup after: ([1],)\n"
915+
]
916+
}
917+
],
918+
"prompt_number": 43
919+
},
920+
{
921+
"cell_type": "markdown",
922+
"metadata": {},
923+
"source": [
924+
"<br>\n",
925+
"<br>\n",
926+
"However, there **IS** a way (where there should be none!) to modify our immutable tuple without raising the `TypeError`, the solution is the `.extend()`:"
927+
]
928+
},
929+
{
930+
"cell_type": "code",
931+
"collapsed": false,
932+
"input": [
933+
"tup = ([],)\n",
934+
"print('tup before: ', tup)\n",
935+
"tup[0].extend([1])\n",
936+
"print('tup after: ', tup)"
937+
],
938+
"language": "python",
939+
"metadata": {},
940+
"outputs": [
941+
{
942+
"output_type": "stream",
943+
"stream": "stdout",
944+
"text": [
945+
"tup before: ([],)\n",
946+
"tup after: ([1],)\n"
947+
]
948+
}
949+
],
950+
"prompt_number": 44
951+
},
952+
{
953+
"cell_type": "markdown",
954+
"metadata": {},
955+
"source": [
956+
"### Explanation\n",
957+
"\n",
958+
"**A. Jesse Jiryu Davis** has a nice explanation for this phenomenon (Original source: [http://emptysqua.re/blog/python-increment-is-weird-part-ii/](http://emptysqua.re/blog/python-increment-is-weird-part-ii/))\n",
959+
"\n",
960+
"If we try to extend the list via `+=` *\"then the statement executes STORE_SUBSCR, which calls the C function PyObject_SetItem, which checks if the object supports item assignment. In our case the object is a tuple, so PyObject_SetItem throws the TypeError. Mystery solved.\"*"
961+
]
821962
}
822963
],
823964
"metadata": {}

not_so_obvious_python_stuff.ipynb

Lines changed: 143 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"metadata": {
33
"name": "",
4-
"signature": "sha256:06e485535e22c756262f09d4477108b57d0fa1029f9831ee77a177267f5afc7f"
4+
"signature": "sha256:1b145c7412627e0fa1c08e3b663174712154077c8d8b7740f66d3021a06216a4"
55
},
66
"nbformat": 3,
77
"nbformat_minor": 0,
@@ -47,7 +47,8 @@
4747
"- [Be aware of the consuming generator](#consuming_generator)\n",
4848
"- [`bool` is a subclass of `int`](#bool_int)\n",
4949
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)\n",
50-
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)"
50+
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)\n",
51+
"- [When immutable Tuples aren't so immutable](#immutable_tuple)"
5152
]
5253
},
5354
{
@@ -818,6 +819,146 @@
818819
}
819820
],
820821
"prompt_number": 35
822+
},
823+
{
824+
"cell_type": "markdown",
825+
"metadata": {},
826+
"source": [
827+
"<br>\n",
828+
"<br>\n",
829+
"<a name='immutable_tuple'></a>\n",
830+
"## When immutable Tuples aren't so immutable"
831+
]
832+
},
833+
{
834+
"cell_type": "markdown",
835+
"metadata": {},
836+
"source": [
837+
"As we all know, tuples are immutable objects in Python, right!?"
838+
]
839+
},
840+
{
841+
"cell_type": "code",
842+
"collapsed": false,
843+
"input": [
844+
"tup = (1,)\n",
845+
"tup[0] += 1"
846+
],
847+
"language": "python",
848+
"metadata": {},
849+
"outputs": [
850+
{
851+
"ename": "TypeError",
852+
"evalue": "'tuple' object does not support item assignment",
853+
"output_type": "pyerr",
854+
"traceback": [
855+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
856+
"\u001b[0;32m<ipython-input-41-c3bec6c3fe6f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mtup\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mtup\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
857+
"\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment"
858+
]
859+
}
860+
],
861+
"prompt_number": 41
862+
},
863+
{
864+
"cell_type": "markdown",
865+
"metadata": {},
866+
"source": [
867+
"#### But what if we put a mutable object into the immutable tuple? Well, modification works, but we **also** get a type error, funny, isn't it?"
868+
]
869+
},
870+
{
871+
"cell_type": "code",
872+
"collapsed": false,
873+
"input": [
874+
"tup = ([],)\n",
875+
"print('tup before: ', tup)\n",
876+
"tup[0] += [1]"
877+
],
878+
"language": "python",
879+
"metadata": {},
880+
"outputs": [
881+
{
882+
"output_type": "stream",
883+
"stream": "stdout",
884+
"text": [
885+
"tup before: ([],)\n"
886+
]
887+
},
888+
{
889+
"ename": "TypeError",
890+
"evalue": "'tuple' object does not support item assignment",
891+
"output_type": "pyerr",
892+
"traceback": [
893+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
894+
"\u001b[0;32m<ipython-input-42-aebe9a31dbeb>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mtup\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m[\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 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'tup before: '\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtup\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mtup\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
895+
"\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment"
896+
]
897+
}
898+
],
899+
"prompt_number": 42
900+
},
901+
{
902+
"cell_type": "code",
903+
"collapsed": false,
904+
"input": [
905+
"print('tup after: ', tup)"
906+
],
907+
"language": "python",
908+
"metadata": {},
909+
"outputs": [
910+
{
911+
"output_type": "stream",
912+
"stream": "stdout",
913+
"text": [
914+
"tup after: ([1],)\n"
915+
]
916+
}
917+
],
918+
"prompt_number": 43
919+
},
920+
{
921+
"cell_type": "markdown",
922+
"metadata": {},
923+
"source": [
924+
"<br>\n",
925+
"<br>\n",
926+
"However, there **IS** a way (where there should be none!) to modify our immutable tuple without raising the `TypeError`, the solution is the `.extend()`:"
927+
]
928+
},
929+
{
930+
"cell_type": "code",
931+
"collapsed": false,
932+
"input": [
933+
"tup = ([],)\n",
934+
"print('tup before: ', tup)\n",
935+
"tup[0].extend([1])\n",
936+
"print('tup after: ', tup)"
937+
],
938+
"language": "python",
939+
"metadata": {},
940+
"outputs": [
941+
{
942+
"output_type": "stream",
943+
"stream": "stdout",
944+
"text": [
945+
"tup before: ([],)\n",
946+
"tup after: ([1],)\n"
947+
]
948+
}
949+
],
950+
"prompt_number": 44
951+
},
952+
{
953+
"cell_type": "markdown",
954+
"metadata": {},
955+
"source": [
956+
"### Explanation\n",
957+
"\n",
958+
"**A. Jesse Jiryu Davis** has a nice explanation for this phenomenon (Original source: [http://emptysqua.re/blog/python-increment-is-weird-part-ii/](http://emptysqua.re/blog/python-increment-is-weird-part-ii/))\n",
959+
"\n",
960+
"If we try to extend the list via `+=` *\"then the statement executes STORE_SUBSCR, which calls the C function PyObject_SetItem, which checks if the object supports item assignment. In our case the object is a tuple, so PyObject_SetItem throws the TypeError. Mystery solved.\"*"
961+
]
821962
}
822963
],
823964
"metadata": {}

0 commit comments

Comments
 (0)