513 lines
12 KiB
Plaintext
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
|
|
}
|