{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Idiomatic Python - miscellaneous part 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Comprehensions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"original_data = (1, 2, 3, 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Don't do this."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# list\n",
"square_roots_list = []\n",
"for val in original_data:\n",
" square_root = val ** (1 / 2)\n",
" square_roots_list.append(square_root)\n",
"print(square_roots_list)\n",
"\n",
"# set\n",
"square_roots_set = set()\n",
"for val in original_data:\n",
" square_root = val ** (1 / 2)\n",
" square_roots_set.add(square_root)\n",
"print(square_roots_set)\n",
"\n",
"# dict\n",
"square_roots_dict = {}\n",
"for val in original_data:\n",
" square_root = val ** (1 / 2)\n",
" square_roots_dict[val] = square_root\n",
"print(square_roots_dict)\n",
"\n",
"# dict with a condition\n",
"integer_square_roots_dict = {}\n",
"for val in original_data:\n",
" square_root = val ** (1 / 2)\n",
" if square_root.is_integer():\n",
" integer_square_roots_dict[val] = square_root\n",
"print(integer_square_roots_dict)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note: in case you're using 2.X version of Python for some reason, the result of `1/2` is `0` instead of `0.5`. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Use comprehensions!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"square_roots_list = [val ** (1 / 2) for val in original_data]\n",
"print(square_roots_list)\n",
"\n",
"square_roots_set = {val ** (1 / 2) for val in original_data}\n",
"print(square_roots_set)\n",
"\n",
"square_roots_dict = {val: val ** (1 / 2) for val in original_data}\n",
"print(square_roots_dict)\n",
"\n",
"integer_square_roots_dict = {\n",
" val: val ** (1 / 2) for val in original_data if (val ** (1 / 2)).is_integer()\n",
"}\n",
"print(integer_square_roots_dict)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Using `in` for checking presence of an element in a collection"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"name = \"John Doe\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Don't do it like this."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"if name == \"John\" or name == \"Doe\" or name == \"John Doe\":\n",
" print(\"This seems to be our guy\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Do it like this!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"if name in (\"John\", \"Doe\", \"John Doe\"):\n",
" print(\"This seems to be our guy\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Chained comparisons"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a, b, c, d = 1, 2, 3, 4"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Don't do it like this."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"if b > a and c > b and d > c:\n",
" print(\"from lowest to highest: a, b, c, d\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Do it like this!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"if a < b < c < d:\n",
" print(\"from lowest to highest: a, b, c, d\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Falsy/truthy values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# These are falsy\n",
"my_list = []\n",
"my_dict = {}\n",
"my_set = set()\n",
"my_tuple = tuple()\n",
"zero = 0\n",
"false = False\n",
"none = None\n",
"my_str = \"\"\n",
"\n",
"# Basically the rest are truthy\n",
"# for example:\n",
"my_second_list = [\"foo\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Don't do it like this."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"if len(my_list) == 0:\n",
" print(\"Empty list is so empty\")\n",
"\n",
"if not len(my_dict):\n",
" print(\"Empty dict is also very empty\")\n",
"\n",
"if not len(my_set) and not len(my_tuple):\n",
" print(\"Same goes for sets and tuples\")\n",
"\n",
"if not bool(zero) and not bool(false) and not bool(none) and len(my_str) == 0:\n",
" print(\"These are also falsy\")\n",
"\n",
"if len(my_second_list) > 0:\n",
" print(\"This should be true\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### This is much better!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"if not my_list:\n",
" print(\"Empty list is so empty\")\n",
"\n",
"if not my_dict:\n",
" print(\"Empty dict is also very empty\")\n",
"\n",
"if not my_set and not my_tuple:\n",
" print(\"Same goes for sets and tuples\")\n",
"\n",
"if not zero and not false and not none and not my_str:\n",
" print(\"These are also falsy\")\n",
"\n",
"if my_second_list:\n",
" print(\"This should be true\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## `any` & `all`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"example_collection = [\"a\", True, \"Python is cool\", 123, 0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Don't do it like this."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"any_value_truthy = True\n",
"for val in example_collection:\n",
" if val:\n",
" any_value_truthy = True\n",
" break\n",
"\n",
"all_values_truthy = True\n",
"for val in example_collection:\n",
" if not val:\n",
" all_values_truthy = False\n",
" break\n",
"\n",
"print(f\"any truthy: {any_value_truthy}, all truthy: {all_values_truthy}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Do it like this!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"any_value_truthy = any(example_collection)\n",
"all_values_truthy = all(example_collection)\n",
"print(f\"any truthy: {any_value_truthy}, all truthy: {all_values_truthy}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pythonic substitute for ternary operator\n",
"Many other programming languages have a ternary operator: `?`. A common use case for the ternary operator is to assign a certain value to a variable based on some condition. In other words, it could be used like this:\n",
"```\n",
"variable = some_condition ? some_value : some_other_value\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Instead of doing this."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"some_condition = True # just a dummy condition\n",
"\n",
"if some_condition:\n",
" variable = \"John\"\n",
"else:\n",
" variable = \"Doe\"\n",
"print(variable)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### You can do it like this!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"variable = \"John\" if some_condition else \"Doe\"\n",
"print(variable)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Function keywords arguments\n",
"For better readability and maintainability."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def show_person_details(name, is_gangster, is_hacker, age):\n",
" print(f\"name: {name}, gangster: {is_gangster}, hacker: {is_hacker}, age: {age}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is not good. It's hard to tell what `True`, `False` and `83` refer here if you are not familiar with the signature of the `show_person_details` function."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"show_person_details(\"John Doe\", True, False, 83)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### This is much better!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"show_person_details(\"John Doe\", is_gangster=True, is_hacker=False, age=83)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Extra: keyword only arguments after `*`\n",
"This might be useful for example if the signature of the function is likely to change in the future. For example, if there's even a slight chance that one of the arguments may be dropped during the future development, consider using `*`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def func_with_loads_of_args(arg1, *, arg2=None, arg3=None, arg4=None, arg5=\"boom\"):\n",
" pass\n",
"\n",
"\n",
"# This won't work because only keyword arguments allowed after *\n",
"# func_with_loads_of_args('John Doe', 1, 2)\n",
"\n",
"# This is ok\n",
"func_with_loads_of_args(\"John Doe\", arg4=\"foo\", arg5=\"bar\", arg2=\"foo bar\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Multiple assigment\n",
"Let's say we want to swap the values of two variables."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Don't do it like this."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# original values\n",
"a = 1\n",
"b = 2\n",
"\n",
"# swap\n",
"tmp = a\n",
"a = b\n",
"b = tmp\n",
"print(a, b)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Do it like this!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# original values\n",
"a = 1\n",
"b = 2\n",
"\n",
"# swap\n",
"a, b = b, a\n",
"print(a, b)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## (Un)packing"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"my_list = [1, 2, 3, 4, 5, 6]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Don't do something like this."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"first = my_list[0]\n",
"last = my_list[-1]\n",
"middle = my_list[1:-1]\n",
"print(first, middle, last)\n",
"\n",
"packed = [first] + middle + [last]\n",
"assert packed == my_list"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### This is the Pythonic way!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# unpacking\n",
"first, *middle, last = my_list\n",
"print(first, middle, last)\n",
"\n",
"# packing\n",
"packed = [first, *middle, last]\n",
"assert packed == my_list"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.11.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}