Files
learn-python3/notebooks/intermediate/idiomatic_misc2.ipynb
2018-07-07 13:28:43 +02:00

513 lines
12 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Idiomatic Python - miscellaneous part 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## String concatenation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"names = ('John', 'Lisa', 'Terminator', 'Python')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font color='red'>Don't do this.</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"semicolon_separated = names[0]\n",
"for name in names[1:]:\n",
" semicolon_separated += ';' + name\n",
"print(semicolon_separated)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <font color='green'>Use `join` instead!</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"semicolon_separated = ';'.join(names)\n",
"print(semicolon_separated)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## `or` in assignments\n",
"The return value of `a or b`:\n",
"* `a` if `a` is truthy\n",
"* `b` otherwise\n",
"\n",
"You can take advantage of this e.g. while writing variable assignments."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = 0\n",
"b = None\n",
"c = 'John Doe'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font color='red'>Instead of doing something like this:</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"my_variable = 'default value'\n",
"if a:\n",
" my_variable = a\n",
"elif b:\n",
" my_variable = b\n",
"elif c:\n",
" my_variable = c\n",
"print(my_variable)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <font color='green'>Prefer doing this:</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"my_variable = a or b or c or 'default value'\n",
"print(my_variable)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## `try` - `except` - `else`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font color='red'>Don't use the following technique for checking if there was exceptions during execution of some block of code.</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"exception_occured = False\n",
"try:\n",
" # here would be the logic of your master piece\n",
" \n",
" bad_calculation = 1 / 0\n",
" \n",
"except ValueError as e:\n",
" print('Oh boi, some value error: {}'.format(e))\n",
" exception_occured = True\n",
"except Exception as e:\n",
" print('Oh boi, something bad happened: {}'.format(e))\n",
" exception_occured = True\n",
" \n",
"if not exception_occured:\n",
" print('All went well!')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <font color='green'>Use this instead!</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" # here would be the logic of your master piece\n",
" \n",
" bad_calculation = 1 / 0\n",
" \n",
"except ValueError as e:\n",
" print('Oh boi, some keyerror: {}'.format(e))\n",
"except Exception as e:\n",
" print('Oh boi, something bad happened: {}'.format(e))\n",
"else:\n",
" print('All went well!')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## `try` - `finally`\n",
"For scenarios where you want to do something always, even when there are exceptions."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font color='red'>Don't do it like this</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def magical_calculation():\n",
" try:\n",
" # here would be the logic of your master piece\n",
" result = 1 / 0\n",
" except ZeroDivisionError:\n",
" print('This could be something important that should be done every time')\n",
" return 0\n",
" except Exception:\n",
" print('This could be something important that should be done every time')\n",
" return None\n",
"\n",
" print('This could be something important that should be done every time')\n",
" return result\n",
"\n",
"print('return value: {}'.format(magical_calculation()))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <font color='green'>This is better fit for the purpose!</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def magical_calculation():\n",
" try:\n",
" # here would be the logic of your master piece\n",
" result = 1 / 0\n",
" except ZeroDivisionError:\n",
" return 0\n",
" except Exception:\n",
" return None\n",
" finally:\n",
" print('This could be something important that should be done every time')\n",
" return result\n",
"\n",
"print('return value: {}'.format(magical_calculation()))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Use context managers when possible\n",
"One use case example is file I/O."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font color='red'>Don't play with files like this.</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" some_file = open('tmp.txt', 'w')\n",
" print('the file is now open: {}'.format(not some_file.closed))\n",
" \n",
" # here would be some logic\n",
" \n",
"finally:\n",
" some_file.close()\n",
" print(\"now it's closed: {}\".format(some_file.closed))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <font color='green'>Use context manager instead!</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with open('tmp.txt', 'w') as some_file:\n",
" print('the file is now open: {}'.format(not some_file.closed))\n",
" \n",
" # here would be some logic\n",
"\n",
"print(\"now it's closed: {}\".format(some_file.closed))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## `min()` & `max()`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"secret_data = (1, 2, 5, 99, 8, -9)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font color='red'>No need to bake it yourself.</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"max_value = 0\n",
"for val in secret_data:\n",
" if val > max_value:\n",
" max_value = val\n",
"print(max_value)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <font color='green'>Use builtin functionality instead!</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"max_value = max(secret_data)\n",
"print(max_value)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## `contextlib.suppress` - ignoring exceptions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font color='red'>If there's a potential exception that is ok, don't handle it like this.</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"value = 0\n",
"try:\n",
" value = 1 / 0 # just for demonstrating purposes \n",
"except ZeroDivisionError:\n",
" pass\n",
"\n",
"print(value)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <font color='green'>Do it like this instead!</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from contextlib import suppress\n",
"\n",
"value = 0\n",
"with suppress(ZeroDivisionError):\n",
" value = 1 / 0 # just for demonstrating purposes\n",
" \n",
"print(value)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Properties instead of getter/setter methods"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font color='red'>Instead of doing something like this.</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class Person:\n",
" def __init__(self, first_name, last_name):\n",
" self.first_name = first_name\n",
" self.last_name = last_name\n",
" \n",
" def set_full_name(self, full_name):\n",
" parts = full_name.split()\n",
" if len(parts) != 2:\n",
" raise ValueError('Sorry, too difficult name')\n",
" \n",
" self.first_name, self.last_name = parts \n",
" \n",
" def get_full_name(self):\n",
" return '{} {}'.format(self.first_name, self.last_name)\n",
"\n",
" \n",
"p = Person('John', 'Doe')\n",
"print(p.get_full_name())\n",
"p.set_full_name('Lisa Doe')\n",
"print(p.get_full_name())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <font color='green'>Prefer properties!</font>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class Person:\n",
" def __init__(self, first_name, last_name):\n",
" self.first_name = first_name\n",
" self.last_name = last_name\n",
" \n",
" @property\n",
" def full_name(self):\n",
" return '{} {}'.format(self.first_name, self.last_name)\n",
" \n",
" @full_name.setter\n",
" def full_name(self, name):\n",
" parts = name.split()\n",
" if len(parts) != 2:\n",
" raise ValueError('Sorry, too difficult name')\n",
" \n",
" self.first_name, self.last_name = parts\n",
"\n",
" \n",
"p = Person('John', 'Doe')\n",
"print(p.full_name)\n",
"p.full_name = 'Lisa Doe'\n",
"print(p.full_name)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.5.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}