Skip to content

Instantly share code, notes, and snippets.

@Paddy3118
Created August 29, 2018 17:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Paddy3118/f2c628d9718a61dd85c433329ecc157d to your computer and use it in GitHub Desktop.
Save Paddy3118/f2c628d9718a61dd85c433329ecc157d to your computer and use it in GitHub Desktop.
Pythons new dict unpacking: An exploration.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Pythons new [unpacking](https://www.python.org/dev/peps/pep-0448/)\n",
"I skimmed this in previous release notes then saw the dict unpcking in a EuroPython [Video](https://youtu.be/h5tmNkyNAKs?list=PL8uoeex94UhFrNUV2m5MigREebUms39U5&t=261) \n",
"and thought I should check it out again in more depth, as I haven't really used it much.\n",
"\n",
"## Tuple unpacking round-tripping"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"elems = (3, 5, 6)\n",
"first, *rest = elems\n",
"first"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[5, 6]"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rest"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(3, 5, 6)"
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"equiv_elems = first, *rest\n",
"equiv_elems"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## List unpacking round-tripping"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"elems = [1, 2, 3, 4, 5, 6]\n",
"first, *mid, last = elems\n",
"first"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[2, 3, 4, 5]"
]
},
"execution_count": 64,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mid"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6"
]
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"last"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(1, 2, 3, 4, 5, 6)"
]
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"equiv_elems = first, *mid, last\n",
"equiv_elems"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Whoops, that result is a tuple!**<br>\n",
"But then the RHS use of commas makes the expression a tuple. Lets make the RHS a list expression:"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 2, 3, 4, 5, 6]"
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"equiv_elems = [first, *mid, last]\n",
"equiv_elems"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 68,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"elems == equiv_elems"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Iterable unpacking in comprehensions\n",
"**Cannot be done!**"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3]]"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ranges = [[*range(i)] for i in range(5)]\n",
"ranges"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"ename": "SyntaxError",
"evalue": "iterable unpacking cannot be used in comprehension (<ipython-input-70-d57f96414bd8>, line 1)",
"output_type": "error",
"traceback": [
"\u001b[1;36m File \u001b[1;32m\"<ipython-input-70-d57f96414bd8>\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m [*item for item in ranges]\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m iterable unpacking cannot be used in comprehension\n"
]
}
],
"source": [
"[*item for item in ranges]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you wanted to get that effect of flattenning the sub-lists then you could use `sum` like so:"
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0, 0, 1, 0, 1, 2, 0, 1, 2, 3]"
]
},
"execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sum(ranges, [])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Dict unpacking"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [],
"source": [
"d1, d2, d3 = {'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'b': 5, 'c': 6, 'e': 7}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that `d3` shares some of the keys of `d1` and `d2`; and that `d1` and `d2` share no keys.<br>\n",
"All values are distinct.\n",
"\n",
"Lets do some dict expressions with the unpacking"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'a': 1, 'b': 2, 'c': 3, 'd': 4}"
]
},
"execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{**d1, **d2}"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 74,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{**d1, **d2} == {**d2, **d1} # Distinct keys"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Dict unpacking order\n",
"Left-to-right; right-most occurrence of the *same* key dominate"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'a': 1, 'b': 5, 'c': 6, 'e': 7}"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{**d1, **d3}"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'b': 2, 'c': 6, 'e': 7, 'a': 1}"
]
},
"execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{**d3, **d1}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that Python 3.6+ preserves the order of keys added to the dict, so in the last example above, `d3` creates the b, c, and e keys with values then `d1` adds the new key 'a' at the end, then updates the existing 'b' key."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## END."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [default]",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment