From 7287b5e80f0a10f1197b215cafd11466b03f8fd3 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 22 Jul 2018 12:39:06 +0200 Subject: [PATCH 01/60] Add logo --- README.md | 8 ++++++++ logo.png | Bin 0 -> 21593 bytes 2 files changed, 8 insertions(+) create mode 100644 logo.png diff --git a/README.md b/README.md index 2f6a3b4..81fcb1f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +

+ logo +

+ # Learn Python 3 [![Build Status](https://travis-ci.org/jerry-git/learn-python3.svg?branch=master)](https://travis-ci.org/jerry-git/learn-python3) @@ -89,3 +93,7 @@ Python is a powerful language which contains many features not presented in most * openpyxl * pdf * pdfrw / PyPDF2 + + +## Credits +* Logo: Abdur-Rahmaan Janhangeer, [@Abdur-rahmaanJ](https://github.com/Abdur-rahmaanJ) diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5abaae321b446e073a90dd604dc284839e5bbeb6 GIT binary patch literal 21593 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 byZA4fo_1?ki&tV}Kmn>sT8dTjR$u=Ig7koC literal 0 HcmV?d00001 From b06a2c95651a215fa005b3a397dafd9fb19ec65a Mon Sep 17 00:00:00 2001 From: Vivek Date: Mon, 30 Jul 2018 01:51:25 +0530 Subject: [PATCH 02/60] Assigning to my_string variable To print the expected output variable needs to be assigned value of replaced sub string. --- notebooks/beginner/strings.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebooks/beginner/strings.ipynb b/notebooks/beginner/strings.ipynb index def3d05..b6dc04f 100644 --- a/notebooks/beginner/strings.ipynb +++ b/notebooks/beginner/strings.ipynb @@ -92,7 +92,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_string.replace('a', '?')\n", + "my_string = my_string.replace('a', '?')\n", "print(my_string)" ] }, From 857b14ce7457c0c8e0b2f66c2f5cb98570e8f1c4 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Tue, 31 Jul 2018 19:52:24 +0300 Subject: [PATCH 03/60] Update html to match notebook file --- notebooks/beginner/html/strings.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/notebooks/beginner/html/strings.html b/notebooks/beginner/html/strings.html index 1211799..c78c573 100644 --- a/notebooks/beginner/html/strings.html +++ b/notebooks/beginner/html/strings.html @@ -11777,7 +11777,7 @@ } $( document ).ready(function(){ - show=false; +show=false; $('div.output').hide() }); @@ -12021,7 +12021,7 @@

str.replace()In [7]: From 4a4dec431f711a5f0e0fd4c436051c932d6227c1 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Tue, 31 Jul 2018 19:57:19 +0300 Subject: [PATCH 04/60] Be more explicit about replace examples --- notebooks/beginner/html/strings.html | 24 +++++++++++++++++++++--- notebooks/beginner/strings.ipynb | 16 +++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/notebooks/beginner/html/strings.html b/notebooks/beginner/html/strings.html index c78c573..39d0fe1 100644 --- a/notebooks/beginner/html/strings.html +++ b/notebooks/beginner/html/strings.html @@ -12015,13 +12015,22 @@

str.replace()
+
+
+
+

This will not modify my_string because replace is not done in-place.

+ +
+
In [7]:
diff --git a/notebooks/beginner/strings.ipynb b/notebooks/beginner/strings.ipynb index b6dc04f..c87bba4 100644 --- a/notebooks/beginner/strings.ipynb +++ b/notebooks/beginner/strings.ipynb @@ -86,16 +86,30 @@ "help(str.replace)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This will not modify `my_string` because replace is not done in-place." + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "my_string = my_string.replace('a', '?')\n", + "my_string.replace('a', '?')\n", "print(my_string)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You have to store the return value of `replace` instead." + ] + }, { "cell_type": "code", "execution_count": null, From 152a28bb2c2f898651ba10671b1356b53e6daf81 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sat, 1 Sep 2018 17:23:55 +0200 Subject: [PATCH 05/60] Test also with Python 3.7 --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index e2729df..b503cc3 100644 --- a/tox.ini +++ b/tox.ini @@ -2,6 +2,7 @@ skipsdist = True envlist = py35, py36, + py37 skip_missing_interpreters = true [testenv] From 50210605db5549dcf2a868a42ee06b9bfe329b3d Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sat, 1 Sep 2018 17:27:00 +0200 Subject: [PATCH 06/60] Test 3.7 on Travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4626992..8719335 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,8 @@ jobs: env: TOXENV=py35 - python: 3.6 env: TOXENV=py36 + - python: 3.7 + env: TOXENV=py37 script: - tox From 0695ea5c6e8c75f7177c5faa7fbabe0371a577cd Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sat, 1 Sep 2018 17:32:59 +0200 Subject: [PATCH 07/60] Use xenial dist for 3.7 See https://github.com/travis-ci/travis-ci/issues/9815 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8719335..234fff8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,8 @@ jobs: env: TOXENV=py36 - python: 3.7 env: TOXENV=py37 + dist: xenial + sudo: true script: - tox From 617baf9bae5055e593a4e921e45e239e3c00c330 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 2 Sep 2018 15:33:22 +0200 Subject: [PATCH 08/60] Add pytest fixtures notebook --- .../intermediate/html/pytest_fixtures.html | 12467 ++++++++++++++++ notebooks/intermediate/pytest_fixtures.ipynb | 345 + 2 files changed, 12812 insertions(+) create mode 100644 notebooks/intermediate/html/pytest_fixtures.html create mode 100644 notebooks/intermediate/pytest_fixtures.ipynb diff --git a/notebooks/intermediate/html/pytest_fixtures.html b/notebooks/intermediate/html/pytest_fixtures.html new file mode 100644 index 0000000..1932a88 --- /dev/null +++ b/notebooks/intermediate/html/pytest_fixtures.html @@ -0,0 +1,12467 @@ + + + +tmp_pytest_fixtures + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + +
+
+
+
+
+
+

Required boilerplate for using pytest inside notebooks.

+ +
+
+
+
+
+
In [1]:
+
+
+
# Let's make sure pytest and ipytest packages are installed
+# ipytest is required for running pytest inside Jupyter notebooks
+import sys
+!{sys.executable} -m pip install pytest ipytest
+
+import pytest
+from ipytest import magics, clean_tests
+__file__ = 'pytest_fixtures.ipynb'
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
Requirement already satisfied: pytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (3.5.0)
+Requirement already satisfied: ipytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (0.2.2)
+Requirement already satisfied: py>=1.5.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.5.3)
+Requirement already satisfied: setuptools in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (39.0.1)
+Requirement already satisfied: six>=1.10.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.11.0)
+Requirement already satisfied: attrs>=17.4.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (17.4.0)
+Requirement already satisfied: pluggy<0.7,>=0.5 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (0.6.0)
+Requirement already satisfied: more-itertools>=4.0.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (4.1.0)
+
+
+
+ +
+
+ +
+
+
+
+
+

Parametrizing fixtures

Similarly as you can parametrize test functions with pytest.mark.parametrize, you can parametrize fixtures:

+ +
+
+
+
+
+
In [2]:
+
+
+
PATHS = ['/foo/bar.txt', '/bar/baz.txt']
+
+@pytest.fixture(params=PATHS)
+def executable(request):
+    return request.param
+
+ +
+
+
+ +
+
+
+
In [3]:
+
+
+
%%run_pytest[clean] '-s'
+
+def test_something_with_executable(executable):
+    print(executable)
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
=========================================================== test session starts ===========================================================
+platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
+rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
+plugins: nbval-0.9.0
+collected 2 items
+
+pytest_fixtures.py /foo/bar.txt
+./bar/baz.txt
+.
+
+======================================================== 2 passed in 0.02 seconds =========================================================
+
+
+
+ +
+
+ +
+
+
+
+
+

pytest.mark.usefixtures

usefixtures is useful especially when you want to use some fixture in a set of tests but you don't need the return value of the fixture.

+ +
+
+
+
+
+
In [4]:
+
+
+
@pytest.fixture
+def my_fixture():
+    print('\nmy_fixture is used')
+
+@pytest.fixture
+def other_fixture():
+    return 'FOO'
+
+ +
+
+
+ +
+
+
+
In [5]:
+
+
+
%%run_pytest[clean] '-s'
+
+@pytest.mark.usefixtures('my_fixture')
+class TestMyStuff:
+    def test_somestuff(self):
+        pass
+    
+    def test_some_other_stuff(self, other_fixture):
+        print('here we use also other_fixture which returns: {}'.format(other_fixture))
+        pass
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
=========================================================== test session starts ===========================================================
+platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
+rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
+plugins: nbval-0.9.0
+collected 2 items
+
+pytest_fixtures.py 
+my_fixture is used
+.
+my_fixture is used
+here we use also other_fixture which returns: FOO
+.
+
+============================================================ warnings summary =============================================================
+None
+  Module already imported so cannot be rewritten: nbval
+
+-- Docs: http://doc.pytest.org/en/latest/warnings.html
+================================================== 2 passed, 1 warnings in 0.02 seconds ===================================================
+
+
+
+ +
+
+ +
+
+
+
In [6]:
+
+
+
# Needed to clean up test classes (Test*) in ipytest
+clean_tests('Test*')
+
+ +
+
+
+ +
+
+
+
+
+

pytest built-in fixtures

Here are a couple of examples of the useful built-in fixtures, you can view all available fixtures by running pytest --fixtures.

+ +
+
+
+
+
+
+
+

monkeypatch

Built-in monkeypatch fixture lets you e.g. set environment variables and set/delete attributes of objects. The use cases are similar as with patching/mocking with unittest.mock.patch/unittest.mock.MagicMock which are part of the Python Standard Library.

+

Monkeypatching environment variables:

+ +
+
+
+
+
+
In [7]:
+
+
+
import os
+
+def get_env_var_or_none(var_name):
+    return os.environ.get(var_name, None)
+
+ +
+
+
+ +
+
+
+
In [8]:
+
+
+
%%run_pytest[clean] '-s'
+
+def test_get_env_var_or_none_with_valid_env_var(monkeypatch):
+    monkeypatch.setenv('MY_ENV_VAR', 'secret')
+    res = get_env_var_or_none('MY_ENV_VAR')
+    assert res == 'secret'
+    
+def test_get_env_var_or_none_with_missing_env_var():
+    res = get_env_var_or_none('NOT_EXISTING')
+    assert res is None
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
=========================================================== test session starts ===========================================================
+platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
+rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
+plugins: nbval-0.9.0
+collected 2 items
+
+pytest_fixtures.py ..
+
+============================================================ warnings summary =============================================================
+None
+  Module already imported so cannot be rewritten: nbval
+
+-- Docs: http://doc.pytest.org/en/latest/warnings.html
+================================================== 2 passed, 1 warnings in 0.02 seconds ===================================================
+
+
+
+ +
+
+ +
+
+
+
+
+

Monkeypatching attributes:

+ +
+
+
+
+
+
In [9]:
+
+
+
class SomeClass:
+    some_value = 'some value'
+    
+    @staticmethod
+    def tell_the_truth():
+        print('This is the original truth')
+
+ +
+
+
+ +
+
+
+
In [10]:
+
+
+
def fake_truth():
+    print('This is modified truth')
+
+@pytest.fixture
+def fake_some_class(monkeypatch): 
+    monkeypatch.setattr('__main__.SomeClass.some_value', 'fake value')
+    monkeypatch.setattr('__main__.SomeClass.tell_the_truth', fake_truth)
+
+ +
+
+
+ +
+
+
+
In [11]:
+
+
+
%%run_pytest[clean] '-s'
+
+def test_some_class(fake_some_class):
+    print(SomeClass.some_value)
+    SomeClass.tell_the_truth()
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
=========================================================== test session starts ===========================================================
+platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
+rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
+plugins: nbval-0.9.0
+collected 1 item
+
+pytest_fixtures.py fake value
+This is modified truth
+.
+
+============================================================ warnings summary =============================================================
+None
+  Module already imported so cannot be rewritten: nbval
+
+-- Docs: http://doc.pytest.org/en/latest/warnings.html
+================================================== 1 passed, 1 warnings in 0.02 seconds ===================================================
+
+
+
+ +
+
+ +
+
+
+
+
+

Fixture scope

+
+
+
+
+
+
In [12]:
+
+
+
# scope is function also by default
+@pytest.fixture(scope='function')
+def func_fixture():
+    print('\nfunc')
+    
+@pytest.fixture(scope='module')
+def module_fixture():
+    print('\nmodule')
+    
+@pytest.fixture(scope='session')
+def session_fixture():
+    print('\nsession')  
+
+ +
+
+
+ +
+
+
+
In [13]:
+
+
+
%%run_pytest[clean] '-s'
+
+def test_something(func_fixture, module_fixture, session_fixture):
+    pass
+
+def test_something_else(func_fixture, module_fixture, session_fixture):
+    pass
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
=========================================================== test session starts ===========================================================
+platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
+rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
+plugins: nbval-0.9.0
+collected 2 items
+
+pytest_fixtures.py 
+session
+
+module
+
+func
+.
+func
+.
+
+============================================================ warnings summary =============================================================
+None
+  Module already imported so cannot be rewritten: nbval
+
+-- Docs: http://doc.pytest.org/en/latest/warnings.html
+================================================== 2 passed, 1 warnings in 0.02 seconds ===================================================
+
+
+
+ +
+
+ +
+
+
+
+
+

Setup-teardown behaviour

+
+
+
+
+
+
In [14]:
+
+
+
@pytest.fixture
+def some_fixture():
+    print('some_fixture is run now')
+    yield 'some magical value'
+    print('\nthis will be run after test execution, you can do e.g. some clean up here')
+
+ +
+
+
+ +
+
+
+
In [15]:
+
+
+
%%run_pytest[clean] '-s'
+
+def test_something(some_fixture):
+    print('running test_something')
+    assert some_fixture == 'some magical value'
+    print('test ends here')
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
=========================================================== test session starts ===========================================================
+platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
+rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
+plugins: nbval-0.9.0
+collected 1 item
+
+pytest_fixtures.py some_fixture is run now
+running test_something
+test ends here
+.
+this will be run after test execution, you can do e.g. some clean up here
+
+
+============================================================ warnings summary =============================================================
+None
+  Module already imported so cannot be rewritten: nbval
+
+-- Docs: http://doc.pytest.org/en/latest/warnings.html
+================================================== 1 passed, 1 warnings in 0.02 seconds ===================================================
+
+
+
+ +
+
+ +
+
+
+
+
+

Using fixtures automatically

+
+
+
+
+
+
In [16]:
+
+
+
@pytest.fixture(autouse=True)
+def my_fixture():
+    print('\nusing my_fixture')
+
+ +
+
+
+ +
+
+
+
In [17]:
+
+
+
%%run_pytest[clean] '-s'
+
+def test_1():
+    pass
+    
+def test_2():
+    pass
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
=========================================================== test session starts ===========================================================
+platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
+rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
+plugins: nbval-0.9.0
+collected 2 items
+
+pytest_fixtures.py 
+using my_fixture
+.
+using my_fixture
+.
+
+============================================================ warnings summary =============================================================
+None
+  Module already imported so cannot be rewritten: nbval
+
+-- Docs: http://doc.pytest.org/en/latest/warnings.html
+================================================== 2 passed, 1 warnings in 0.02 seconds ===================================================
+
+
+
+ +
+
+ +
+
+
+ + + + + + diff --git a/notebooks/intermediate/pytest_fixtures.ipynb b/notebooks/intermediate/pytest_fixtures.ipynb new file mode 100644 index 0000000..7e6d9ee --- /dev/null +++ b/notebooks/intermediate/pytest_fixtures.ipynb @@ -0,0 +1,345 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Efficient use of `pytest` fixtures" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Required boilerplate for using `pytest` inside notebooks." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Let's make sure pytest and ipytest packages are installed\n", + "# ipytest is required for running pytest inside Jupyter notebooks\n", + "import sys\n", + "!{sys.executable} -m pip install pytest ipytest\n", + "\n", + "import pytest\n", + "from ipytest import magics, clean_tests\n", + "__file__ = 'pytest_fixtures.ipynb'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Parametrizing fixtures\n", + "Similarly as you can parametrize test functions with `pytest.mark.parametrize`, you can parametrize fixtures:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "PATHS = ['/foo/bar.txt', '/bar/baz.txt']\n", + "\n", + "@pytest.fixture(params=PATHS)\n", + "def executable(request):\n", + " return request.param" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%run_pytest[clean] '-s'\n", + "\n", + "def test_something_with_executable(executable):\n", + " print(executable)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## `pytest.mark.usefixtures`\n", + "`usefixtures` is useful especially when you want to use some fixture in a set of tests but you don't need the return value of the fixture." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "@pytest.fixture\n", + "def my_fixture():\n", + " print('\\nmy_fixture is used')\n", + "\n", + "@pytest.fixture\n", + "def other_fixture():\n", + " return 'FOO'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%run_pytest[clean] '-s'\n", + "\n", + "@pytest.mark.usefixtures('my_fixture')\n", + "class TestMyStuff:\n", + " def test_somestuff(self):\n", + " pass\n", + " \n", + " def test_some_other_stuff(self, other_fixture):\n", + " print('here we use also other_fixture which returns: {}'.format(other_fixture))\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Needed to clean up test classes (Test*) in ipytest\n", + "clean_tests('Test*')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## `pytest` [built-in fixtures](https://docs.pytest.org/en/latest/builtin.html#pytest-api-and-builtin-fixtures)\n", + "Here are a couple of examples of the useful built-in fixtures, you can view all available fixtures by running `pytest --fixtures`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### [`monkeypatch`](https://docs.pytest.org/en/latest/reference.html#_pytest.monkeypatch.MonkeyPatch)\n", + "Built-in [`monkeypatch`](https://docs.pytest.org/en/latest/reference.html#_pytest.monkeypatch.MonkeyPatch) fixture lets you e.g. set environment variables and set/delete attributes of objects. The use cases are similar as with patching/mocking with `unittest.mock.patch`/`unittest.mock.MagicMock` which are part of the Python Standard Library.\n", + "\n", + "**Monkeypatching environment variables:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "def get_env_var_or_none(var_name):\n", + " return os.environ.get(var_name, None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%run_pytest[clean] '-s'\n", + "\n", + "def test_get_env_var_or_none_with_valid_env_var(monkeypatch):\n", + " monkeypatch.setenv('MY_ENV_VAR', 'secret')\n", + " res = get_env_var_or_none('MY_ENV_VAR')\n", + " assert res == 'secret'\n", + " \n", + "def test_get_env_var_or_none_with_missing_env_var():\n", + " res = get_env_var_or_none('NOT_EXISTING')\n", + " assert res is None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Monkeypatching attributes:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class SomeClass:\n", + " some_value = 'some value'\n", + " \n", + " @staticmethod\n", + " def tell_the_truth():\n", + " print('This is the original truth')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def fake_truth():\n", + " print('This is modified truth')\n", + "\n", + "@pytest.fixture\n", + "def fake_some_class(monkeypatch): \n", + " monkeypatch.setattr('__main__.SomeClass.some_value', 'fake value')\n", + " monkeypatch.setattr('__main__.SomeClass.tell_the_truth', fake_truth)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%run_pytest[clean] '-s'\n", + "\n", + "def test_some_class(fake_some_class):\n", + " print(SomeClass.some_value)\n", + " SomeClass.tell_the_truth()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fixture scope" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# scope is function also by default\n", + "@pytest.fixture(scope='function')\n", + "def func_fixture():\n", + " print('\\nfunc')\n", + " \n", + "@pytest.fixture(scope='module')\n", + "def module_fixture():\n", + " print('\\nmodule')\n", + " \n", + "@pytest.fixture(scope='session')\n", + "def session_fixture():\n", + " print('\\nsession') " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%run_pytest[clean] '-s'\n", + "\n", + "def test_something(func_fixture, module_fixture, session_fixture):\n", + " pass\n", + "\n", + "def test_something_else(func_fixture, module_fixture, session_fixture):\n", + " pass\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup-teardown behaviour" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "@pytest.fixture\n", + "def some_fixture():\n", + " print('some_fixture is run now')\n", + " yield 'some magical value'\n", + " print('\\nthis will be run after test execution, you can do e.g. some clean up here')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%run_pytest[clean] '-s'\n", + "\n", + "def test_something(some_fixture):\n", + " print('running test_something')\n", + " assert some_fixture == 'some magical value'\n", + " print('test ends here')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using fixtures automatically" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "@pytest.fixture(autouse=True)\n", + "def my_fixture():\n", + " print('\\nusing my_fixture')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%run_pytest[clean] '-s'\n", + "\n", + "def test_1():\n", + " pass\n", + " \n", + "def test_2():\n", + " pass" + ] + } + ], + "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 +} From 334b342b4ede4da54ceb0e123b5300fdb0918139 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 2 Sep 2018 15:41:00 +0200 Subject: [PATCH 09/60] Add links to pytest fixture materials --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 81fcb1f..4808910 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,10 @@ Python is a powerful language which contains many features not presented in most 1. [Idiomatic Python - miscellaneous part 2](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/intermediate/html/idiomatic_misc2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_misc2.ipynb) 1. Idiomatic Python exercise [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/idiomatic_python_exercise.ipynb) +#### Step up your `pytest` game +1. [Efficient use of fixtures](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/intermediate/html/pytest_fixtures.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/pytest_fixtures.ipynb) +1. Other tips and tricks + #### General topics 1. [Goodies of the Standard Library - part 2](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/intermediate/html/std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/std_lib2_exercise.ipynb) From 5ca4a98e43eb8c9efe50be960d06cb3785319892 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 2 Sep 2018 15:44:32 +0200 Subject: [PATCH 10/60] Add links to pytest docs --- notebooks/intermediate/html/pytest_fixtures.html | 6 +++--- notebooks/intermediate/pytest_fixtures.ipynb | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/notebooks/intermediate/html/pytest_fixtures.html b/notebooks/intermediate/html/pytest_fixtures.html index 1932a88..6c3fb24 100644 --- a/notebooks/intermediate/html/pytest_fixtures.html +++ b/notebooks/intermediate/html/pytest_fixtures.html @@ -11844,11 +11844,11 @@

Efficient use of pytest f
Requirement already satisfied: pytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (3.5.0)
 Requirement already satisfied: ipytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (0.2.2)
 Requirement already satisfied: py>=1.5.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.5.3)
-Requirement already satisfied: setuptools in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (39.0.1)
-Requirement already satisfied: six>=1.10.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.11.0)
 Requirement already satisfied: attrs>=17.4.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (17.4.0)
 Requirement already satisfied: pluggy<0.7,>=0.5 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (0.6.0)
+Requirement already satisfied: six>=1.10.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.11.0)
 Requirement already satisfied: more-itertools>=4.0.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (4.1.0)
+Requirement already satisfied: setuptools in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (39.0.1)
 

@@ -11931,7 +11931,7 @@

Parametrizing fixtures
-

pytest.mark.usefixtures

usefixtures is useful especially when you want to use some fixture in a set of tests but you don't need the return value of the fixture.

+

pytest.mark.usefixtures

pytest.mark.usefixtures is useful especially when you want to use some fixture in a set of tests but you don't need the return value of the fixture.

diff --git a/notebooks/intermediate/pytest_fixtures.ipynb b/notebooks/intermediate/pytest_fixtures.ipynb index 7e6d9ee..3875667 100644 --- a/notebooks/intermediate/pytest_fixtures.ipynb +++ b/notebooks/intermediate/pytest_fixtures.ipynb @@ -67,8 +67,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## `pytest.mark.usefixtures`\n", - "`usefixtures` is useful especially when you want to use some fixture in a set of tests but you don't need the return value of the fixture." + "## [`pytest.mark.usefixtures`](https://docs.pytest.org/en/latest/fixture.html#usefixtures)\n", + "[`pytest.mark.usefixtures`](https://docs.pytest.org/en/latest/fixture.html#usefixtures) is useful especially when you want to use some fixture in a set of tests but you don't need the return value of the fixture." ] }, { From 5a89897d57996f3e10a7ce4d8cfde6374c2044cc Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 2 Sep 2018 16:29:15 +0200 Subject: [PATCH 11/60] Add tmpdir examples --- .../intermediate/html/pytest_fixtures.html | 93 +++++++++++++++++-- notebooks/intermediate/pytest_fixtures.ipynb | 37 +++++++- 2 files changed, 120 insertions(+), 10 deletions(-) diff --git a/notebooks/intermediate/html/pytest_fixtures.html b/notebooks/intermediate/html/pytest_fixtures.html index 6c3fb24..31549e7 100644 --- a/notebooks/intermediate/html/pytest_fixtures.html +++ b/notebooks/intermediate/html/pytest_fixtures.html @@ -11843,11 +11843,11 @@

Efficient use of pytest f
Requirement already satisfied: pytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (3.5.0)
 Requirement already satisfied: ipytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (0.2.2)
-Requirement already satisfied: py>=1.5.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.5.3)
-Requirement already satisfied: attrs>=17.4.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (17.4.0)
 Requirement already satisfied: pluggy<0.7,>=0.5 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (0.6.0)
 Requirement already satisfied: six>=1.10.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.11.0)
 Requirement already satisfied: more-itertools>=4.0.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (4.1.0)
+Requirement already satisfied: attrs>=17.4.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (17.4.0)
+Requirement already satisfied: py>=1.5.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.5.3)
 Requirement already satisfied: setuptools in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (39.0.1)
 
@@ -12215,13 +12215,88 @@

-

Fixture scope

+

tmpdir

tmpdir fixture provides functionality for creating temporary files and directories.

+
In [12]:
+
+
+
def word_count_of_txt_file(file_path):
+    with open(file_path, 'r') as f:
+        content = f.read()
+        return len(content.split())
+
+ +
+
+
+ +
+
+
+
In [13]:
+
+
+
%%run_pytest[clean] '-s'
+
+def test_word_count(tmpdir):
+    test_file = tmpdir.join('test.txt')
+    test_file.write('This is example content of seven words')
+    res = word_count_of_txt_file(str(test_file)) # str returns the path
+    assert res == 7
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
=========================================================== test session starts ===========================================================
+platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
+rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
+plugins: nbval-0.9.0
+collected 1 item
+
+pytest_fixtures.py .
+
+============================================================ warnings summary =============================================================
+None
+  Module already imported so cannot be rewritten: nbval
+
+-- Docs: http://doc.pytest.org/en/latest/warnings.html
+================================================== 1 passed, 1 warnings in 0.03 seconds ===================================================
+
+
+
+ +
+
+ +
+
+
+
+
+

Fixture scope

+
+
+
+
+
+
In [14]:
# scope is function also by default
@@ -12245,7 +12320,7 @@ 

Fixture scope
-
In [13]:
+
In [15]:
%%run_pytest[clean] '-s'
@@ -12311,7 +12386,7 @@ 

Setup-teardown behaviour
-
In [14]:
+
In [16]:
@pytest.fixture
@@ -12328,7 +12403,7 @@ 

Setup-teardown behaviour
-
In [15]:
+
In [17]:
%%run_pytest[clean] '-s'
@@ -12390,7 +12465,7 @@ 

Using fixtures automatically
-
In [16]:
+
In [18]:
@pytest.fixture(autouse=True)
@@ -12405,7 +12480,7 @@ 

Using fixtures automatically
-
In [17]:
+
In [19]:
%%run_pytest[clean] '-s'
@@ -12448,7 +12523,7 @@ 

Using fixtures automatically Date: Sun, 2 Sep 2018 16:48:27 +0200 Subject: [PATCH 12/60] Set theme jekyll-theme-hacker --- _config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 _config.yml diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..fc24e7a --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-hacker \ No newline at end of file From a3b53da541c166977db9436a4e50880217e3c5e9 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 2 Sep 2018 17:20:38 +0200 Subject: [PATCH 13/60] Set theme jekyll-theme-tactile --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index fc24e7a..259a24e 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-hacker \ No newline at end of file +theme: jekyll-theme-tactile \ No newline at end of file From b8a8d67ce8dc272d9146d220dcbdd70058434517 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 2 Sep 2018 17:29:59 +0200 Subject: [PATCH 14/60] Set theme jekyll-theme-slate --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 259a24e..c741881 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-tactile \ No newline at end of file +theme: jekyll-theme-slate \ No newline at end of file From 154bca70ea7753a1c9ed77c1f10f4d1c13bf35c9 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 2 Sep 2018 17:56:15 +0200 Subject: [PATCH 15/60] Point html links to github pages instead of htmlpreview --- README.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 4808910..49792da 100644 --- a/README.md +++ b/README.md @@ -27,24 +27,24 @@ See [contributing](https://github.com/jerry-git/learn-python3/blob/master/CONTRI ## Beginner -1. [Strings](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/strings.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/strings.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/strings_exercise.ipynb) -1. [Numbers](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/numbers.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/numbers.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/numbers_exercise.ipynb) -1. [Conditionals](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/conditionals.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/conditionals.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/conditionals_exercise.ipynb) -1. [Lists](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/lists.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/lists.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/lists_exercise.ipynb) -1. [Dictionaries](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/dictionaries.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/dictionaries.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/dictionaries_exercise.ipynb) -1. [For loops](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/for_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/for_loops.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/for_loops_exercise.ipynb) -1. [Functions](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/functions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/functions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/functions_exercise.ipynb) -1. [Testing with pytest - part 1](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/testing1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/testing1.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing1_exercise.ipynb) +1. [Strings](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/strings.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/strings.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/strings_exercise.ipynb) +1. [Numbers](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/numbers.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/numbers.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/numbers_exercise.ipynb) +1. [Conditionals](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/conditionals.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/conditionals.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/conditionals_exercise.ipynb) +1. [Lists](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/lists.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/lists.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/lists_exercise.ipynb) +1. [Dictionaries](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/dictionaries.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/dictionaries.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/dictionaries_exercise.ipynb) +1. [For loops](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/for_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/for_loops.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/for_loops_exercise.ipynb) +1. [Functions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/functions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/functions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/functions_exercise.ipynb) +1. [Testing with pytest - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/testing1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/testing1.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing1_exercise.ipynb) 1. Recap exercise 1 [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/recap1_exercise.ipynb) -1. [File I\O](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/file_io.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/file_io.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/file_io_exercise.ipynb) -1. [Classes](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/classes.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/classes.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/classes_exercise.ipynb) -1. [Exceptions](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/exceptions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exceptions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/exceptions_exercise.ipynb) -1. [Modules and packages](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/modules_and_packages.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/modules_and_packages.ipynb) -1. [Debugging](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/debugging.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/debugging.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/debugging_exercise.ipynb) -1. [Goodies of the Standard Library - part 1](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/std_lib.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/std_lib.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/std_lib1_exercise.ipynb) -1. [Testing with pytest - part 2](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/testing2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/testing2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing2_exercise.ipynb) -1. [Virtual environment](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/venv.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/venv.ipynb) -1. [Project structure](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/beginner/html/project_structure.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/project_structure.ipynb) +1. [File I\O](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/file_io.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/file_io.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/file_io_exercise.ipynb) +1. [Classes](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/classes.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/classes.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/classes_exercise.ipynb) +1. [Exceptions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/exceptions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exceptions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/exceptions_exercise.ipynb) +1. [Modules and packages](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/modules_and_packages.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/modules_and_packages.ipynb) +1. [Debugging](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/debugging.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/debugging.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/debugging_exercise.ipynb) +1. [Goodies of the Standard Library - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/std_lib.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/std_lib.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/std_lib1_exercise.ipynb) +1. [Testing with pytest - part 2](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/testing2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/testing2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing2_exercise.ipynb) +1. [Virtual environment](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/venv.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/venv.ipynb) +1. [Project structure](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/project_structure.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/project_structure.ipynb) 1. Recap exercise 2 [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/recap2_exercise.ipynb) @@ -53,18 +53,18 @@ See [contributing](https://github.com/jerry-git/learn-python3/blob/master/CONTRI #### Idiomatic Python Python is a powerful language which contains many features not presented in most other programming languages. Idiomatic section will cover some of these Pythonic features in detail. These materials are especially useful for people with background in other programming languages. -1. [Idiomatic loops](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/intermediate/html/idiomatic_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_loops.ipynb) -1. [Idiomatic dictionaries](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/intermediate/html/idiomatic_dicts.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_dicts.ipynb) -1. [Idiomatic Python - miscellaneous part 1](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/intermediate/html/idiomatic_misc1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_misc1.ipynb) -1. [Idiomatic Python - miscellaneous part 2](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/intermediate/html/idiomatic_misc2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_misc2.ipynb) +1. [Idiomatic loops](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_loops.ipynb) +1. [Idiomatic dictionaries](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_dicts.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_dicts.ipynb) +1. [Idiomatic Python - miscellaneous part 1](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_misc1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_misc1.ipynb) +1. [Idiomatic Python - miscellaneous part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_misc2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_misc2.ipynb) 1. Idiomatic Python exercise [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/idiomatic_python_exercise.ipynb) #### Step up your `pytest` game -1. [Efficient use of fixtures](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/intermediate/html/pytest_fixtures.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/pytest_fixtures.ipynb) +1. [Efficient use of fixtures](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/pytest_fixtures.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/pytest_fixtures.ipynb) 1. Other tips and tricks #### General topics -1. [Goodies of the Standard Library - part 2](http://htmlpreview.github.com/?https://github.com/jerry-git/learn-python3/blob/master/notebooks/intermediate/html/std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/std_lib2_exercise.ipynb) +1. [Goodies of the Standard Library - part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/std_lib2_exercise.ipynb) #### Backlog * Sets From 4bb72323beda7dd2e5644dff81fc4d88b4d11b6a Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Wed, 19 Sep 2018 22:01:45 +0200 Subject: [PATCH 16/60] Add logging stuff for logging exceptions --- notebooks/beginner/html/std_lib.html | 89 +++++++++++++++++++++------- notebooks/beginner/std_lib.ipynb | 20 +++++++ 2 files changed, 88 insertions(+), 21 deletions(-) diff --git a/notebooks/beginner/html/std_lib.html b/notebooks/beginner/html/std_lib.html index 080a530..08b36a4 100644 --- a/notebooks/beginner/html/std_lib.html +++ b/notebooks/beginner/html/std_lib.html @@ -11848,11 +11848,11 @@

-
local now: 2018-07-08 12:07:23.620463
-utc now: 2018-07-08 10:07:23.620661
-2018 7 8 12 7 23
-date: 2018-07-08
-time: 12:07:23.620463
+
local now: 2018-09-19 22:00:35.202267
+utc now: 2018-09-19 20:00:35.202567
+2018 9 19 22 0 35
+date: 2018-09-19
+time: 22:00:35.202267
 

@@ -11896,8 +11896,8 @@

strftime() -
2018/07/08-12:07:23
-date: 2018-07-08 time:12:07:23
+
2018/09/19-22:00:35
+date: 2018-09-19 time:22:00:35
 

@@ -11984,7 +11984,7 @@

-
tomorrow this time: 2018-07-09 12:07:23.620463
+
tomorrow this time: 2018-09-20 22:00:35.202267
 tomorrow - now = 1 day, 0:00:00
 days: 1, seconds: 0
 total seconds: 86400.0
@@ -12077,10 +12077,10 @@ 

Working with timezones -
naive utc now: 2018-07-08 10:07:24.490800, tzinfo: None
-utc now: 2018-07-08 10:07:24.490800+00:00, tzinfo: UTC
-Paris: 2018-07-08 12:07:24.490800+02:00, tzinfo: Europe/Paris
-New York: 2018-07-08 06:07:24.490800-04:00, tzinfo: America/New_York
+
naive utc now: 2018-09-19 20:00:36.074664, tzinfo: None
+utc now: 2018-09-19 20:00:36.074664+00:00, tzinfo: UTC
+Paris: 2018-09-19 22:00:36.074664+02:00, tzinfo: Europe/Paris
+New York: 2018-09-19 16:00:36.074664-04:00, tzinfo: America/New_York
 

@@ -12153,13 +12153,60 @@

-

Formatting log entries

+

Logging expections

There's a neat exception function in logging module which will automatically log the stack trace in addition to user defined log entry.

+

In [8]:
+
+
+
try:
+    path_calculation = 1 / 0
+except ZeroDivisionError:
+    logging.exception('All went south in my calculation')
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
ERROR:root:All went south in my calculation
+Traceback (most recent call last):
+  File "<ipython-input-8-ccd7d25e79b7>", line 2, in <module>
+    path_calculation = 1 / 0
+ZeroDivisionError: division by zero
+
+
+
+ +
+
+ +
+
+
+
+
+

Formatting log entries

+
+
+
+
+
+
In [9]:
@@ -12211,7 +12258,7 @@

-
In [9]:
+
In [10]:
@@ -12258,7 +12305,7 @@

-
In [10]:
+
In [11]:
import random
@@ -12320,7 +12367,7 @@ 

Searching occurences
-
In [11]:
+
In [12]:
import re
@@ -12373,7 +12420,7 @@ 

Variable validation
-
In [12]:
+
In [13]:
import re
diff --git a/notebooks/beginner/std_lib.ipynb b/notebooks/beginner/std_lib.ipynb
index 59cd765..e2eff73 100644
--- a/notebooks/beginner/std_lib.ipynb
+++ b/notebooks/beginner/std_lib.ipynb
@@ -178,6 +178,26 @@
     "logger.critical('This is critical')"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Logging expections\n",
+    "There's a neat `exception` function in `logging` module which will automatically log the stack trace in addition to user defined log entry. "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "try:\n",
+    "    path_calculation = 1 / 0\n",
+    "except ZeroDivisionError:\n",
+    "    logging.exception('All went south in my calculation')"
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {},

From b388730ee811fe53dcafa69a8de8796b3f4fcdc8 Mon Sep 17 00:00:00 2001
From: Jerry Pussinen 
Date: Wed, 19 Sep 2018 22:07:37 +0200
Subject: [PATCH 17/60] Require ipytest>=0.3.0

---
 .../intermediate/html/pytest_fixtures.html    | 73 ++++++-------------
 notebooks/intermediate/pytest_fixtures.ipynb  |  2 +-
 2 files changed, 25 insertions(+), 50 deletions(-)

diff --git a/notebooks/intermediate/html/pytest_fixtures.html b/notebooks/intermediate/html/pytest_fixtures.html
index 31549e7..935802b 100644
--- a/notebooks/intermediate/html/pytest_fixtures.html
+++ b/notebooks/intermediate/html/pytest_fixtures.html
@@ -11820,7 +11820,7 @@ 

Efficient use of pytest f
# Let's make sure pytest and ipytest packages are installed
 # ipytest is required for running pytest inside Jupyter notebooks
 import sys
-!{sys.executable} -m pip install pytest ipytest
+!{sys.executable} -m pip install pytest ipytest>=0.3.0
 
 import pytest
 from ipytest import magics, clean_tests
@@ -11831,31 +11831,6 @@ 

Efficient use of pytest f

-
-
- - -
- -
- - -
-
Requirement already satisfied: pytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (3.5.0)
-Requirement already satisfied: ipytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (0.2.2)
-Requirement already satisfied: pluggy<0.7,>=0.5 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (0.6.0)
-Requirement already satisfied: six>=1.10.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.11.0)
-Requirement already satisfied: more-itertools>=4.0.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (4.1.0)
-Requirement already satisfied: attrs>=17.4.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (17.4.0)
-Requirement already satisfied: py>=1.5.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.5.3)
-Requirement already satisfied: setuptools in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (39.0.1)
-
-
-
- -
-
-
@@ -11986,7 +11961,7 @@

-
=========================================================== test session starts ===========================================================
+
=================================================================================== test session starts ====================================================================================
 platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
 rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
 plugins: nbval-0.9.0
@@ -11999,12 +11974,12 @@ 

-
=========================================================== test session starts ===========================================================
+
=================================================================================== test session starts ====================================================================================
 platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
 rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
 plugins: nbval-0.9.0
@@ -12101,12 +12076,12 @@ 

-
=========================================================== test session starts ===========================================================
+
=================================================================================== test session starts ====================================================================================
 platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
 rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
 plugins: nbval-0.9.0
@@ -12197,12 +12172,12 @@ 

-
=========================================================== test session starts ===========================================================
+
=================================================================================== test session starts ====================================================================================
 platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
 rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
 plugins: nbval-0.9.0
@@ -12272,12 +12247,12 @@ 

Fixture scope -
=========================================================== test session starts ===========================================================
+
=================================================================================== test session starts ====================================================================================
 platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
 rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
 plugins: nbval-0.9.0
@@ -12362,12 +12337,12 @@ 

Fixture scope

@@ -12428,7 +12403,7 @@

Setup-teardown behaviour -
=========================================================== test session starts ===========================================================
+
=================================================================================== test session starts ====================================================================================
 platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
 rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
 plugins: nbval-0.9.0
@@ -12441,12 +12416,12 @@ 

Setup-teardown behaviour

@@ -12506,7 +12481,7 @@

Using fixtures automatically -
=========================================================== test session starts ===========================================================
+
=================================================================================== test session starts ====================================================================================
 platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
 rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
 plugins: nbval-0.9.0
@@ -12518,12 +12493,12 @@ 

Using fixtures automatically=0.3.0\n", "\n", "import pytest\n", "from ipytest import magics, clean_tests\n", From 88edde7b8e0b7e0079265793ba76b87f85725207 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Wed, 19 Sep 2018 22:14:23 +0200 Subject: [PATCH 18/60] Add link to more detailed tutorial --- notebooks/beginner/conditionals.ipynb | 13 ++++++++++--- notebooks/beginner/html/conditionals.html | 11 ++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/notebooks/beginner/conditionals.ipynb b/notebooks/beginner/conditionals.ipynb index 69fdc8d..3850f20 100644 --- a/notebooks/beginner/conditionals.ipynb +++ b/notebooks/beginner/conditionals.ipynb @@ -260,6 +260,13 @@ " \n", "print(greeting)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For more detailed overview about conditionals, check this [tutorial from Real Python](https://realpython.com/python-conditional-statements/)." + ] } ], "metadata": { @@ -271,7 +278,7 @@ "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3.0 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", @@ -282,5 +289,5 @@ } }, "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + "nbformat_minor": 1 +} diff --git a/notebooks/beginner/html/conditionals.html b/notebooks/beginner/html/conditionals.html index 08e0210..7f500c1 100644 --- a/notebooks/beginner/html/conditionals.html +++ b/notebooks/beginner/html/conditionals.html @@ -11777,7 +11777,7 @@ } $( document ).ready(function(){ - show=false; +show=false; $('div.output').hide() }); @@ -12377,6 +12377,15 @@

if-elif-else
+
+

From c8ab3057a7cea50c0f794628f94745616313a4be Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Wed, 19 Sep 2018 22:44:45 +0200 Subject: [PATCH 19/60] Add logging to a file --- notebooks/beginner/html/std_lib.html | 82 +++++++++++++++++++++------- notebooks/beginner/std_lib.ipynb | 39 +++++++++++++ 2 files changed, 102 insertions(+), 19 deletions(-) diff --git a/notebooks/beginner/html/std_lib.html b/notebooks/beginner/html/std_lib.html index 08b36a4..b6251fe 100644 --- a/notebooks/beginner/html/std_lib.html +++ b/notebooks/beginner/html/std_lib.html @@ -11848,11 +11848,11 @@

-
local now: 2018-09-19 22:00:35.202267
-utc now: 2018-09-19 20:00:35.202567
-2018 9 19 22 0 35
+
local now: 2018-09-19 22:44:15.396930
+utc now: 2018-09-19 20:44:15.397085
+2018 9 19 22 44 15
 date: 2018-09-19
-time: 22:00:35.202267
+time: 22:44:15.396930
 

@@ -11896,8 +11896,8 @@

strftime() -
2018/09/19-22:00:35
-date: 2018-09-19 time:22:00:35
+
2018/09/19-22:44:15
+date: 2018-09-19 time:22:44:15
 

@@ -11984,7 +11984,7 @@

-
tomorrow this time: 2018-09-20 22:00:35.202267
+
tomorrow this time: 2018-09-20 22:44:15.396930
 tomorrow - now = 1 day, 0:00:00
 days: 1, seconds: 0
 total seconds: 86400.0
@@ -12077,10 +12077,10 @@ 

Working with timezones -
naive utc now: 2018-09-19 20:00:36.074664, tzinfo: None
-utc now: 2018-09-19 20:00:36.074664+00:00, tzinfo: UTC
-Paris: 2018-09-19 22:00:36.074664+02:00, tzinfo: Europe/Paris
-New York: 2018-09-19 16:00:36.074664-04:00, tzinfo: America/New_York
+
naive utc now: 2018-09-19 20:44:16.308229, tzinfo: None
+utc now: 2018-09-19 20:44:16.308229+00:00, tzinfo: UTC
+Paris: 2018-09-19 22:44:16.308229+02:00, tzinfo: Europe/Paris
+New York: 2018-09-19 16:44:16.308229-04:00, tzinfo: America/New_York
 

@@ -12238,8 +12238,8 @@

Formatting log entries -
2018-09-19 22:00:36,127 | MyLogger     | WARNING    | Something bad is going to happen
-2018-09-19 22:00:36,128 | MyLogger     | ERROR      | Uups, it already happened
+
2018-09-19 22:44:16,365 | MyLogger     | WARNING    | Something bad is going to happen
+2018-09-19 22:44:16,366 | MyLogger     | ERROR      | Uups, it already happened
 

@@ -12252,13 +12252,57 @@

Formatting log entries
-

random for random number generation

+

Logging to a file

In [10]:
+
+
+
import os
+import logging
+
+# This is only required for Jupyter notebook environment
+from importlib import reload
+reload(logging)
+
+logger = logging.getLogger('MyFileLogger')
+
+# Let's define a file_handler for our logger
+log_path = os.path.join(os.getcwd(), 'my_log.txt')
+file_handler = logging.FileHandler(log_path)
+
+# And a nice format
+formatter = logging.Formatter('%(asctime)s | %(name)-12s | %(levelname)-10s | %(message)s')
+file_handler.setFormatter(formatter)
+
+logger.addHandler(file_handler)
+
+# If you want to see it also in the console, add another handler for it
+# logger.addHandler(logging.StreamHandler())
+
+logger.warning('Oops something is going to happen')
+logger.error('John Doe visits our place')
+
+ +
+
+
+ +
+
+
+
+
+

random for random number generation

+
+
+
+
+
+
In [11]:
@@ -12305,7 +12349,7 @@

-
In [11]:
+
In [12]:
import random
@@ -12367,7 +12411,7 @@ 

Searching occurences
-
In [12]:
+
In [13]:
import re
@@ -12420,7 +12464,7 @@ 

Variable validation
-
In [13]:
+
In [14]:
import re
diff --git a/notebooks/beginner/std_lib.ipynb b/notebooks/beginner/std_lib.ipynb
index e2eff73..3818bec 100644
--- a/notebooks/beginner/std_lib.ipynb
+++ b/notebooks/beginner/std_lib.ipynb
@@ -226,6 +226,45 @@
     "logger.error('Uups, it already happened')"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Logging to a file"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import os\n",
+    "import logging\n",
+    "\n",
+    "# This is only required for Jupyter notebook environment\n",
+    "from importlib import reload\n",
+    "reload(logging)\n",
+    "\n",
+    "logger = logging.getLogger('MyFileLogger')\n",
+    "\n",
+    "# Let's define a file_handler for our logger\n",
+    "log_path = os.path.join(os.getcwd(), 'my_log.txt')\n",
+    "file_handler = logging.FileHandler(log_path)\n",
+    "\n",
+    "# And a nice format\n",
+    "formatter = logging.Formatter('%(asctime)s | %(name)-12s | %(levelname)-10s | %(message)s')\n",
+    "file_handler.setFormatter(formatter)\n",
+    "\n",
+    "logger.addHandler(file_handler)\n",
+    "\n",
+    "# If you want to see it also in the console, add another handler for it\n",
+    "# logger.addHandler(logging.StreamHandler())\n",
+    "\n",
+    "logger.warning('Oops something is going to happen')\n",
+    "logger.error('John Doe visits our place')"
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {},

From c79d1ee950c6680147712abedceedce195030fb5 Mon Sep 17 00:00:00 2001
From: Jerry Pussinen 
Date: Fri, 21 Sep 2018 23:22:17 +0200
Subject: [PATCH 20/60] Update dir structure

---
 README.md                                     |    46 +-
 notebooks/beginner/html/file_io.html          |     6 +-
 .../beginner/{ => notebooks}/classes.ipynb    |     0
 .../{ => notebooks}/conditionals.ipynb        |     0
 .../beginner/{ => notebooks}/debugging.ipynb  |     0
 .../{ => notebooks}/dictionaries.ipynb        |     0
 .../beginner/{ => notebooks}/exceptions.ipynb |     0
 .../beginner/{ => notebooks}/file_io.ipynb    |     2 +-
 .../beginner/{ => notebooks}/for_loops.ipynb  |     0
 .../beginner/{ => notebooks}/functions.ipynb  |     0
 .../beginner/{ => notebooks}/lists.ipynb      |     0
 .../modules_and_packages.ipynb                |     0
 notebooks/beginner/notebooks/my_log.txt       |     2 +
 .../beginner/{ => notebooks}/numbers.ipynb    |     0
 .../{ => notebooks}/project_structure.ipynb   |     0
 .../beginner/{ => notebooks}/std_lib.ipynb    |     0
 .../beginner/{ => notebooks}/strings.ipynb    |     0
 .../beginner/{ => notebooks}/testing1.ipynb   |     0
 .../beginner/{ => notebooks}/testing2.ipynb   |     0
 notebooks/beginner/{ => notebooks}/venv.ipynb |     0
 .../intermediate/html/best_practices.html     | 12048 ++++++++++++++++
 .../notebooks/best_practices.ipynb            |   380 +
 .../{ => notebooks}/idiomatic_dicts.ipynb     |     0
 .../{ => notebooks}/idiomatic_loops.ipynb     |     0
 .../{ => notebooks}/idiomatic_misc1.ipynb     |     0
 .../{ => notebooks}/idiomatic_misc2.ipynb     |     0
 .../{ => notebooks}/pytest_fixtures.ipynb     |     0
 .../{ => notebooks}/std_lib2.ipynb            |     0
 28 files changed, 12457 insertions(+), 27 deletions(-)
 rename notebooks/beginner/{ => notebooks}/classes.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/conditionals.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/debugging.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/dictionaries.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/exceptions.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/file_io.ipynb (98%)
 rename notebooks/beginner/{ => notebooks}/for_loops.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/functions.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/lists.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/modules_and_packages.ipynb (100%)
 create mode 100644 notebooks/beginner/notebooks/my_log.txt
 rename notebooks/beginner/{ => notebooks}/numbers.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/project_structure.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/std_lib.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/strings.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/testing1.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/testing2.ipynb (100%)
 rename notebooks/beginner/{ => notebooks}/venv.ipynb (100%)
 create mode 100644 notebooks/intermediate/html/best_practices.html
 create mode 100644 notebooks/intermediate/notebooks/best_practices.ipynb
 rename notebooks/intermediate/{ => notebooks}/idiomatic_dicts.ipynb (100%)
 rename notebooks/intermediate/{ => notebooks}/idiomatic_loops.ipynb (100%)
 rename notebooks/intermediate/{ => notebooks}/idiomatic_misc1.ipynb (100%)
 rename notebooks/intermediate/{ => notebooks}/idiomatic_misc2.ipynb (100%)
 rename notebooks/intermediate/{ => notebooks}/pytest_fixtures.ipynb (100%)
 rename notebooks/intermediate/{ => notebooks}/std_lib2.ipynb (100%)

diff --git a/README.md b/README.md
index 49792da..a37f554 100644
--- a/README.md
+++ b/README.md
@@ -27,24 +27,24 @@ See [contributing](https://github.com/jerry-git/learn-python3/blob/master/CONTRI
 
 
 ## Beginner
-1. [Strings](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/strings.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/strings.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/strings_exercise.ipynb)
-1. [Numbers](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/numbers.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/numbers.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/numbers_exercise.ipynb)
-1. [Conditionals](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/conditionals.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/conditionals.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/conditionals_exercise.ipynb)
-1. [Lists](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/lists.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/lists.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/lists_exercise.ipynb)
-1. [Dictionaries](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/dictionaries.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/dictionaries.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/dictionaries_exercise.ipynb)
-1. [For loops](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/for_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/for_loops.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/for_loops_exercise.ipynb)
-1. [Functions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/functions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/functions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/functions_exercise.ipynb)
-1. [Testing with pytest - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/testing1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/testing1.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing1_exercise.ipynb)
+1. [Strings](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/strings.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/strings.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/strings_exercise.ipynb)
+1. [Numbers](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/numbers.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/numbers.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/numbers_exercise.ipynb)
+1. [Conditionals](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/conditionals.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/conditionals.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/conditionals_exercise.ipynb)
+1. [Lists](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/lists.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/lists.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/lists_exercise.ipynb)
+1. [Dictionaries](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/dictionaries.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/dictionaries.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/dictionaries_exercise.ipynb)
+1. [For loops](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/for_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/for_loops.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/for_loops_exercise.ipynb)
+1. [Functions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/functions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/functions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/functions_exercise.ipynb)
+1. [Testing with pytest - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/testing1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/testing1.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing1_exercise.ipynb)
 1. Recap exercise 1 [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/recap1_exercise.ipynb)
-1. [File I\O](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/file_io.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/file_io.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/file_io_exercise.ipynb)
-1. [Classes](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/classes.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/classes.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/classes_exercise.ipynb)
-1. [Exceptions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/exceptions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exceptions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/exceptions_exercise.ipynb)
-1. [Modules and packages](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/modules_and_packages.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/modules_and_packages.ipynb)
-1. [Debugging](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/debugging.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/debugging.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/debugging_exercise.ipynb)
-1. [Goodies of the Standard Library - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/std_lib.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/std_lib.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/std_lib1_exercise.ipynb)
-1. [Testing with pytest - part 2](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/testing2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/testing2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing2_exercise.ipynb)
-1. [Virtual environment](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/venv.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/venv.ipynb)
-1. [Project structure](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/project_structure.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/project_structure.ipynb)
+1. [File I\O](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/file_io.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/file_io.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/file_io_exercise.ipynb)
+1. [Classes](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/classes.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/classes.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/classes_exercise.ipynb)
+1. [Exceptions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/exceptions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/exceptions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/exceptions_exercise.ipynb)
+1. [Modules and packages](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/modules_and_packages.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/modules_and_packages.ipynb)
+1. [Debugging](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/debugging.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/debugging.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/debugging_exercise.ipynb)
+1. [Goodies of the Standard Library - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/std_lib.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/std_lib.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/std_lib1_exercise.ipynb)
+1. [Testing with pytest - part 2](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/testing2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/testing2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing2_exercise.ipynb)
+1. [Virtual environment](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/venv.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/venv.ipynb)
+1. [Project structure](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/project_structure.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/project_structure.ipynb)
 1. Recap exercise 2 [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/recap2_exercise.ipynb)
 
 
@@ -53,18 +53,18 @@ See [contributing](https://github.com/jerry-git/learn-python3/blob/master/CONTRI
 #### Idiomatic Python
 Python is a powerful language which contains many features not presented in most other programming languages. Idiomatic section will cover some of these Pythonic features in detail. These materials are especially useful for people with background in other programming languages.
 
-1. [Idiomatic loops](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_loops.ipynb)
-1. [Idiomatic dictionaries](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_dicts.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_dicts.ipynb)
-1. [Idiomatic Python - miscellaneous part 1](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_misc1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_misc1.ipynb)
-1. [Idiomatic Python - miscellaneous part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_misc2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/idiomatic_misc2.ipynb)
+1. [Idiomatic loops](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/idiomatic_loops.ipynb)
+1. [Idiomatic dictionaries](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_dicts.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/idiomatic_dicts.ipynb)
+1. [Idiomatic Python - miscellaneous part 1](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_misc1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/idiomatic_misc1.ipynb)
+1. [Idiomatic Python - miscellaneous part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_misc2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/idiomatic_misc2.ipynb)
 1. Idiomatic Python exercise [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/idiomatic_python_exercise.ipynb)
 
 #### Step up your `pytest` game
-1. [Efficient use of fixtures](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/pytest_fixtures.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/pytest_fixtures.ipynb)
+1. [Efficient use of fixtures](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/pytest_fixtures.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/pytest_fixtures.ipynb)
 1. Other tips and tricks
 
 #### General topics
-1. [Goodies of the Standard Library - part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/std_lib2_exercise.ipynb)
+1. [Goodies of the Standard Library - part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/std_lib2_exercise.ipynb)
 
 #### Backlog
 * Sets
diff --git a/notebooks/beginner/html/file_io.html b/notebooks/beginner/html/file_io.html
index ddc9486..5cb4038 100644
--- a/notebooks/beginner/html/file_io.html
+++ b/notebooks/beginner/html/file_io.html
@@ -11827,7 +11827,7 @@ 

Working with pathsprint('current directory: {}'.format(current_dir)) # Note: in .py files you can get the dir of current file by os.path.dirname(__file__) -data_dir = os.path.join(current_dir, 'data') +data_dir = os.path.join(os.path.dirname(current_dir), 'data') print('data directory: {}'.format(data_dir))

@@ -11845,8 +11845,8 @@

Working with paths -
current file: /Users/jerry/github/jerry-git/learn-python3/notebooks/beginner/file_io.ipynb
-current directory: /Users/jerry/github/jerry-git/learn-python3/notebooks/beginner
+
current file: /Users/jerry/github/jerry-git/learn-python3/notebooks/beginner/notebooks/file_io.ipynb
+current directory: /Users/jerry/github/jerry-git/learn-python3/notebooks/beginner/notebooks
 data directory: /Users/jerry/github/jerry-git/learn-python3/notebooks/beginner/data
 

diff --git a/notebooks/beginner/classes.ipynb b/notebooks/beginner/notebooks/classes.ipynb similarity index 100% rename from notebooks/beginner/classes.ipynb rename to notebooks/beginner/notebooks/classes.ipynb diff --git a/notebooks/beginner/conditionals.ipynb b/notebooks/beginner/notebooks/conditionals.ipynb similarity index 100% rename from notebooks/beginner/conditionals.ipynb rename to notebooks/beginner/notebooks/conditionals.ipynb diff --git a/notebooks/beginner/debugging.ipynb b/notebooks/beginner/notebooks/debugging.ipynb similarity index 100% rename from notebooks/beginner/debugging.ipynb rename to notebooks/beginner/notebooks/debugging.ipynb diff --git a/notebooks/beginner/dictionaries.ipynb b/notebooks/beginner/notebooks/dictionaries.ipynb similarity index 100% rename from notebooks/beginner/dictionaries.ipynb rename to notebooks/beginner/notebooks/dictionaries.ipynb diff --git a/notebooks/beginner/exceptions.ipynb b/notebooks/beginner/notebooks/exceptions.ipynb similarity index 100% rename from notebooks/beginner/exceptions.ipynb rename to notebooks/beginner/notebooks/exceptions.ipynb diff --git a/notebooks/beginner/file_io.ipynb b/notebooks/beginner/notebooks/file_io.ipynb similarity index 98% rename from notebooks/beginner/file_io.ipynb rename to notebooks/beginner/notebooks/file_io.ipynb index bc004ca..76c8ee2 100644 --- a/notebooks/beginner/file_io.ipynb +++ b/notebooks/beginner/notebooks/file_io.ipynb @@ -31,7 +31,7 @@ "print('current directory: {}'.format(current_dir))\n", "# Note: in .py files you can get the dir of current file by os.path.dirname(__file__)\n", "\n", - "data_dir = os.path.join(current_dir, 'data')\n", + "data_dir = os.path.join(os.path.dirname(current_dir), 'data')\n", "print('data directory: {}'.format(data_dir))" ] }, diff --git a/notebooks/beginner/for_loops.ipynb b/notebooks/beginner/notebooks/for_loops.ipynb similarity index 100% rename from notebooks/beginner/for_loops.ipynb rename to notebooks/beginner/notebooks/for_loops.ipynb diff --git a/notebooks/beginner/functions.ipynb b/notebooks/beginner/notebooks/functions.ipynb similarity index 100% rename from notebooks/beginner/functions.ipynb rename to notebooks/beginner/notebooks/functions.ipynb diff --git a/notebooks/beginner/lists.ipynb b/notebooks/beginner/notebooks/lists.ipynb similarity index 100% rename from notebooks/beginner/lists.ipynb rename to notebooks/beginner/notebooks/lists.ipynb diff --git a/notebooks/beginner/modules_and_packages.ipynb b/notebooks/beginner/notebooks/modules_and_packages.ipynb similarity index 100% rename from notebooks/beginner/modules_and_packages.ipynb rename to notebooks/beginner/notebooks/modules_and_packages.ipynb diff --git a/notebooks/beginner/notebooks/my_log.txt b/notebooks/beginner/notebooks/my_log.txt new file mode 100644 index 0000000..1a87c50 --- /dev/null +++ b/notebooks/beginner/notebooks/my_log.txt @@ -0,0 +1,2 @@ +2018-09-21 23:17:54,486 | MyFileLogger | WARNING | Oops something is going to happen +2018-09-21 23:17:54,486 | MyFileLogger | ERROR | John Doe visits our place diff --git a/notebooks/beginner/numbers.ipynb b/notebooks/beginner/notebooks/numbers.ipynb similarity index 100% rename from notebooks/beginner/numbers.ipynb rename to notebooks/beginner/notebooks/numbers.ipynb diff --git a/notebooks/beginner/project_structure.ipynb b/notebooks/beginner/notebooks/project_structure.ipynb similarity index 100% rename from notebooks/beginner/project_structure.ipynb rename to notebooks/beginner/notebooks/project_structure.ipynb diff --git a/notebooks/beginner/std_lib.ipynb b/notebooks/beginner/notebooks/std_lib.ipynb similarity index 100% rename from notebooks/beginner/std_lib.ipynb rename to notebooks/beginner/notebooks/std_lib.ipynb diff --git a/notebooks/beginner/strings.ipynb b/notebooks/beginner/notebooks/strings.ipynb similarity index 100% rename from notebooks/beginner/strings.ipynb rename to notebooks/beginner/notebooks/strings.ipynb diff --git a/notebooks/beginner/testing1.ipynb b/notebooks/beginner/notebooks/testing1.ipynb similarity index 100% rename from notebooks/beginner/testing1.ipynb rename to notebooks/beginner/notebooks/testing1.ipynb diff --git a/notebooks/beginner/testing2.ipynb b/notebooks/beginner/notebooks/testing2.ipynb similarity index 100% rename from notebooks/beginner/testing2.ipynb rename to notebooks/beginner/notebooks/testing2.ipynb diff --git a/notebooks/beginner/venv.ipynb b/notebooks/beginner/notebooks/venv.ipynb similarity index 100% rename from notebooks/beginner/venv.ipynb rename to notebooks/beginner/notebooks/venv.ipynb diff --git a/notebooks/intermediate/html/best_practices.html b/notebooks/intermediate/html/best_practices.html new file mode 100644 index 0000000..f8bb112 --- /dev/null +++ b/notebooks/intermediate/html/best_practices.html @@ -0,0 +1,12048 @@ + + + +tmp_best_practices + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + +
+
+
+
+
+
+

Test your code

+ +
+
+
+
+
+
+
+

Why

    +
  • No surprises (especially in production)
  • +
  • Make sure that everything works as expected
  • +
  • Make sure that old stuff works as expected after introducing new features (regression)
  • +
  • Tests give you confidence while refactoring
  • +
  • It documents how your implementation is used
  • +
  • ...
  • +
+ +
+
+
+
+
+
+
+

Tooling

pytest

There's unittest module in Python Standard Library but the go-to test runner nowadays is definitely pytest.

+

Some reasons to use pytest:

+ + +
+
+
+
+
+
+
+

tox

tox makes it simple to test your code against different Python interpreter/language and dependency versions. This is important when you're writing software which should support different Python versions, which is usually the case with library-like packages. On the other hand, if you're developing, say, a web application which will be deployed to a known target platform, testing against multiple different versions is not necessary. However, tox makes it also possible to configure, for example, linting and building of docs as part of tox run. Thus, it tox may simplify the development workflow significantly by wrapping multiple different operations under single command.

+ +
+
+
+
+
+
+
+

Write high quality code

+ +
+
+
+
+
+
+
+

Why

    +
  • Easy to read
  • +
  • Better maintainability
  • +
+ +
+
+
+
+
+
+
+

Tooling - code formatters

+
+
+
+
+
+
+
+

Tooling - linters

+
+
+
+
+
+
+
+

Tooling - pre-commit

+
+
+
+
+
+
+
+

Structure your code

+ +
+
+
+
+
+
+
+

Why

+
+
+
+
+
+
+
+

Structure your projects

+
+
+
+
+
+
+
+

Why

+
+
+
+
+
+
+
+

One environment per project

+ +
+
+
+
+
+
+
+

Why

+
+
+
+
+
+
+
+

Tooling

+
+
+
+
+
+
+
+

Use continuous integration

+
+
+
+
+
+
+
+

Why

+
+
+
+
+
+
+
+

Utilize the capabitilies of your editor

+
+
+
+
+
+
+
+

Why

+
+
+
+
+
+
+
+

Use existing solutions

+ +
+
+
+
+
+
+
+

Why

+
+
+
+
+
+
+
+

std lib, Pypi

+ +
+
+
+
+
+
+
+

Use Cookiecutter

+
+
+
+
+
+
+
+

Use logging instead of prints

+ +
+
+
+
+
+ + + + + + diff --git a/notebooks/intermediate/notebooks/best_practices.ipynb b/notebooks/intermediate/notebooks/best_practices.ipynb new file mode 100644 index 0000000..4cf89ce --- /dev/null +++ b/notebooks/intermediate/notebooks/best_practices.ipynb @@ -0,0 +1,380 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Best practices in development" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test your code\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why\n", + "* No surprises (especially in production)\n", + "* Make sure that everything works as expected\n", + "* Make sure that old stuff works as expected after introducing new features (regression)\n", + "* Tests give you confidence while refactoring\n", + "* It documents how your implementation is used \n", + "* ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tooling\n", + "#### [`pytest`](https://docs.pytest.org/en/latest/)\n", + "There's [`unittest`](https://docs.python.org/3/library/unittest.html) module in Python Standard Library but the go-to test runner nowadays is definitely `pytest`.\n", + "\n", + "Some reasons to use `pytest`:\n", + "* [`fixtures`](https://docs.pytest.org/en/latest/fixture.html#fixture) for writing reusable testing code\n", + "* [`markers`](https://docs.pytest.org/en/latest/example/markers.html) for splitting tests to different groups (e.g. smoke, run only on CI machine, etc) or skipping tests in certain conditions\n", + "* [Automatic test discovery](https://docs.pytest.org/en/latest/goodpractices.html#test-discovery)\n", + "* [Configurability](https://docs.pytest.org/en/latest/customize.html)\n", + "* Active development of plugins, to mention a few:\n", + " * [`pytest-cov`](https://pytest-cov.readthedocs.io/en/latest/) for coverage reporting\n", + " * [`pytest-xdist`](https://github.com/pytest-dev/pytest-xdist) for speeding up test suit run time with parallelization\n", + " * see [complete list](https://github.com/pytest-dev) of plugins maintained by `pytest`\n", + "* Ease of [writing own plugins](https://docs.pytest.org/en/latest/writing_plugins.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### [`tox`](https://tox.readthedocs.io/en/latest/)\n", + "`tox` makes it simple to test your code against different Python interpreter/language and dependency versions. This is important when you're writing software which should support different Python versions, which is usually the case with library-like packages. On the other hand, if you're developing, say, a web application which will be deployed to a known target platform, testing against multiple different versions is not necessary. However, `tox` makes it also possible to configure, for example, linting and building of docs as part of `tox` run. Thus, it `tox` may simplify the development workflow significantly by wrapping multiple different operations under single command." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Write high quality code\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why\n", + "* Easy to read\n", + "* Better maintainability" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tooling - code formatters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tooling - linters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tooling - pre-commit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Structure your code\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Structure your projects" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## One environment per project\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tooling" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Use continuous integration" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Utilize the capabitilies of your editor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Use existing solutions\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "std lib, Pypi" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Use Cookiecutter" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Use logging instead of prints\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "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 +} diff --git a/notebooks/intermediate/idiomatic_dicts.ipynb b/notebooks/intermediate/notebooks/idiomatic_dicts.ipynb similarity index 100% rename from notebooks/intermediate/idiomatic_dicts.ipynb rename to notebooks/intermediate/notebooks/idiomatic_dicts.ipynb diff --git a/notebooks/intermediate/idiomatic_loops.ipynb b/notebooks/intermediate/notebooks/idiomatic_loops.ipynb similarity index 100% rename from notebooks/intermediate/idiomatic_loops.ipynb rename to notebooks/intermediate/notebooks/idiomatic_loops.ipynb diff --git a/notebooks/intermediate/idiomatic_misc1.ipynb b/notebooks/intermediate/notebooks/idiomatic_misc1.ipynb similarity index 100% rename from notebooks/intermediate/idiomatic_misc1.ipynb rename to notebooks/intermediate/notebooks/idiomatic_misc1.ipynb diff --git a/notebooks/intermediate/idiomatic_misc2.ipynb b/notebooks/intermediate/notebooks/idiomatic_misc2.ipynb similarity index 100% rename from notebooks/intermediate/idiomatic_misc2.ipynb rename to notebooks/intermediate/notebooks/idiomatic_misc2.ipynb diff --git a/notebooks/intermediate/pytest_fixtures.ipynb b/notebooks/intermediate/notebooks/pytest_fixtures.ipynb similarity index 100% rename from notebooks/intermediate/pytest_fixtures.ipynb rename to notebooks/intermediate/notebooks/pytest_fixtures.ipynb diff --git a/notebooks/intermediate/std_lib2.ipynb b/notebooks/intermediate/notebooks/std_lib2.ipynb similarity index 100% rename from notebooks/intermediate/std_lib2.ipynb rename to notebooks/intermediate/notebooks/std_lib2.ipynb From 63762ea3cb7cd2bbb967f1b7d66f1f69050d7a95 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Fri, 21 Sep 2018 23:26:53 +0200 Subject: [PATCH 21/60] Adapt post save hook to changed dir structure --- utils/post_save_hook.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/utils/post_save_hook.py b/utils/post_save_hook.py index 6111e3f..daf2b6f 100644 --- a/utils/post_save_hook.py +++ b/utils/post_save_hook.py @@ -29,7 +29,7 @@ "\n", "\n", "
\n", " Date: Sun, 23 Sep 2018 13:19:39 +0200 Subject: [PATCH 22/60] Add best practices --- README.md | 4 + .../intermediate/html/best_practices.html | 465 +++++++++++++++++- notebooks/intermediate/img/bad_code.jpg | Bin 0 -> 33450 bytes notebooks/intermediate/img/ci.jpg | Bin 0 -> 33325 bytes notebooks/intermediate/img/cookiecutter.jpg | Bin 0 -> 43643 bytes notebooks/intermediate/img/debugging.jpg | Bin 0 -> 55137 bytes .../intermediate/img/high_quality_code.png | Bin 0 -> 133588 bytes notebooks/intermediate/img/ide.jpg | Bin 0 -> 35166 bytes notebooks/intermediate/img/prints.jpg | Bin 0 -> 21118 bytes notebooks/intermediate/img/reinvent.jpg | Bin 0 -> 32737 bytes notebooks/intermediate/img/testing.png | Bin 0 -> 352475 bytes notebooks/intermediate/img/virtualenvs.jpg | Bin 0 -> 31928 bytes .../notebooks/best_practices.ipynb | 362 ++++++++++---- 13 files changed, 709 insertions(+), 122 deletions(-) create mode 100644 notebooks/intermediate/img/bad_code.jpg create mode 100644 notebooks/intermediate/img/ci.jpg create mode 100644 notebooks/intermediate/img/cookiecutter.jpg create mode 100644 notebooks/intermediate/img/debugging.jpg create mode 100644 notebooks/intermediate/img/high_quality_code.png create mode 100644 notebooks/intermediate/img/ide.jpg create mode 100644 notebooks/intermediate/img/prints.jpg create mode 100644 notebooks/intermediate/img/reinvent.jpg create mode 100644 notebooks/intermediate/img/testing.png create mode 100644 notebooks/intermediate/img/virtualenvs.jpg diff --git a/README.md b/README.md index a37f554..59b3d65 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,10 @@ Python is a powerful language which contains many features not presented in most 1. [Efficient use of fixtures](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/pytest_fixtures.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/pytest_fixtures.ipynb) 1. Other tips and tricks +#### Best practices +1. A list of best development practices for Python projects. Most of the practices listed here are also applicable for other languages, however the presented tooling focuses mainly on Python. +[Best practices](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/best_practices.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/best_practices.ipynb) + #### General topics 1. [Goodies of the Standard Library - part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/std_lib2_exercise.ipynb) diff --git a/notebooks/intermediate/html/best_practices.html b/notebooks/intermediate/html/best_practices.html index f8bb112..2803cb6 100644 --- a/notebooks/intermediate/html/best_practices.html +++ b/notebooks/intermediate/html/best_practices.html @@ -11800,6 +11800,70 @@

Best practices in development

+
+
+
+
+
+
+
+

One virtual environment per project

+ +
+
+
+
+
+
+
+

Why

    +
  • Isolation
  • +
  • Different projects have different dependency versions
  • +
  • You don't want to mess up the system Python
  • +
+ +
+
+
+
+
+
+
+

Tooling

pipenv is currently the recommended tool for dependency management but "consider other tools such as pip when pipenv does not meet your use case". If pipenv doesn't fit your use case, I recommend using virtualenvwrapper for managing virtual environments and pip for package management. On the other hand, if you're working on only a couple of projects, built-in venv will do just fine.

+

pipenv

+ +
+
+
+
+
+
+
+

virtualenvwrapper

    +
  • If you are using Windows command prompt: virtualenvwrapper-win
  • +
  • Like the name suggests, a wrapper around virtualenv
  • +
  • Eases the workflow for creating, deleting, and (de)activating your virtual environments
  • +
+ +
+
+
+
+
+
+
+

pyenv

    +
  • Easily change global / per project Python version
  • +
  • Also a tool for installing different Python versions (also different runtimes available, e.g. PyPy)
  • +
  • Useful if you'll need to work with different Python versions
  • +
+
@@ -11821,7 +11885,7 @@

Why

  • Make sure that everything works as expected
  • Make sure that old stuff works as expected after introducing new features (regression)
  • Tests give you confidence while refactoring
  • -
  • It documents how your implementation is used
  • +
  • Good tests demonstrate the use cases of application, i.e. they also document the implementation
  • ...
@@ -11855,7 +11919,7 @@

Tooling

-

tox

tox makes it simple to test your code against different Python interpreter/language and dependency versions. This is important when you're writing software which should support different Python versions, which is usually the case with library-like packages. On the other hand, if you're developing, say, a web application which will be deployed to a known target platform, testing against multiple different versions is not necessary. However, tox makes it also possible to configure, for example, linting and building of docs as part of tox run. Thus, it tox may simplify the development workflow significantly by wrapping multiple different operations under single command.

+

tox

tox makes it simple to test your code against different Python interpreter/runtime and dependency versions. This is important when you're writing software which should support different Python versions, which is usually the case with library-like packages. On the other hand, if you're developing, say, a web application which will be deployed to a known target platform, testing against multiple different versions is usually not necessary. However, tox makes it also possible to configure, for example, linting as part of tox run. Thus, tox may simplify the development workflow significantly by wrapping multiple different operations under a single command.

@@ -11876,16 +11940,69 @@

Write high quality codeWhy

  • Easy to read
  • Better maintainability
  • +
  • Better quality == less bugs

+
+
+
+
In [1]:
+
+
+
import this
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
The Zen of Python, by Tim Peters
+
+Beautiful is better than ugly.
+Explicit is better than implicit.
+Simple is better than complex.
+Complex is better than complicated.
+Flat is better than nested.
+Sparse is better than dense.
+Readability counts.
+Special cases aren't special enough to break the rules.
+Although practicality beats purity.
+Errors should never pass silently.
+Unless explicitly silenced.
+In the face of ambiguity, refuse the temptation to guess.
+There should be one-- and preferably only one --obvious way to do it.
+Although that way may not be obvious at first unless you're Dutch.
+Now is better than never.
+Although never is often better than *right* now.
+If the implementation is hard to explain, it's a bad idea.
+If the implementation is easy to explain, it may be a good idea.
+Namespaces are one honking great idea -- let's do more of those!
+
+
+
+ +
+
+
-

Tooling - code formatters

+

Tooling - code formatters

PEP8 (see also "for humans version") describes the style guidelines for Python code, you should follow them. Luckily, there are awesome tools that handle this for you while you focus on writing code, not formatting it.

+
@@ -11893,7 +12010,11 @@

Tooling - code formatters
-

Tooling - linters

+

yapf

+

@@ -11901,7 +12022,14 @@

Tooling - linters
-

Tooling - pre-commit

+

black

    +
  • Note requires Python 3.6+
  • +
  • Note "This is a beta product" while writing this
  • +
  • Uncompromising - not as many configuration options as in yapf
  • +
  • Good integration with editors
  • +
  • Try it in the playground
  • +
+

@@ -11909,7 +12037,7 @@

Tooling - pre-commit
-

Structure your code

+

Tooling - linters

Automatic code formatting is great but in addition to that, you should use static analyzer (linter) to detect potential pitfalls in your code.

@@ -11918,7 +12046,10 @@

Structure your code
-

Why

+

flake8

+

@@ -11926,7 +12057,12 @@

Why

-

Structure your projects

+

pylint

    +
  • More verbose compared to flake8
  • +
  • Criticized about the default configuration but is easily configurable
  • +
  • Gives an overall score
  • +
+
@@ -11934,7 +12070,10 @@

Structure your projects
-

Why

+

bandit

    +
  • Checks for security vulnerabilities
  • +
+

@@ -11942,7 +12081,17 @@

Why

-

One environment per project

+

Tooling - pre-commit

pre-commit

Ideally, all project contributors should follow the best practices of the project, let it be e.g. respecting PEP8 or making sure there's no linting errors or security vulnerabilities in their change sets. However, as code formatters and linters are (mainly) local tools, this can not be guaranteed. pre-commit let's you configure (.pre-commit-config.yaml file) a set of hooks that will be run as pre actions to a commit/push. After a developer has called once pre-commit install, these hooks will be then automatically ran prior each commit/push.

+
    +
  • Run formatting before commit
  • +
  • Fail the commit in case linting errors
  • +
  • Even exercise the test suite before the code ends up to remote (might be time consuming in most scenarios though)
  • +
  • Easy to configure your own hooks
  • +
  • And use the existing ones
  • +
  • There's also pre-push option
  • +
  • Written in Python but supports also other languages, such as Ruby, Go, and Rust
  • +
  • Less failed CI builds!
  • +
@@ -11951,7 +12100,8 @@

One environment per project
-

Why

+

Structure your code and projects

+

@@ -11959,7 +12109,11 @@

Why

-

Tooling

+

Why

    +
  • Package and module structure gives an overview about the project
  • +
  • Modular design == better reusability
  • +
+
@@ -11967,7 +12121,13 @@

Tooling

-

Use continuous integration

+

How

Some general guidelines:

+
    +
  • Don't put too much stuff into one module
  • +
  • Split project into packages
  • +
  • Be consistent with your naming conventions
  • +
+
@@ -11975,7 +12135,84 @@

Use continuous integration
-

Why

+

A few words about structuring your projects. If you're developing, say, a relative big business application, it makes sense to separate some of the non-core business logic packages into a separate project and publish that as separate package. This way the "main" repository doesn't get bloated and it's more approachable for newcomers. Additionally, there's a change that you (or someone else) can easily reuse this "separated" package in the future, which is often the case e.g. for different kinds of utility functionalities.

+

Let's take a practical example. If your team has two different applications which interact with the same third party, it's beneficial to implement a separate client library for communication with it. This way a change is needed only in one place (in the client library) if the third party decides to make a backwards incompatible change in their API.

+ +
+

+
+
+
+
+
+

Tooling

cookiecutter

+ +
+
+
+
+
+
+
+

Cookiecutter is a tool which let's you create projects from predefined templates.

+
    +
  • Rapid set-up of new projects, no need to copy paste from existing ones
  • +
  • Consistent development practices across all projects (project structure as well as e.g. pre-commit, tox, and CI configuration)
  • +
  • You can create one yourself or use some of the existing ones
  • +
  • Written in Python but is applicable for non-Python projects as well, even non-programming related directory and file structures
  • +
+ +
+
+
+
+
+
+
+

Use continuous integration and deployment

+ +
+
+
+
+
+
+
+

CI & CD belong to the best practices of software development without controversy, no matter what is the technology stack used for development. From Python point of view, CI is the place where we want to make sure that the other best practices described above are followed. For example, in bigger projects, it may not be even practical/possible to run the full test suite on developer's machine.

+ +
+
+
+
+
+
+
+

Why

    +
  • Make sure the tests pass
  • +
  • CI is the place where it's possible to run also some time consuming tests which the impatient developers prefer to skip on their local machines
  • +
  • Make sure there's no linting errors
  • +
  • Ideally, the place to test against all target versions and platforms
  • +
  • Overall, CI is the last resort for automatically ensuring the quality
  • +
  • Manual deployments are time consuming and error-prone, CD is automated and deterministic
  • +
  • You want to automate as much as possible, human time is expensive
  • +
  • Minimize the time required for code reviews - what could be detected with automatic tools, should be detected by using those tools. Human time is expensive.
  • +
+ +
+
+
+
+
+
+
+

Tooling

Tooling depends on which git repository manager option you've chosen and what kind of requirements you have. For example:

+ +
@@ -11991,7 +12228,74 @@

Utilize the capabitilies of you

-

Why

+

Why

    +
  • Efficient and fluent development
  • +
  • There's plenty of tools to make your daily programming easier, why would you not use them
  • +
+ +
+
+
+
+
+
+
+

Tooling

As there's a number of different editors and IDEs available, not to mention that everyone has their own preferences, I'll just focus on highlighting some of the features of my favorite IDE, PyCharm, which I highly recommend for Python development.

+

PyCharm

    +
  • Good integration with pytest, e.g. run single tests / test classes / test modules
  • +
  • Git integration (in case you don't like command line)
  • +
  • Easy to configure to use automatic formatting, e.g black
  • +
  • Intuitive searching capabilities
  • +
  • Refactoring features
  • +
  • Debugger
  • +
  • Jupyter Notebook integration
  • +
  • Free community edition already contains all you need
  • +
+ +
+
+
+
+
+
+
+

Use existing solutions

+ +
+
+
+
+
+
+
+

Why

    +
  • Python Standard Library is extensive - and stable!
  • +
  • There are over 150k packages in PyPI
  • +
  • Someone has most likely solved the problem you're trying to solve
  • +
  • Spend 5 minutes doing a google research before starting to solve a new problem, e.g. stackoverflow is a magical place.
  • +
+ +
+
+
+
+
+
+
+

Learn how to debug efficiently

+ +
+
+
+
+
+
+
+

Why

    +
  • You won't write completely stable code anyway - impossible looking conditions will occur.
  • +
  • When something is not working as expected, there are plenty of tools out there to help you figure out what's going on.
  • +
+
@@ -11999,7 +12303,10 @@

Why

-

Use existing solutions

+

Tooling - debuggers

pdb

    +
  • Part of the Standard Library
  • +
  • Sufficient for most use cases
  • +
@@ -12008,7 +12315,10 @@

Use existing solutions
-

Why

+

ipdb

    +
  • Feature rich pdb with similar API
  • +
+

@@ -12016,7 +12326,9 @@

Why

-

std lib, Pypi

+

pdb++

    +
  • Drop-in replacement for pdb with additional features
  • +
@@ -12025,7 +12337,31 @@

Why

-

Use Cookiecutter

+

Tooling - profilers

+
+
+
+
+
+
+
+

gprof2dot

    +
  • Find the performance bottlenecks of your application via illustrative graphs
  • +
  • If you're using pytest (like you should), see also pytest-profiling which is powered by gprof2dot
  • +
+ +
+
+
+
+
+
+
+

py-spy

    +
  • Profile running Python program without the need for modifying the source code or restarting the target process
  • +
  • Potential tool for identifying problems of e.g. a web application in production
  • +
+
@@ -12033,7 +12369,96 @@

Use Cookiecutter
-

Use logging instead of prints

+

objgraph

    +
  • Graphs which are useful while hunting memory leaks
  • +
+ +
+

+ +
+
+
+
+

Tooling - runtime error tracking

These are especially useful with web applications as you'll get reports - and notifications - of runtime exceptions with full tracebacks and variable values. This information is often enough for identifying the root cause of the problem, which is a huge benefit considering the time required for implementing and deploying the fix.

+ +
+
+
+
+
+
+
+

Sentry

    +
  • Complete stack traces with relevant variable (locals()) values
  • +
  • Browser and OS information of the client
  • +
  • Support for other languages as well
  • +
+ +
+
+
+
+
+
+
+

rollbar

    +
  • Very similar to sentry
  • +
+ +
+
+
+
+
+
+
+

While writing this, both sentry and rollbar are free for hobbyist use.

+ +
+
+
+
+
+
+
+

Tooling - misc

+
+
+
+
+
+
+
+

Use logging instead of prints

+ +
+
+
+
+
+
+
+
    +
  • logging is part of the Standard Library
  • +
  • With logging you can redirect the output to a file
  • +
  • Logs are usually the first place to look at after an end user reports an issue
  • +
  • You can specify the runtime level - no need to remove the debug prints
  • +
+ +
+
+
+
+
+
+
+

General guidelines

    +
  • Use Python 3, legacy Python (aka 2.7) will retire soon
  • +
  • Develop in branches. Even if you're the only person in the project, branching makes it possible to easily switch between different features / bug fixes.
  • +
  • If you're not developing alone, practice code reviews. It's one of the best ways to learn for both parties.
  • +
  • Document your master pieces
  • +
diff --git a/notebooks/intermediate/img/bad_code.jpg b/notebooks/intermediate/img/bad_code.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c42c8f5b9d33442e5be946141cfeb15d9e099904 GIT binary patch literal 33450 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 Lwl9DOuWSDUO1W2t literal 0 HcmV?d00001 diff --git a/notebooks/intermediate/img/ci.jpg b/notebooks/intermediate/img/ci.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d506a5228d02c93364e2f04559d728a797471823 GIT binary patch literal 33325 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 f(5Kd)k^o?X2<642A6A_$` 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 F|Jh57H@5%) literal 0 HcmV?d00001 diff --git a/notebooks/intermediate/img/cookiecutter.jpg b/notebooks/intermediate/img/cookiecutter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6c02f41e48dc7d8855d89f12cbc79723a7f0529f GIT binary patch literal 43643 zcmb4qbyQnT*Ka5eEmo`)2<}q6XbQ!pXmKeNE$&WQTnZGo0!4!qQrw}q7l-2R5FCOe z+&s_we)n7J{&)9TIcKkPX7=pg?3p<;zs!03`?v-mQkGYe2cV$=0E(ys@VE~6D(7Qo z4FIUA0XP5v01f~XjRb&>($G)`0F4TO`L7NDD5Jgnzq%G0+kewM0RSTG02u#GV~D!` zBPh%NSxH(==b_;{nwe`=4>skKi&vk6i#_9JFs}-_X$*08fa~(23C=djLR`7no@O z%D>qF0Q4sqXqW&jY#dxXd{lyNA^;jX>K-}<76vvJ1`d`x+7kdeF$M`eCf{=gA}nc5 zeo}K+M(i(i2{L4PS^`x}7O%)V-6q~93I^k>YrkRsNFj8Z>RH}#T1p4_4Ex4ZEWp6dHeYK zg-1k2MSn|8OV7ysQB({mDJ}a|SKrXs)cm`rx37O-aA?+6Rp)h`1MnXXpl-8>&$9s%=r#+SGLMb|l7z@(RmkPGx(Mc^;E!{se3 zsP)z;0GC0pW9=3)-U0G^1f-nYXL6^k-^p!?8{RppE?rg@UYH8ZxfyTrwoQ4g5So%5 z(Ynw22kA|J2V3@cU9Fzcv;|6Bw2y^VPKMtFhk-Snb+X5vE$hYJ1LOQ@e88O3=WP;? zfOogxl3Q;P1;~TvHKx)unWy20B!R09{kZ^Y6oGhCuMXXw2AOezq3o5K3o3Wn%0Xb=()Q^ zj@|Mef)aIq1`RfJYz7ulNtx~0!2;4|%OeUf&1oTTXZf(R+cw1%1z=6cU@4KKpck-| z^?=-QG_iNt1>{eZ=jGdsU<=*2*KyF9S!}FaxGw|)M>1tN~BcNY0 zezzo$u*>UGb5Ba^u4Zc`$Ew8Y4w`xapKOOf-``fZuC%8$p4&W)Z(dV1_hr!{cd6%Gl*p40R!n<&J_7dM8XT zSqG&EKI39Lttd3#=VY>F%b|6L_l_9Q5!RG>%XbN7Ib!K>8_YP{O#8GqWbj>wzqo`)w@8W1pX*$d zpG!%#A4fdDWR+Sm5Yfr$PZ6_mSl4K@Qrq!VfAjE~ER2z~fGO%--+5HjK1?gII8~ao zY&wP1Pq*@CVF=qu81WnSU`s5w>3u1G{ea9rMVng^DcKt?2M0%nA-nA{+t?Cz^X=_x z;h^|X6S1>rSVON1jiqQ z98=ByGh(KRU&C|@OG>Hhxs$3<=t$-8v?5FJTxb~6vHq|xT-+Yc)$GjM?D-*1zCRzl zGR7Tpvmbl0*VrCR}VUzIQ}lFrrYL;q-8MvwV*=y54l-xU=|y(^Q+i`7?i3iCpKjqO8`rfT=5= zxF246YGjEfo|YcNY*?~pm+EdWTA$o2RRQ*3k93TOToBlK;6fsvqIAL7_lv936_nZf zYI`?#&r46r)P^?RXc%W%d9lq?I{d0kn z`A>Uj8R=wl3YlSF5r)C&xtV^3066uoXV}%_+_ZhmI8dSg${G#v2uQUX^`I7^DB70M zkaAzqVIYf&h-9IjtQLClCPZ>%D}vyVg&cuRRDoUQ4V3bu0P_}7g`X_lZYoxdG`hwH&y;x6l=*nMG&zo^<|heNU1f(S`1^;YH9507LF7r9~X6hiCCuex_~G9jZwtq zBz<~u)0)LD)7+ZPm#?I%H5p0zm$^0op&A{?%0ZP)UR6>eoQ)34HpUvVTCnLz%VG4X@uGmoyke&tK!nKs&{-_;^19=aZ{Y`!5khx;` ze_8_k+;L54#WwJ!zpL)N|F9{qD_gadEaY~_te?DB8Iya(G~wiXQJgYUp4WM2s8r9= zMy@>L8*28RuCDHb(-`M3hr`^>SxCyE=+{63r|R?aVVH*T7kmcM&$1#vcgIL9v`4pjDLMhWViKeM_1jIJOxNrk|g`O~)rsHG<#WRY|I6H4K0Nkgw+S2OY4+`*)Jn`3qMut!OLf;=x>R*ahA z_B^5qp|;>=nkDPF?0aa~gfKOHxlo(mj?VZQwVr_EBqYoT?7Ke?LX-AxuL*o%S>GLSj$3rMk_iN<9g9Q?Zjrfp z?8`izsjmz-@RUcgXFOxQROPH*RCI_~DLY#(mSY_~`?E_>yk!R3pJ~P#e)rjPHrvNQ z@TEygDbwF(!@p>1&hPd1j0zMu?DpJm%(t4eDZaYF>o7=dp)W7y`1ZHc#JT6Y4b64K z3E59K9U8}EFIvV#rmlJ9FQz6Q_QAUNg9q?HGn;_U>KX08{w)JgaKv%Dsu_3vz414= z^&{ZOI_31KHa3L!E#Xq7k2f6u3xeVS#>4@J9kl|Lt`(CXxOFRu`_vH?hioXY?zdE6Z8gGhA zakT5++gu1-_Jns(ATn;N@nN~imlYH+-)Q57)eG=t(psA7^P@+=SL71obSvSi)TdEo z@|o1?pY;<7Lhx_-^XvE@(Cj*F&dcAJ4)1rE+nV*aLKNQkl2q`(~LM z2+onqnVIv5420x{DHO%FUKk z+m>>mbM*1+=7$Fa|HB^yAAQ8m>OSkvvB5oW3Ie@4kaat!_^Y5<->OwWPxtOgHInsS z-12HH61j9r5Ge6wcR@-}q2`~7Uv5a?xcl7Iy6MG5!-UXA&iqEuoGITS?c2kd52<0$ zCneXb1dIoSnNq2@CBPyo@r|>36yZ(bsDt{@piwy>5;r)c?7t+uNdEt z?q8e5z1?I%2o&G4E?^!Z&4vT^oWw6%E37Y(Lxu z_OCyT2@}Q#id?we^C6yYx5gA~EdE7mxL%ZYC@wx2odjP~ISZY#&_HG%0pDqFfj`95 zUu+VE>;p%~3d{Ft75Z-R?m@l2!Yp@bI~nUQg2vSUY+&!1#Uk+Ik2|3`o&hJ&ZeQ2V z*0cM2UYYGiWT2QSdg%}C3CtREln?d_KPnkEjTh<#xBlFdZ(iR1AaE2U{c7l$K`W3K zQ2djV+$143@IrNrQ-teQ#5IhH-t7gt;C02Vh=rcw$d{r~!_ib`>z(={-)a-D))7C6 zIj6nDOLdvX&E}x5P46sbqtsE07aY_Q5e@SRCyuI-dNi+j?x!=g*tYuR4U@hl2UC86 zA<0djj~~to-VJZ!5=+f(l(T`P;e%>MpqNeYk5=2Kxkcvf2<%N^Xkbkaz8R4dA2RAJ zK&dtcytMvqYE!JMVgt73m?P*8OVqDi{BTye#d^9Md-Rh)UN$ zc;dTzmu+aBWUo3iyN=>r(<3S=VRtV=@JOZ+kM;$L^J8)PC^XW|MAXxstai zrVA<7D7OuX_R`IsT6s}@R-}_l$^dpdD~Q`Te;M7}0$oBFE&H#AO4xF)^FEPfIE}7T zpNaikTVv2mOOw8I6eKj&Exfvc6j%bw{wXaP>aKFi$o&zn7bk^VlURFBL`xkqW+oo4ab|5&xHt6$9|`UR)Z!QNH-Gi^tipZX4Dn4g%Ea1`y-xS5V|+Pz89CAqcpC_VGKZPvz|4B`De_#@=#~ z@$jR^wls-rOdlTKuLr9~zzgvu&?a|~C~CmDscsC^P%e8HXGv6$hF=|#m`go8c$yXh z+9Wx?s(J)a=FSjosAb*#U3#@h_mzRS+&+mgIy;p1*!FmRd$jo-x7TX9ds>)C$94Rg zGrT9j3GFm3qGJIV3tC_Z%>5a^OaL?j9X@+_kLYpO6OQQ!T3ns2J&fpFd5UsarME#(I0)FltPyAr z?&Dm0kz%*WdKDtrKr0yZ?3V4 zQ9S}`rMnLqZ{E(|&1<}yxcX2F?IAQrnQmGI_gT3;S-&gERZ%S%! zZ!&-j$52c3uXXT4q`(Ri?VI$bw=Y}x+`-1NcMv7mI8BB-qBHj_3ciTs%W^&gSD3+j z1E@27df}T$fwTr%^_YxtA40Ep+nje38Ja$C4^np+*IR~NeeG%-9|8Hoxj)Od=HV(` zB9ZNk)gj#*p&Ufp#LK}=ral5Jr(i9^H0Ck+(lp(<4^=1_FMo`bcyj;jS;R2em+2R4lrOE~n znVG|4-^u!m4|mgleZ5x=Tb!Ol-P%w#>kB)so!H9{`93Xy=bItO(O${^!0OBdrvWS8!=8n~Nd4bJ3Fy zU#wgguV>uM>9Svg6Z<~}u5c@Fcbn~EugZ|ohmR5qu_rzJmJFc@c`BGDJHQm?T6Htd z;jC8yp4KoJTO z%2QGLRNkGB(Mqc1nmt1qJe3`zOxGyOUQfxxYKGHQJ~Bvc$i26-(j+SvUc>#M9KK%{ zOp;h+a6G=y*#bYfa(ASCz5Jm$aph$R^m^MUw>h~~e$|Pap180y@o=Rh!0Q=vxHv&) zIF+G_Y^YE#W_OlT0w6feoPyuTr@Of^!r|BQgItTVx4%MUgJkhKzk;u$6^Z3iLzb_T zuqxYiZ1twclC}-3zQF}EU)F8=D4E-drb*dW)}=K^HFtO1pP>7fc~Ll}owjVP8^epR zWV>iZ(g$@rmfiJgUn_bo-cP|sj!-Lly;O)1^akvJBmc{t^V_74R3t|sO5noOt~;|_R2m?JX534 z`Blf1a4$UEzI;)#rkmf8%v7B?!aw$z_!8!5hhg7|h@g@)^;zN8xu>Tm(xS4%BXDob z{4d{M!FIc{VSb{QB5>>vmM>;)Wl&+tAKt>>tWs*a@r2?tCR}-_-5N zE48vdikt8|Lw4!5z_+;ljP#w#_bGesj}46#ed|6S8yjajMc%#tkInnK`vR0vHOeDO z^9UbZ#)YY;e>Rrfo#_(X@)vBav{IOeFfYr01WW@yxnbgMY;SiRH(r9Tb!(~w`@hUM+ z7;C8)7iPC+mNfs5 z{3>QOG~C|dWY}zNit2A#>1UE+T_WNN&`+bDF#R3OS6*HY{d8SEd>h^PLo57s)oYcu z9Ti9GCSnIGGGl`n?tXIiH?TRncNfj)*E`@W=u-K!C(sXxijEEzI&Ak>Nb6Yv{_Xa< z8l4_8{B+%4DQy#`+s_guPg(lpB>RTgCTfPU2Z417(y?Bd&5vZp%m%--P5c-%Kp#_~?}7I*3T!STQgQAM^)_WGleyz6@y-Cz7%A}zKw2EQT7D| zy`5SAtA$un6XC&7@f6By%$%fB&eH#?dkW)2#>>EXp&J>>O-i&>S^H3oFkyb>KOFBL z0TI`W=^gpho!;w?eb_=Nz0J`okkv(=Bs*7@iH~gy5Su3AWwvxUS>{XY z?DO8t0(GXrZPnL&L&gf-Swq){)s0(m%wdMbYz_A8UYBwXjIX!?*El9I>{1;JbmhV* z%o>Y6G(so{RD61SXLq>QqV4}`y0)3B`f9s-Q-;-g9kT0FR+=b;=d;zD)wC?~$YH2A z4BNTdb9sC7zl?-LzxfsQw@^udbfh)kl~c*7>5E>~>yrY-U73>YhN>13@t`@UF2*$H zm!BEzJ2m~Hj#yGY#Yt-4kfgFDaE+9d&NXte&sFu5{bs?@BjpnvZKQY^47DoLfCj3v zCy#mxD&_}!e!tXbO!}0Nc`_bKZ|Tk|Be0V`VpQ9U)7nU{=Z&LWxuv6&pj{giIta5^ zQTa&@W6Z#f+prYnb&B3yn&F(kN$#|l@KUmiyYqL9p55qr8Fs-OBRex!{dQcm*fKF_ z?bz`3cxiT6nMsdc8rBu1amx?Hst9IS1OLu|g;#Ail_r<7bF7{>AFqmZa@u~Z z674qUl2&psE|W#zu^pD34mV6j#;tpWX@J8@kYPub^o?QOmZ(*D`quGB+4}nNAxG=z z4ayr_C-avUR*A%&lRpWj-jNKVdL?4%RG8BkM<&lGb)7tF`GidD!+d^&JF|Cr94F4g zbfi|P6Ay#T!28+N5#b3IoK3O6{uFR_0huRG8b6vW5~IHsX_X1auN0z7Gb|+z)TeOE zI+4ilEHSpI&Jm9}k?E17k~O%7>*u?_D`HuoEQ}m7$I<=ZMb)%h09^ulQ8ryD*iZ{+ z1u3?)wbXrHf}O2IGG*{Hm{a|9xbB*6k%K1dz+@dU6zI&~^{bfltz#)!GAVyF+?H0h z#8Z(q2n&@hWFu!FVS8g(mZJGB@nD=}N+(O{+%5zcN)(fR?7&0pOcW;{R`isc$<=)c zuYifJ~ct|8y>sBF{i~84z4MFhpsLCXv$Hh z#S3Lp8k78vXs4Rul>?*i;jU@y&wG8HW7?_|)ms*qN@bSS_=i4cWi!PwzY1=^TITMW zsjg6P{Oen(P7pTC8{t$S*EW>rJtsdyw8C??$cV8NU!0CJ+Vhw12K}iw^Zf6O9)rBT zpH_><#dU3pIvmFJzJ@FKb6|%8?&g9h;lia+Zzeaju{deWk=A6DX?(R^j!tj;CY?D= z)so%a#wLU;)!~&KA>mZsI7=dSpq*v@+xN8tdUt>>dNHMt?ogT*TdB?Po&8M`J9@@05=ym z#GobkMcOmE=cBHCby<52l&aD1fBx#=;le_HW2N-ft1cv)WuC=b#~WR|38P_B{Z48_ zvEpc&CppR0xp61YoniBPr-TxP*Ex&MMhlb4AQOK53+xt>I!__xGP0d4yXh!idZZ+I z{Q!PLxJkpZCf-QZ7*oRV2u4?uhu1WYTG#rw3JaX)g5DO2OuXM)H+53^F20V-)AKF7 z)#ISR7~I}&q9}* zh+${QATKGAJ3oqeki%R-h`nAhSk5FyBV_V+FU9S$l72)>gXmZ$&C@A^$v8^Dl;=Ru ziLGs0!I_^ctx?mGMNUxuSBy&JHpOA)f~`pD@wWWFqa#<#&U&bKeN2Pyu9Uy$LcUtX z5>Cs_Ran1^jmsgGd2>tV2D7ouFGltPC^v_uR@pSfNpqy3KJE@vo=&awwNEgHl6@_h zyms+cPvAu4mmHX5LgG+WyOW>SA){r9PTXsax1wm-S#q0QgF!6CpQDq4!kfWDkZx!4 zCmGfiHBRvL%x_Ikf47cJA`XlmC&wz5XbQYPqD=%0Sz&IogdFQwvoqdV#y?Ga4UCtHfW2!Xi($itJYmiGTCz?C0(w@GEzX(SUiFg<_{pL2Ovd3z zvL(a63l+jy0qr{?=)hJL&lzWuDPZfcWF}8u_A6G$27X85UW>x(#^jG;42s82zoNqU zqnFA!(13ypF3n03`R`v7J1fbnXpu)auP@IYtW0$mFW`7B>X^vcS>~|_d(Fx7ABj*h z>)Z!;CCG8`Xc{R-r!l#|(Uuz|Yoy>zNYDGWT(F$&U($gquZve$m`LO_kvylJoZn|< zZ0dx!tF)eIhn7u-qq;JU(_eDax{%>%94apF};uIs8Rj#=w>U&D z&VID_P2JZo*Y&RH^ti5lX){$+ez)%L33(9FuPp1kKCl6mV?jg=X!E5))xybxQD);b zbEi`~5f8}LN_kBfpypZQTSG>PQut&rTnyqz3EKxm_cR&?8uzD*F=OYBP#R}f_u7gqR6vrrtDJ?ElDn} zk2~VW(D(eiAMZHbD!@l`U?XBOhkGzQ_FSi2viXl>dw0J$bPtS=P}OUgRd}#MkBB;P z5?&=-2>jsFe9q2btcSxAYZ4ck(1jS5ILz~ZF%nxtxO%>*XK95SHLRjn_`P zL{6z9AYCbn>e_}I{}_V=CO34`o@xqMDsV$PXxHjA4$=M=IW$IYvsMxJ2CU zwatku^^NiC4xAHOsxy_dlLrea6fthAd>vHQ;j;Y*$gD-yfj5CD=B39!(AjYwMgC~p zFoS-^!-uf(ha0)L8wg**wH!N~8?-cAOl;h#GLD!tG#&Y0)DL!eUKt=Kj1PtnT@jWc zcduN|8XhckFLxG^o8FHAJ3DBb3OO-C%_za?OwDYLLljT7bvjUY#QN0#bm9?^p8nv@ z@^bTEkEl@|aSAHTkd_&K@3_#-ovn>}*W2(2h+I*$s0-H_C5#d7Zh`wBm@w0{SA#a$ zs3lNtQf7yKV-V-{z+Dk8w`x@;HL%Mz&MimuNp^RIS_(^s_jh0SgogQ)J-_-vN-APf zyyzW;uyjgrY$yF9nE9U?RJG)Asbf4y_P`R6Mf`U$Q+l2r{{#fVGn-k{-FBmMX@#($8WEcCWuTEMG5eBK!vpB45fahlQ+YuboLiY?I{})b zX*(kBCC4+|%IeNF_;n;Mdbj;mU?Zwh!W3E=sS%)bl|mSKZBn_+X3~D_UkejgpWV(( zLXO5`cMu_*1|@urmxkAQU&4Z(dp!b-a>x?JJ1U?A3_uc}c;7R}ks>dxBcL%giej6u zTbpYSbTz`+Zfb6AjXBJp#VNWwsLkZX4YVrg_IJ5EXwZ&0R3?R)9qopKh~ZU6uq|i> z%m`>~#|<*JO^{g@anfP&T75>uhwx)`a+caGR87*p^%w>kobGC-=uw#yX^y6)n;%*Fh z!NvQglL1C;WyhwHE5S~!M$IZt@f0UGIgDZ(UqmP@8NPffvruEvUE*GU|2uimC2MhB z6VD=AqdZ2guoI(dvBjV(L6kp61?St=_RoyA{Q;uXNSXJk3g7utILlzosbT0_$@_7t z1^DhSa3wd`w008XICGSlb)pmZwJy9~Y{u=nB#@sg7jZoA|Mwpk)Mi8w+P4Az!)7s$-kv6En?8MY%zhG>ybx*Fz@?5hD#EpSHqZH#B$5K)>)DVgZoJL zVW%mCzgW#fQnBd0jf=XmefQn1tPi-Ai7?`R$Sg^!St~s$Yl}Hm+}M{u)Ct_iY)bi1 z*#B)9nvorGKRp-fd5dw=vGU!={9HT!+athFj%-bT?0B9P)tv&|aXz+~*5PN(O{9bSI+ISN9ofs}KBktdB91Et0J2v+ADO zm={!9`5rlN4>c2i8UvQy=NTbdawM+cHJa31+WoCSpD%$RfuG-NC$Sx`?H^pOQ(BsR zXrIotZJ!7%&c(g|-e{2{K3qF69>jU$ze2mC2kgFV%v(Q@A}szR0b)PJ#$Lwg2^pS< z`S{zpK0EI(Z9W|~>o}Ys;_5}E`YW=%DGA5pnXzL#j_DW?~Ag zP&vp685@W56nen7ROSNq(-+ANRAY-RBZ?20V{a|QzP^l^Qn#nx8^CX*h*kP=KYfCE z2;lZguPc7q^07ghoUegG-3_wM_x-hPo5UCPFPEx{vXSxzjC_F`$bt(u71v*VOQ%c2 zAr*qz?4kO-r%|6x(}5Y~QIuOENf z@I|Xsjngew`s$6RuRrn-LkPwVA*}Qewk7Is#ovUAYjL>?1<0urwmYM5y{2AhH!tsb zYq_Ws+ac!=((|wlRANd_PK`575~sdcc^sh0n9u zlYQ+~^>5M^V~+6y8{3!6KC$<|U?jpMM&nHl{_uH>GU+LuuPTH7I@)#qJ>NUF_G#Mk zr?L)$5rEBB_q@~oy;ZR*x=D)&!q6D|dg?v7aGtSeE_o|;ALZZUS+eoW{_W?eea9fQTLK6R z6%n|#X2wuTLDCo8Du8sp2?viN&&F;cTQ#|Qyat)CKhiw{e0HI1x73?65d+roiO2?_ z<(k{4iKM_eYbfubdyws+n?H-f@ZHgB*2Gofkk{bo%yzg8HzLUXe5`VmSC=M8KTdPb zx`S6`)++T4lgF*kDWTH}_vd9g;I|&ess6h_oJRm)e;oA&1~EQsa(r?xX11xIo=g$b zK-9|b2ilao<@52pY@hgcv=ZXZ0EEj=5R(5g;g{S-pEp1+phhOhJsP&nO6TkDZIFNksYn0VxiS|ciZyIyuFwZR`Q?S_A1V4%M0bdJ4Sa}e*^7_@Z ze&jIh$`2f!s@~WJ>hn)rFfE7BP`A%*+|}e#@V*}bn*ESyV?m=_c;YXgD>6k}K!>*1 zP9zIUddk2Dagg>KAszt6#@A&g5%W+l6PBneePhA!`uIdX=FaGJxHws5%9ZN)JUC)F zjdmZ#ZYAbs#Yet%@YC&5;6;tT+jCldYwTg_V7XMbK}jCLOAV>#<9)n)fzmE-HU$li zKO%@c#I*1oCj*+S>Vyr}lk=}=xHj0~IY|q#X{DXj-K|#t(zNl`d*91v+AYi-#!od=X{^eTKeti zc>blRe)$w`sXwiM+u)gsm8&2n{p9Q76h;sB!j;mc>-uvArLU}z&!>GPkslTbpV_`k zP*QAIEL097XCi@1-ESEq6}bpDZf~#KdeEQhsf-9>UH_ zAM>;&Ju5)&z&4HMwXLu7xm8jcuSDay5@~~9%pHwSiAY9XUQ@} zrt!S&x5J<_w0KMTLLhwQH$J6e3-hfcsU@o|kFl@nPa)CM>FjFr7eH+gJjxfy4G zzOI{S5GDpQdzdZ8fZX7)YQbAoxzPGzFHL&Y|BQra04&gx(gL~V@NQQwlCK5&ebKb7 zhOm?Rm+3zuEt?1=8Rufub{4CR)t(?Sp2rd%2AaNXdIb0)50ftC=eWn1Hd#pbLH4M{ zp3^R3_x`66Fv3Y$Jy-q4u+mu=KXOC9OtbHE5Enb`%ceZ!*p2>R%*N(BR$HzP9vST?b}Z(B&ti=q0jR&dJ@1Qmty}Cre?K+hR5t;(I*JR?Z35}z+l(dMaw6KAo zNbuR$|2())-L-5n`uwfZaNk%xCq86t`bhmw%NMk^cLRoBq#^OHn+ZQH<2}4(T)Sbn ziQjAC}Kgf*dO3qo`HnMr%tG+2s`t)np>dk>8AZRm$DI)v=C}&33R_7VJI&f5`+F z_djq+R_C6%0=p=^P~UpQ;3A1mo+CSt-Y~x7QF*yXQp;rYyiiA>>yF+tqWvIOH7c3^~k?Kt6PjmvuP@-n+L1Dj61`rt9fnXv04pwncz zt`INteSVaTPa2gDo6K9oq#ku*;JWzB>ejg-9Mnvm%hj&=VNgk>Z3(;XDTkIqX@O3} z*U%CK)VrPo2@gZN7C84B0N~9S2KYM*Owf&S5QMA^N=cWwwSH~Th9ZtpZSnmBq1_`O zUjGsB1qMEYb*y=TV4+}i5Nz)e5EfB~`n+NT6#D8Iw7CxIqFKF%G(-|_70FhD&= zH&1})IQ~IfdZAVUrRwMEcY;TSkPEJg<3(lgnp&4Kl9VA9eeJpz64|EUjM~@J-}MMs zYpd^o-!vjgz0@Ck`yT;VdTuvH7M00Ei3$4!#vYY2u{f8c$8?BN9Y{0P6sHyBO0obc zvGE89zR|mH=Y0gEAYh_-BVJ@|aFJ1SK zbvsVfK&%bm{ta;-%iDXDp|$M)7w1wdiVS=glLglRoB24EAIHt1;pHXDG9FbzZBY?; z-LX~)+nMxy%kg}&_Usv+W+}T3Qi|ab5F+k?l}1!1aM!|uS-!X4prjm#%Q06=hD6|P z0wa;T{?Kc(q0I+zr{Y#eOJM2z_*@LCvwM`oX=fe*w5T%Cmr-4gZ0>=eA2A-kW`kG; zp8mS-fIldlhSQXS&dgDPomWC$ECzvK&^5`1_#5y;FjZn8O>YK`@C`m>K_yYThbiqu zo0ECa_dO7<3E8?H2W_B`T1lCncfffap-4#>D2yfvRop-AHsyx#5n%DVHmLSG)xtvt z*R|A=B&tZ^FB!y^TWQwUX2OQHMbZbD{R31z*c$!RCUWekr%7E?Dj4DrZyAmI;#l$giAoAhCf}v2eB7 z!Y1Y3yNI#_7bcG9h;JA3^Xu{;*f5JAJwv?|&fnMb*JnRtn(;S(V^J|I9fuA`mtgi~ zSB}2Itw>9ic!qQA-zcwR)vlqFB4*c>-Cz{T$;1&zcKGAdt@tD027F`O@t0c#Qstr> zB<(bNw=^rdp*(dRVOwd9wcs&)aa`4ps%X-rEY{zgZ#uDMjz!*iN-l^JhrQm8zY$k$ zRFkV^3$wYEf!y_fBAE4`{2<_8n6dVZe=;7)SNaH8>RfglKN65>Nl&4&xEI&=qgxLrx=GP3C=K(G4Tj8GetYvflQE5#vvViq&T;%IMk3qfVO*auEso5=; zf~ip?EHZV9WWQ%($E?3$PR7K_l`2)@^AK# z1HwK~6C-2Hni*Fd(xx595|B!EBK0?3=SWL8ow7hEO@7zT&f9xMHuN*wGxFWb8ytOI zbZO~Zg^j%cURUG}YLCjl`=8``8qF>3DEs1;Oi|9!g9!f}>C z73cU+9VYQPyfxrY;axTL^&=o}t7TUyN9h}$&|3s$Zi)8I;HTJ+i_B&*#%!Ng91jkN zbi?qjl)%baJ)Bd^(<4&A#qCr%bR{b#WsM+(n9LK`>y#Lx3k?R9C6xSJ{9I2uPXmAiOTcO%0PZzI zKSM2kPk&E;8uZ(bwZ4R~_!V4=@Gq5AGQr9~&_Dnx)i2tR4(y}rX~~a-MUr)dH|Cej z+dNS|g&&bWN;dZLpciuQ+B*)!=yX~O5A^Qhq6unCke0HbX;1xp6C%*`ysYPCpiIPx z)!xwA2E2J)b5&u27~JAvh=a6_BxLv0D}bck<;MW+e+DYu*BR09l+lAkibzv!zKFGA z(>`4?4$|2QQq#RxB<>1Po_ha!A}EiG^F2W0b#B|#@{WYE#Hu7n9h8{1HOJqG(Xyx9RyQNrc*9i3^SK>#5?v%6d8|XKqJGGW z!#Sdk_1x{drTX*3g$(|0p4KaWH!`p)IZLc1#?4IIq5EVC$5KVF=%g06O9RbLBJjrYymg}R_N6Uhag%NwDMsJArh0=ook^~%sc9eR^~#4M0m*o z={x<$5)$9_zGbolD?V2;B2H-ytGMz_z{wYJ#syOE6pL9Y1{2fSY>VZ?I4(YEz0=vC z!X2+er=$PMTulAK@BkSrdKdA2Ldqkci+yiO%p+hi5%-}oO%Zo^J_uGb9Qh3OJs5O> z4C7VCyN-j4VKUyIp0`E8DHDt_5-A=fbxevn38i2aL%(XMlfd0Vu_F82o0$xT_F-ZZ z)(X&fDV=lsZ9OwyjYH!=d{v7>X5NLF7@xM#g5sQ?zUEt9@p_QXBws@QTx`vTghbA-d=Z`M=X}@0grIDx-#J$7#vlc!Zf* zDOP7-6*&o~gxG*peq8=H7oNZat^vQjy)m|fTes(W2M2M9w-kl}Ch~PhE^-E896!r8 z5?_N$>O9<}4Y#+>jO#!Lv{Zt>^GZFb@wX!)?TX7KOmzyTWbe|XnU#W$=?|#IKTyas z2o`~WS7iFBCPa6{-M3XYR}%VZ6QPg@ERuw&o?nHKH)-!(4aQ$5)|`F9(G5`+ghWah zIx*fGTGE>5OCRaRiLZHr4qh|K1Ubj5U+4e>u#)@BVjxF*8x3r9TxUL+czZf?%p+fj z3Zx$(C&YzY*`Lf>muC#xKFUa&+YRrWVy^Fmo3*Iq74V&pL|qZ&fdA+U&c>7ObRHM6|$nKmsEs#><>x9kpE6z7bsu8)p>n=HA{+!hKp#yB00>kejZexMH z)4A>F??Idb&yS^ybq|xKZ>8KedsWtVCa^h~$`?x3rnp?$BKvizY01Z9d}jKub6eyS ziG0eM(|~MeVh1A_vmr7&2?rw?mbnT#?**k)=aV_Kz#;|P=P40HDwS^;djv2?*p=I* zoXMWPC>(mGEc>JUycq-ix|w4-Hwn~B%6_m9D=#1P8b-UKi%++U(h7VsigU?Db*}^+ z{iCprp>y{-!TT*-%@=9xu2V zq99m2)_JMw0=EX5-{ObZgt&^>OOpl*pTB=q_N^-kl1){pMB%saI{52nSRawZqUb{U}*#%ppgIjPXxCD0zKDfI>u;3b80}QUgCAhm=g1ftG zfZ!Sk4gejvY-&D+QIYYtyYQ0DH zEnh8GOlIltG7Os|L!)3;l`0Uvl2VBbqY_|gnT#_=$&sQtQ}V@@tD0dFOTMv@VIw63 z$5nSuRTSjZ;6kli>2~|A#%r~f%}KGR?_{;Fy&CjW`^#JR@8ivA%@!LHQ{~yBLJun` z6OktU0x0~l{Z}qL!X`x$9K;Zc8TB_8b!iIkgM61};zafg^aoVxH>~MP3VUTcRY5#G zhN`!rNS;=Of#(Is(cc_MQmi~z_TKppC$5eRo~cnWvJ8?Eyv~EfY`78wG8fsV4#{HG+s_$)CLLW?Z zo;ycASkCtvmyU3jFegR$i_xvzSH$5?Tox7KWn0yYCkWPkY2`etzY|wc2DUczMDJff zM$CE`2o?7i!)x$lrDtWWAsNx-ZKxQ#7*Aa(X%%rtzl>>cl85;}4KZgZJ+Sp!{HQ3I zN^889Ft)m3s5ncn!7X+DQzl9;OhjmtXnp6{P!urfV4`4QkgBJXz{xnT;K>-3bH+zE zb6Q_GYF8R|C)%#?y@n*R!$yo@w<Y9tWnHBQTBXAM5SC`+)y9`#-fjnTjgWx1t1Z z`?$+urF}lB8w~}iN_a`79NAIhYWay7mBNlocXls4uu8uKnq|3$j0ADeOeOJTv@S=| z$f`Wfp;lin_Ug!wvbn_uvtS1lcZ@8A8WSpG3qJV))7ptI-NoNG5y7p4MKVKGpwbFO zy&kk(rgNqSQIyn4eof2UX2$(V`}K1cLE)Y1s`{7!H)-7PMLzIL2OjQ?JBN;)8ixmS zv0MyTOj{?i$VDbvGg-WzZydz{OLB6O=AuS*8U0w!H&KolWuewDXi2eMB0LYP_7_{0 zhA)22px}k7=l*$<_F%XJXdI!m_^{kPlQx1`~!@9cu2`%y^#DC1o~tcny(rEBp9{Y#Br z;qS{VlzcS<~f>#!l6MMhK3ZT{rS9< zDgtWK`CWY?1Lb$Ku7)7O64gRgB^0U+n+h@^&IV~ zbuNI8M@He}tv8kKG)$;kf~RXfcs!_&)w|tfzb3g%fXqRsrG;_@pXH~;bqb^zkHlpc zcVU;C^{vXjf_$?&?mFDS%0Ay`X0mpt3#q{3IkrRGk#dIff=O|XPqK_zxXX!QPhEbj zWL^yeN0~<0Ip?qz*yPm)EV}6zUW!^sx9{3ap;B+34w%b^#&S|!AguUiPkzn4atV?I z#xo|xSLa}>f>YM@M5;b{r$i`=k`d_erWPEEu&TzGSfUc(e)r&8xcH6Cv!KIl`uuB7 z)><%Ux-%hx@AxW{4m6=GkFf}G8IYQ0aYg`D48AG4URPG4|q%15In z5`6^3yEW=a=8O(_rQa_LGSg#JF=V`xn_e}Or|l_RO;=QpGgdB6Wz2azFDWBEs{ckB zn0#_RJwT2e??WvA9s5tWMy}?$f$UeE?!Kvl%Tej1jU+o`YKR%8IID^!pAVLanSxNvIJ>fOb-=BN8e|TW&j;sw8E2j>yGe%$ z-O9S%C*j#5SqU*>%#?N9pHtF=d$AEK=*Nl?(oDh^)!53{v2^4z3qDSy;6}lNT`LHQ ztRn=oyLHFrngE>@aSi4_T;FL=3xf}5gmsFf27wHs*<}fxy+%DOr>&%f*Pcqk(#YAO zH>h`n;_4zXsnhp0O8X|n$En9>c=$<=Nro~525SpPjx4c`e~3P3q0pVbop1Yr)4KJY z(vbXHM>3e-m9vIGlJ&&S%T2C}k6-&6Heof!TSBr~6Foz!bKmRS9PatuJ3$)uY+ zr!F6d$k(rCEXK;R&_YwCRA*h$a9CQJV)k;=#<4!3LBF3KSjXBFw)2I)I;ntK%(!i8 zWAISFW$jPj!<0R%>{ccjOJ_b@XnYZXaf9^Qv199JX|*7-)k)<$%O6-pCi<0uU!6fy z0SiAJ-`W_vorM^f8D-B`VujopZp+m5kz;lnPt%3qG8zb-VSpd|OrVcN=3azQ?NJ?t z{o=$fNg;jJ-F}m5w>zM)E5b7AmE{KS5_F{tn&8aqyaY?+y-W6@d#!!#Y}G4H+!n~O zXH0X9B}vNb6$Z2D>OWI;*Rv|u@((hr$scKeiM=m=<|9bsJ-2w{e@|AtWmEj&tQbn@ z!1%ogxc#PbqLvJNd?NybtTEH4euM=#v^A_h%*TuG=C?{2wkuu4$wz;&#OUr(vo~Brodbx8 z;NuMj^YL*gQw(nN3^C$Jr`jhgX|yG%5CkkLeKiD)-BVq=4s8Lq(e1%L83m2TTR-;e zEnx8XuOf%XGKn{5)VH*dP3Y8{@U|U9nn@H-$xzCd|L@ZcQgnKJyD01NR}!hEY%k{e z+A&)AlsZ&)re8FpJJ8(HkUy-`0lD5cG#~ctk^StemnT;X@dQ)O$-i^SAiY)lCDmf8 z0y#IAyM|XMmkc!ze}Lf!=@ih^0aTnc$*T#mgjhSr1Mnis8~FE@x3v^@yTEZQOGxOF z@FIMDsqt^V)Wr#Lbx;omi#$K7Y(NSM1nB(TY*2szi2F8zF*Au5DilW;S_m^2A_EH6hk6Yt>FG#Lnu|BBS0tC}?_o-j5__$zb zQ}9lY&c2?1vE%VaMp*F?)wTI9wBLgPK`Tri>6>CP^*0*2U5bZEE2d-x?os*68i^;B zgfctE>&xbU0OzQ7v&|%iwh(vf0u3tNl}rq>H#C?LW*5f@Q7HO9?H{a3vjBGo2Ht|# z-cqjEpD1=#cg*~f_UMZkH#wm^tk_S&#`+>&Tl(BViDQB*N%bbReFrbt&w`(?e&3ui zLI{5qa9DsM#@>>y`nHwaLC$7_<9A5Esw|&yt2JMu9v)4~WVKOEM83FHYA{RMKgaSb z)x&KBBszmX<=uM^7!xv&h~mQv5)Wt_VGw26v%6TEds`<{r=~`%MD@F`UqDw8AOzT7 ziJmaxg|Q0 zZ7);Z!FP^DMMWOQ5;>*Se1we8gP9q+;ZsHd8&eyQo@c=szGFJ*J94UZOwb0$*Sg-F zZB4WcR@!m#wTbj-Hm}=bDlkLwn45}X+9oM8X=RZH^u&?#85#z~BKg_|@mKr@K!O!B zUJb(xBJq`G8`PP$8qlJD-5rJFfysw`=Bj1OIg_A14SC1#JxFw{7)3b;Ggs>5HtiSqi}k@qYR zb{M?3Vf(eH{>=J=>JO}*<$q_r0{sIVT&Ztx?-V6wk+@7pg862c@5@qbSYNK<2NFAK zst~mXq5OohLbvgM4f*Cb_-n$L@=F+9-bo0-cKM%8)_fMb5h6$0))Eu^-?E&tZKv{S7cES9YI4+QP7=gxYU;KEHc(=4f|yc{e|sakyl#Kzcl+ZkKPY8 z?KV!lo;m0ar#KJW14p@$$wU`X3TZ7talTtU$D}UOpkA6$vw=u)9{Hop7UMR2&-%Dp zCTOTTq>@AMOY}haIAYoWZiKA z9DCVs4r1_!_WY1iBs@&eSd?uArrG@8R60d!&}DD^Hk9cr=(4zPu)J)%HFD zK=*B4e^Wonr_1T$sQ%4({o>>r{76YdV|q{h6eMhE^!V#hq4Y&&oFOfMwc;9fGRXe{ z);T5&4=a-=453<{9Ern3F^PyC8m$46(uv%w@MZ>Z$)cuxutZfNhoz?qxJKLGi;*@&k-v4PQZ>oVH>!1evrSaX55qw1M=93c4&VH zVeyWfKw(r28SM19GFMYX&S>U`5{I6Y~K|4}C`;kIbV6TH`qV_t7n*LRU@pWY| z6T(dVBsPwM_Z{95ue+>vB962{)9>%>V_jdj+^TVSTY6( zv{2F%LEmrgHik&tZ!YU2(i)R`tm=#j%m~j^T0Hv6f&Rh?(Hpf{#K{Zi6w;&IW^rqM zWGLB^x@7g~e=^Jq3`RSl`V^frpT%8vSkNe?r-gr&$LLi-l~YzdG)GwMicdw1Wi6;j zFJ$j<&4%;^lZgsOZDj|~NFSF5v#%FM++6vl?d_&dD{fwq$1tT%+m$l}U%T-4~ z52jYnTgiS8s|-E%bK@ zqg~iN{=6|HlZtJB*{s7zy&dafAO^ygtRABb+XqO?X^W6=|Fbn$bKY$Pe^nzYu=Ab7N zQiEz#7^>5Ey*YZzO=^VQ!AhB05@Yya8%M0Ljr+WH@DH%`58&i-uMX~d=sWxiOAi_1 zXox(S*IUL2x$A<2&Aio%3#cM8#TXcF8Zug~A9v5A4dH_-w~_KiH6#A+fEHO6`D{)r zmw0&TGoD6=W*+2W{CWU@if^?)E8YZj;Mr|jnfwpHq_fNu@DE@Pn`@*7qt)6Be5R(T zjWOPH6@4M&p8B(lyZV!oh($lPm^NnW_uJp#Cou3m{s;W0e}HPAmng{gi`li$c^|BR zWPmm?!gF2htM;32%-De-eFJg(n6M(sZlKvJh!_IQ#$&T_Wo%Cu{0F#BUIa}bPhH;~ z!ZJ0wCxrLl^hWCkA=7^Jo}IquY$`#gYvqD9h+?8zsadcF9r_&y zj#|yb6!c?vKI1U(&?cP7QeQjqGSb_({Zl9?D@Pp6xbGA74?qX1`v>?K6k+T73F|QG z-Sa;{WPr><`>OKDK=uht3abH^sYRH@&lLoxQFI^$ug80p%W-uP2OC{DOvfqKCjRCs zu2$-B7WQpoDI&|zY~DVuH@4??6&oRgH+|fHfTX^*zLRc~Ip~MdyN#1LzFFO{#E*4h zP<@&ObxUzCu77~J=g!>q+u!90XdRv+FZz>7!YRit_@u)liNiknspn3(h{~ZV)%I&A zEVP-}ND0RcY`jmz_YJZPo~ttp+#z#a0LHc z9t_s=&`ApKT+hn0DEbJAsBU^Rxkd?Fi&H*H{HgeXflg+5E^kQ%QVsD$7d~Wm` zc(O0db6GkrBl7A@J$Nc)uMG+wkk~fZSZfGM(xxMQD}i%whPnR$z!g3qu6~B7FZ-%> z{-RgVCTW5~;Sys|ZupZV3g3FnOA)~wC4Jwv$znMDWCF4wl_o(P-p0*Kx%X8a2L648 zyLcwu3y{bceJ*Z~hq@pK>QxYnCV@>^_HGQD(2YCLcqS$=Px}UVGtstCvYsY0LRGg1 zXm((FF3i{qky233Y^X-mlo=KS^?$-pR+1t!5ezYRNB`4z-asA1B&Z=H#UFC8gBoa7 z-Dk~gJ<9nHz>=FTj53lVB2R5+OcbCG;78M6+0#D1Q3!KbeDgt7Zvb<-x!3f8R|Ly| zyUgmaqL_p{vtP7P5Gp8jb?KU*p3#YFj)2obi`;}&GmH_o{|8Y1&1KjCWs!u2K3!8? z7rbbe?a!z`!#WsuVZy{oj)%w4w1z=DL)c-Hoe)=55F=y2*UXGc@q|}l9v}iX%>=BAFTE@Wq`2L5Hlq_E2K!iAw1decO1NZDJpx>*t(prvyFqd}?UxTJC z{3L_IziIo%V(pG;7fwecs?IVl&fUl)nnrz@9u~+@xx9ZW9+Viqe#Yp6zaodvnu?4M zm5n6^rK4rJvN(uM{R2=KHozJnwV_QmobN{qu0b0xj~Mt7$ZR83sk9$E=*|X+>vCZI zSEVzv08K(4Fn5cFHX*0IH3wNRd^UM5uacVu*S+EEqu_ z!xERxAyg{uBZys(aC|by>8@@jz479HvY_u)MaDIBUlUzjohg7>@8}#PmWWyXMJPuI z`{N*N>`R;w;p)b0P5^ec3^{}&q$i)_oeRGw6j|KO0{_y?=t{agJAwUA_w={ll~1xb z->dIbl;Q1Jq&iBUs}HJcIG=M{U?N{LPOv)y3QM3C(?>Rd_rOyR*ybl;v3V2GjaX=c zbm;^4V99S)A$jcOR@-MC6$GZAPPQpgYM5UuBV+kK(M(wn&hy}G{sa6LsrfG4VlzWg zV+4ZWLu0ibq$8)@VErj?SfD*MnVlEEmW%8?>4OG`L!!v9hFuz$h1v{LmB5G~7V6z7 zrQQX0dboZcT~{FAifu}B^m8}1k$(-**W^k6;#t_W@DCsfGuM9r=9UX65zM^*0puZ? zKh>Y9?lCLym6@e;`ewbuX2pDqi)J2lFG_YY4kYIGgl(()T zyVpgoaN9Yi>5E`*G;3f7{xma>P*YKL*Dz1cu18f^N#Ko%rN9EgJ_yU((K__z-l(8( z|9x%Gs9hC!S^nx~Sd_q2LSjS1zLs62K&pOb3m&QL@s#qdMo`Q#iyJH?ig})7&ud}$ zaPt|4YO3|@d^-?{v>c+Smh zn&wCqd-<$CoJ`Gx)cBDq23MCzp*XCeP686*8E&zGs6apE)4sAzh(0|ja<@Lv0qFHh;V*mv)|4x*dJBw zUx-iS&y$|jQBTIIuIOdiE%)#vbCa+lOVD-m(}v2wD^I=O z=H7DHsa|1G2&{d3Fs)td9i}SIN8{hPh8b5I8%-7y4=zX;xhg^#4|vkCT(Rwnm;_2_ zK@Rx+y;lUG_EkTDu+Rg{4m_}l1UC(<6w*JZwaCo?FAOvd*fv_^;&Yq9@nHcd`%TA7 zm7qDo74GyI?=NHu8<0)^ZO;I0Y-HvihBObAi=lP_@N?}8OwWReGj1WKESJwn%@vc41ZaOVe0M%zf_5%3S$$@ znol%3Wye6~#cHcy?pXyi%qLZqt=#<$bnKk1*`i2GQw*(>#CD2ga>3%Ack)? zB071ABg37*J`b55c5ke0X%61qm3Q&%D4{d-86hg^a~KhqW&wDh{iOX(>llMI6}Q4v zasNfMT%n{?g;})%L$w|>ro*f7S8@QqINiOSc1mS0!5($Z`os1WU1WQ>{V_3@q*QRP z;d^W%oNsXFgJ@Wu-5&}b9CZz)bJkVW7)pN49B9(Uvm8A|8j)2p-C1vK`4(=Od%hMQ zAG9t0Y#I!?4EFMt88i!~x$2)IR9&G~|Iie|OQ9bzv0#OTZ782|^=nxr-n~?)_bpZL z#*Q6o%HiOvkFu^rkn_KS+vDvf~t6|Lk&58=+nn|HUT26}(Z+(Vo? zh_>V|f$a1LG|{qR@EuBRIlBY%ks&QGwjuJb=n^$Iw>iTt67AQq%+g}Br|+Z9pmcdl z@z^Nt9p(3wEhXFbADDMJvl*yzG~}UrSSlt08oG|?-SG*!{{UEAWdmIGi#m^Ba3S202K*>~^@E&Va|d>`Kr8+@GH`o4&-1zR)Jdl* zNZST`zAmJf%G>rLwr006LCev~_1LcG1Vuo`achSQn|x!Ev}Pt<<;li*+PFMQyA97O z+DNTp5Z6SeS1B#*D83+ax)x{5;ktE^3xwovf#z9WjA?PSPaoy8(By$ZU{LCz@?6f$ zPpbw~Q~19Z0dlqFs;ID4!zS#^>;H9E}n-UaU-WHBi_RtcRcHAK^g+vz_K+%mQkEQnE#lMPN^`fnSWbcO#Pwl#*ln zN&}a^0UC(9r}ll95rA*HK0D&+6>cke1gm_r^4^B20%k9&y-EU3Tk`OK)$MzDnEd^E zw!}W~k9x8*a#&`%U|M5;hZ?XTtrshIH4$ZDFNP-k&!l4JY_WjFpEZ~TT0x%Gt=lR+@Ac{01G~bd|i3e$Y#lD=_Qy&O z1GN&8e#)5bSI9@OPQbbT2<6pxE+nSRCzDF#qevC~6iG>EG=YuQa5zqMS5wa!mYNe% za?bP#y@H_h$6t-O8va|_Hd7aZeGtD8+xrP)lX*7uF?P?Ne?J$C@; z+{?}a9(W74;8kdA&^)JCu9z zQflBiE0;klH=nKiU43?c%R-akOy>w9SGn!f47Wzg`Ji-U6vUOt$X1-wyQ+ZLzF%yy zmu6_&NKG?&5bs0x?bx%PuQv;ypkX&Gxbj`9s%F`{DY7xk?&w8KoFN8BX}aGgpMRJ% zt4oZllgqxY5l63;K2FT|jjh9-1cwWZ)kSkXGlfOv^T+ADGuk-b+A9Ro8`=;jvbcq%f*mKBM+>(8M6)RZAGq!AjR1XNo!J_KJrDC7|NX$sg|YHM8^C0 zs5lA1M|~W_rlfjV9Lsy(U&F*94Vlc;$Atb&=`| ziem}q3obVsT%h-+>ph_H5cu8h*Z1oRazk25C~)2!kaxsN6iTlAU;&2+K`~+lxP$c1 zdfmkN;q}rDdcrHjs2LvzYj|ngqR?-c&mjh*8Hx%K@dopY)_cIZ-CS5E=aWO1NSJow zZ)YRBRnM=^i4p9S1DTvnEu9>WG4TrAUVNud#yU@9Icn8o7fc?rJ!Ub5tKbCr>RAqW zYR0iee{PWxlMaqQbO9PYn4Q?Jt)>rYaeoeN5Tuw5yO6qp%+qb!A zt86E3n5SNMghlG~5qNKSK@Jf`R8)(-$Tvns$U+5B4Iv?wH&(I_g(9fXD+HRLC8731 z&|F+ZAZWsnSKi4Jw_*E3CoWcMO10G_N&x{dSWo)!o1InI_&KCG+St+ z+nqMI0UGF4yMM^)8VQ_W4?wsqM58X?gbVMj6=gryIZ%XSJ~C#JMnM&~7>=+xDMSPM z2yx7d3kTH$iS6As@d7NXg$Wc+(}zge=6JDpT?l!)1_-jFcO7RvWEU_v3uhezR)7!H zXiCKq?h>3%|hmdBd`7Y-6@NlvNfL7UVK+mQ=b+H>1 ze@{D+fH^kdq5sMMM1;WbDQmo?EU9rI{q;yXvS9b-Ck-n~nYVc?p4ue%e&3X+E2(5r zW4R!nM!5N?JAdh--$C(V)dobqa8efXG7TwYVOjxFEO(j^N@82iaSfIvRQO_Jcg8AH zTyDH!|ASE5d7%P+1s{kv^~Ez2u3%nuA11#Bn$yxcfuilnW0S&2)N3CML1dWgTL>yv zeK(V}-|lcHqAHM9kk8fze^V7ay7gT3&6^jN``DepZS|c4m)YLl`O51G*5XAB0d!;W zj0eq0ts~0c?|%VIyhY?JqNHxSqQvo`CnGjit4k*}2W8WWVmVw0^3V_c17I&3&8K2@ zfIe1}e`r;iA1wO_Il|HEn0(P0STmM_C43p2Xek&@fmGMg;UkCn7*OnyoFe$x65e3y zrf44}#JrUiNBLn2YI~K?Yp~Zr|5ttPP5vbUhOHf0|LltZP5bs8it0y56Jt)g;-gNyn&}@S z(z8PQ4#ei%Xc%w#s%1q%El_#weeG&P@m`k+Sk~*K?tIogMz9a--M#HQ5#{__30SUl zgzaWQIn?ao`!kU607}r>F21%{JsxHTezSc78I*)kj~8veZJ{DQi1;94Y`w>%(Q!WM z?9g)8k4dN6hnU^wGrxzlPFheHPZeCBdzR;NIlOOpNqpc0!%($#+kykLJ4()HY$B9a z7N7UxD7BZcDh;S=!<^L9EH9MR;L`#3b8I0Otr`q1s?~}Npd+XFg_3mMwmtZZ%St;A z>H@2H%DwLE?S(Z70`Ci^pq((-;{fXQ5gGMho?u)O(g!J+hyJ}FWDtqQG8*SbtAO`< z@DY%`;I%EBZOFK3;FX(1eCD43R$042ZS)yML8GVyVYe`JSSaPw4TQ+-=(ZlP4Z?sT z!20Fk_K))7*%T$jtUHETJEAg~>e&W=_Gqy5qjse%KdK$+JvY*z$RxPuSJ$ z7OMO1-QyeE#G(^S5a`2CXet;qgszCdQ*a0|{X$Zk#-t2KvZYuCt_qszFSvW4+J3W` zU{+B0>n(~(@wc%t3d*tW^e9giCz?te5y3S2wTiB~5JWS>zl*a35ME&Mt2aP1a_H_C zntoVK$DvpI3$w#fJJsk)KW%=!TO81Z60J z2j<&-XjWo0oIXd*-1I?xyOn^n1Fnm(8yNUuA@8cc(a_v|T|;0p9Md=?qZT+${k^ki z+MLT$te(J5iUV0qe9IqnLNhzJCprho=i-|fGGjS_beH4)zFF!$cZW%!Y0&OX*6jUe zhV&gg6l}jagxf^m2`FLtE)uBG<qgWRJadF31u?x zrB**5*O+2E^%qN)8PB1d$)!Z>#)>YboDg}|e`8@hmc_+zLwS9y52*B^iH-gSnq`Ak zBeA@h)!is%*2+<{*hOE94vKU~Jwq!e3PY0D&@zH*JQC#JywMTP9#9XxbMY~{HBOR? zj({W@g76)0rQ_f)Mt`{E=v=RO61%wFuW3mJa;#Fo%!WT2~t+i<4Cno|JiZ;jfo&H zE%c^c&ds|XFj4BhfYCHV#Qpefhtdc>m8)C}X)eNj6V(@((%wZte<*u3cKr3F*Q}tX zer=Cnl!ubVHoX3%CZB-hsKI2@&uGRZ8_^rB;s-CS~R9Chkth%M|N!zmC(`BN!#4g@-FYXIP^WUr2j4wCDL^P zHz$LY1W|Ws6Zg=Kfx)T=%x3V6i%{8*o2_ZP-*FXpzJ)etS|{gQeB(g(9^V(st(MOu z=bZ0Ihm~ZQ<3@*{#IX|y(rcg8Ey0t1l43w_vD!0l#4@s{kP%xyZ*1E9>|h-Vd&aJ` zjU*23TXU=(Jg82=n}~C`BXnY!QFq->D=0$=Yt=~_A9`ga7_wqKu-vXfk-Oe2wyS3& z=`YSXx*in=ugLbG-uVHewA`)8BbTY?GgVnDMXv@0PIbs`vlTk?`!>rs(B-Yu4=IDjE{Ko-Mj)t$?L-bu# z24)=vzn+(uamDJCXPjLJR9NG$Y>6nP9ddK(jt_nW(+>gYsj>8h{T_o8BsIa8Mca9} zkW&BII_$lSw>f7!ObyN~NhGeOj35E3BUe{Yd)Zt1#H*Xz5{R}deqni=;bqZu1!GQ` zp-3+y-l=CXrN01C>?wKgLAy|zDO6i-nXHNmE>I^S<&#?3&7E3uyDF&S)?!cU@~*WW z%io0YRGIVbhkr=8WJ%^j;i%!_YrmO0^3^zELX#6nK53RSyKv8AUva%iB;uv!IBbEk zqKTR0eisf2Fo^pn;n`IJz%>-kLT~pYaNJ;bDpx**U@E z%BqC(CdGbwkl1-(ul?SB=FvXQT(xiE?H}O3k^|iTUXMipz`-NIp3H^45R3)~z@_2F zfz=#PyIm)T6g4dj?A`qTN)G+ny%O~6J}E9J9)D1Sh|qc^5{UHD@`FDZY7hG0Y+LAy9xHm}5K$3p1J@u! zk7IEhi2{dWugYh$_QwSapqY+=HxRd^m9MZIVEXttcJ!S*Cem0%QRi#RbH{Vop;=yz z9Ym0FCD?V>r z+hVQt)BE0`{=CoHjs9&2hO{}Jd7tl3XFA9l0wXer$5qM&4XA6sM-P>aW!uy5Wz>Cv zOaT?uCSZ-^8#^>h*FU3NAH%=cVBA$pfvq*4WqJgJbEq zlhP8-h^}LXxSB-#P`ptLu3las0AJ{ri?M*p?Ocr~(k?YdE>od6cX6=Q0fFI(B6252Gi*j;1bWK*qcoc#Fd`9tE8_W82P;Nc8 z3vI@rpv&)85qMtLg4n(WUp_>59L$?x$KPZ8y>T<3^1<=J&m;~7w@}q(`qdhl-Twm+ zwR<$40O{UD%>iT+#o#bl)}R>FvE;nHuksANZM{hpY{s5@0mWVQRXpeZG8nXKzWo)) zOz3a(Mebx&*bMa{GHLDF$Xx=9lzoaSVlGEu<~D%h`XN*4%$_TSti3w$K2KstU_61w zChy5>;LA@+>L|67G4jI@ zanS?o$K$+tsos!+aQR*E{qdAXrnKn5xmc2>-T1ZP&@~p@jT(h9^oA|K<0(?^8zw0x zJMC{1lwScvFIDG1zmRlej!b75w2X}W%pY7Z`Qn&@CBm7E6JS+lTVru})*;*hHt)3E zb;<4+XiAM^aLzE?bBSS;*}l-NyDywMhwF73Y-5T8J=?w~5cudav`GH@qqv{1{SOaC zBc~dllg^x8>e(rE4J&Jc@MP0o`c-2y*{pSy=Vq%#cZcVAS5Ex2E?Qgb(ZLQUCw`(K z<9ygtIB^+hyV9MX$~jQHd##7Ka^sEM8dFbD8*=c&-NL=;+d`b|~2m+-6&jQ)x3a0eW={5mvdX?y? zkA6pdRK!6}3Kj_J(!7}-ZEL*@6OD%^w0`y?KTQ-o!#_L!VzQwNm~vGJoG7NtQTD}% zH5>VMJovJtiie*={NW>wFOF;8Cwueu*5%_-p>>bidIwkT&psksd#QtPdy~kNNbg7{ zr_3c{4c6G>_7WPnb8UWJP37l?p$p@okWjm{p!#)iaOsO2|4~EdFFncI&h`4%OT5*E zX52v+L*d*yD$?HNn{EJ)?p#d|VH^8D2o7qwjNst96izSo)VDzHYeHO11> z6u?kF-q_S_%L|algQ>Lqo{j73t?Sr%CQTFKld{nkl_SFIW#~x3x!TKG<-yxhxtqSB zP`*~|ZrEI%7NvY>EVnrDFdp_j6Gw^S7K>hKA5=JEKE9x9Kk%Rg9CcFQop=AwQG{J) zK%D781;1PQSUyvNvupzyMHF9F11$u4GypMDSws^`7To$_*(5!=nqJFq19qAR%l;dU zFBTSID+F5VF?XgQH)?`(ar6X2ec2JjcV(Nqeg_f^?M@4ldy=u_j3me8kksD{88#2t z?>UElv`5qP+UV&4su+U3;RR!|Q^u$f((fN+4Gi?{5K#|pR3kI)ZPK)h0Q6i3;~vt@ zaMLgM^k34WVTFZz=I!^CeD%yUelxRw>o-DvYFX8`LKyR83Cu6EZu&v=|YGF|-56#XweI)dtul4@>MiG$N(!b9h>y?i(7eQQQ)iIMLCDVBG|+eU-sQF1=Zux;%KebG&e> z-?XA)h`6pv(xQY>1ZWc_@osTmI!V{CH~>*|lqC4q(hl`iB4-TUT*| zmuUGQs(Zmf5~}?ev^vFyN>Fu5m-A5~L07i^Vo2#7V&Vk4)1DX2Ar*-L& zMU_MyrCsmIf;|o1a0;30;Zj$KLA~0Jk@{q(t44nr$`t1eu_PS!7$J$Up3W1?UoUza zR(ak~g+~&>Q*=%^^h4Y8dboNVU(sN+s}IAIO)9Fob{!Vf9Iy7+m(2mc7kcJy`IJCu zh6hqq`p+$_ud8-G%LOay?Z%kFP1FjAT{G(R$*Ns-3w_V4A6=<6t9FC#{c4f=4~{bw zg6T9tad6satA$sF9Ps4b*JY$hw=AjMMv+rdqIHojz#}pw1}T?&g+fUngz}M`~v(N8!nJ_ z{SkUAIj|Mcgv9PZ<9;9*Va9nF-vQHX_z3wP599j}pj>Y*Fpz=jylMOG+>{CocSJ%< zZF?@O@y#+i^$CLrK4&@@ErBjno#q7wp-|mI!;;pk1g`{vROi*5pW^D_l=a^kW1P2R3Ft6H zyou%dynBu+jADI z>Y2-8ZrPzXT@}gW5?U@ zKI?%}d9Er9*oQBq(3T-TyRO~-wr?C~{R(=CoUV>R#LR!KPa=GHtWO2^cn{?M=_E{S zZkH5f8OEA`5!X1XL4%%pMCeiSHd{JH^dWpKknY)Xz-wJOhexZ-k(3NC?vkN;oC#uK zV~YicG??z{6{9hxA)0|G=LMIs%tQwwa}m#UswC*CgURl+dGZxv!3CI!b=u^p1wV@^33diY(jQe4cwVn@wj@XfA3C!} zV~rHkLb((J>LYL(~7Fx!sf$)T} z+)L)0mnmaPNl3&<_E%E`1h~OZw3bh___?u9ZGd)9pxx2s9uN>3r!M3)5~iHMC9 zmKy>+8Q&&TNq69$Ks*_4gwp^~>KcTrCwe2uPX?$WxIU&lIt~Dl9_pz1sv{*gGEL>m z!NY)q$njugy6Q@wD6IwQ>7scTBod#IdeLygCG1hnDRfY;o|Qgc0(gXybf;ieW0u9@ zP5juI{bS_=E{m>At3j}XhXVir4gt$8LQM{eMVUzg02xzZ*&}45;%r%j#8eraG-US? zW(;Exl)ugj9F%kZ>Kp^*f8-DeJXyJ);*JC!sFZ=~g*<+&M;X9UYHRB61w0j@a`kn- zFrb2G%`4rSW)wIM={$F}1O_GZQq*51LJ{MNozu3$2M<<0Z`DI4ESWEw90l1&0RdP_ z8JhBEcncIn(#Q;>sJxOnl(Hv-!CX()s%_W=hpWJSs&OX|ZJag&uRmFF8h46A!_^HC z^x2TPr6B(R1qVl-nzBXHXViH}QiO|vP;J@sR5|JH`_F!V;luu1KjIWmHDr0;_~m(C z%fPA{v3jXqITlnQ$4~eeKJQA%{{ZlrBII%q_i^^rg@p`pQuY4;2>$?$2>$@^RHLO) zQU3sgn(_Yt0M5CV3@mW-KnS*fg_00t3NceZ@LnoHr6WN?a8W0l!e|+qA{5)e{{W1m z-GySOzZia3m>a&eNHX|!K_+9>8RPzh*jUipyVyZIwq+I}#rXdK7G7+pDIBOr6zog5 zqObiPuLRw5{{Sa6f(FFRJabcko*Y{kP;Yjrq*r5#vJ>gzwa@wr(1ZREU2v)jW<|$0 zOQr32AMoL+sJWuD;88Sy5S3vyS%Vs7gnfDI{>)J-ljcYq&4dv0QRzjkiAk$TUG9WM z=V1OR$V}wrm(v55$L{$eK58hzhk}0FiGyebrOix$rfOY1gD9MXD7raGQn#=wr;>_>-Ij0}=;bKat zDa-eNlm7t1UGCRWu*UU!xv=&ebyy;LPb1lU&fu$SML?1`Q5d26q@ivHK&h$BwToBv3>7u2ahemX%QEjXW9JNFS1vPo^7%PkfJyw>@AK-^$02 zigE#WhrTWYtao05MC|_S}f?K5P}CwRtD7u#?ZXj?X+FiY!2h z4ZLX&b@2!0uI*np<#pX4?y^7P3RE;xTFRJD_~fcCq~x%DhM+}E{{Yv8;8bl?qF5RQ zQO15Oa#?$6v++8Nv+LttUv)_VeV-~P6cKZtB8xjcN1`Ttw3e_+hs2ll6sIjyhEh&f z8Ui2O)ozIc4FC!uu`8MbnP`>~mvp(zm&Hz^k!-|%fl-k8nv67_>mIjE&3hTJ{{V{= z3lsUp$YcGe>ZI!9$F7*_Jw zGKyuKFU8O@@>#JxMu>V4NNS>kJK|~)M1HkTaOrf7eh@S6@W@BQ&1Wid?u>Is)0T1n z03p=NU9$;RR)6DP{{R3C8UFwdX~p4rQ=j|uyvBhWszW3Gye|X(9V~(l+g6T#3(fAg z4-^_9ig|f{XzYZ(=V zD1lGZs7yD)oFJphuF<9b?V4M_v1D`IHG~l@z1A06dj9~(*i-~ia{L<$_J6@a6k@`f zW)_4JQ8%6FuL)S<{{V0KGfe$Zg&`*e01|`Ptmf4Lmjw`Dd@9f^v%d4+#XVe3#nAX{ zM$S|zve&(#dg1?G6H*Pb`__MCU{!8lr0Eh|y0Kb3u z3_k2|tQ?c(t`~t!!;vMj4pj*AU;IB#u9H5lcpk1AbT@p*-_r#$d|$=Za{zFl}9vG8$R%l-YmSuySN0 zi``<|3Fg3y)8798$$Tos62&q907oD5!~Su+sn7lT4X!qxO2ATlS584yzD(k>!y^vx zSU@Ldkxl`~3$>gQ$N}Ve?M8Mg^w)2Re>6xde;e_?8}Yvz3(KGQ%Yh$vj_pF<-AI`d zyJN*Pm;Kpa4hkFxuvxIiMjwuAms0b@{{U7F5?QH&yoQh^B`@QCG@CTFXQ%uLf8Yn2 zLBmxMqa09S=FQ0aHiAgAfbn3UK1GI?dfMzk(P81NL{lfu3u@g=LkH%grGtuwXdm6f z0OPd1r1}Zo{4HiYvtoeNva++47C+=SiWd|updvbVQP!B~gI;DWYWR1Kyfa~(QVV#}|UuI(k zPI6%y=DLs*^<{0gUSr3bH+=1vz)(rN-CpdsdA+{u3S*jRrgEc^C~z8C(a-!Eu3z$1 z!YPc{f58i%_E$@<6q2CjWJWo*I+GzGI?o*UP9=yu>^%a1vLedm-&QXa1DcbyLu@{3 z!wf&-VSL$>{yAK2QHIS9I;yQ48mF4k;*aq9jIPoVyC|9>cn^vXzq@JmS&^E@&G%6* z(bW)^a62qSB#%v@aLIdBA0_@i=~L}-v;P1kMS1@K@;P2#^Oc%JAra)LSOa;(X-f#- z_$b1x+5Z5I{@?KC@c#glS6dni5BdZ{eMl9l_#afmgk#;|=o~IpsE2L~)f^L|oWf$t zj|EFJsW2Tw)i)`Cesx(i<@_lwDpHLnQRw2UT2S^_D>0HDEQsyq0=6iSz)x0ENOE;h z>;6M@va+bG&`3cv7I9aezZBiFhD;k6?Aq;Y_}gF{)aBM)%d9aar9^hbm| znlrrcg8=4z_`Qq3Iw;0(`n z-Q=J@HIH63Z-`@FODMr!Svr0z7h!mw@;S16a-jC8NcjnLRu*3urYSh_dMbg)T?h>- zKF<~lAx_uANofclq%}taARld1OCXUFAHU5)Wtl=e`}JNPsFBE68S5m7Wqv;u zysnl2;-2r33+}U}+d=KiC(QnS8|6V7v-lAM=W`$DSvO?#QkSo~yXVJVEOJ z03yQG)b6bz{kow-h9!&BU~s3G;97a1_BbPtmg4^aLNN1X3_%>5Atn-nd0R4eK0)TD z1W=Dp^r)6&!mfzsd}`fPBYn|?Qvl)f@kn&IAbYFU_=^Tx2?nq-K2Y(_NWA(E$BZ1xc0aHjI zx$3G3`zla;JycPHm{tAN$?rL9Ot?IHD~?;HXK-};Uv5jVoYJxG~5)K z_oMxA5fARZRN!QL@U!@8b$wDL_|YX4#B|5W?XX?N;C)ahutPrq>b(OKT6VM{gXBJ_ z6v;EfmSP+Siphv)Ou2D%(RZXS3-{)aSqM06t_extJ1c(XkCy0@_kLAN1w=Dgfe|?# zq3V`7q`#h%A5cTx2Ies!o%^7SaD*4fvXk_{`Z%g;Geoc5Q8q#xp7N7fcmvIhqU_pS zqKPc|4_7?A1D@C23O03-;Kra2EV2)Z16b8gverKm!HK?HvF6}m6d&Tky7Y_F5yg26YJaUuJCeaT$bi>w8MCp&vhG{Oy6E?HNhv2 z>m;oEK~!rf>+E%183N&60>S~|@zsk43l;Cf#rKjF9~Cl>NUCD-QhO{YKf;^I<0l`Q zq*QsTvd+z#8^Hc32Alr?169jZrc%EvtPhtN&-f!4?su`$6={5-xx$|WFo_bh0zcsS8 zmFztHS!KtWhQZ!*N>|CDAW_$Hqf$q9abF0imp(UMBtT+$v$Ld3iV|peu1n=^Ss3fb ztBfx`?-!~j9n%1_Ih^rdJRK6jqq5)*zLa8pdi1Z4M!dOeB8xTkQTxT3b$h3AW#Y@l z@UMR=6c>sF&QNj(+At8)nEg=>@+oZ9sO16A-c0pO<($U_nja*2F&AF;vEbYb>}d?2 z-T7DP8UE?6q%^H>B~u}I4VE==erKv8Ba_Vdx#+@BFh;E^ zjP0diizB7WHc~m{RQyeIAK#=Fm2zE#g#Q3Ps!~>E1HrU`;*Yeo0kv{UU+sjAwQimfXe~049uai##IsO#*(&Ii~nxsw%xY>_F`rK~5>MoH_3z9!27lx2= z=Sv{K3=5*%$8Nr=F=j~r02T^kcm4^Q4yl!Cun-kXE1ql#Ff3A_Ig&mnx_&VjJ}By* zgAY__Sq;Py@Icw96_S3;)FXP*9tmYuYlk*+uXoosH-qh4{WzaT>YW8VK|XjFyA4t0 z51+3UV3>;GDpHwWsMP$-l!7uu38Gxo;|{1^luY!q{mV>EhzZpA<3NAcM8jT%6Nl zy-+O@C+chUOoJa)jl>=t(M~G6vQcodHI#QXMV28~hSZFN9*Os7um_#U`m*={B7Zda zFoO>R;Ui=h_cZvBO*HF_qP@#kv8(Wl~Po+2j*ubzLC`f?58X5{k z$~h*K9u9JIG(QVOabfp+=SfKdd=uRSCzpWgJXY*Xnp_SpfS1}lM|M0{Sn=rm+?!5h zIv#86GcY}eS4w)31KkQbPD`aa9m?+osMF?X4k1*JfBmcN;m|$QC~FWWV_!q)AaMK2 zwt!Wcni(hrHT1C*LOjQatJfG~l<_4e>`B>t6h#D&bQG+-<|{>LJiK>I!1$d10Kkl> z5-h%?jo+IQX#80;o1~jSru2t1?bQ?LLBw%OBzTGr&Nw!xm8pd&z%LiaG|wx-VbxfZ z3ZglW!)FHk>wshDDDZ)}-d=I3T(PB20rz4ty5r`TN$vf$fk!r8o@?fiSoK7JkaX+*G}m6L}6N_6}I`MJ|kmH4|(2jzI8 z76~J_nj4yQFZWcb=VdHyoAF1)WjS(z1CDvRrqYYzjFlB?6L%KvX4c?x8AC4C{_-YM-w6b&MN5_TS2%k4J=uBMC(htq}kP`&0U(s@={{S4(9c;$KKS&kSvP>hk zjx*!s?w#;J8P8>J!X}wKw@9q=k0fzqtORln)AwC6NKmhNK!{F+*ZSo6>i*j_B=T^i ze>10=7X>Em;+rcHVpM{ep$D2z`HDA4IEMK*(b09MHU=W_u%TCH+1AjHpRP@mXX-9M9 zu7Ac7dy0VZ>MAl9LL<|KBGX$VlD(f*6M%)_ASd19&`C%>t5Wg{{R_59Vd7#-13@jq zIg`2;1{ZPh;>|u_XQH%NBoaR!FFqJ(6ZmWq$Us=@To3i`u|Db5oG?7G<9}6H?!s~F z&6^~LC)>?_jr!-(^w`g*uQlx;4PQX2Vkrzyx;6_AdJh(JaR~5u`d#u|k44Q)&lS%$ zUFV7bj^b+~2`$0KQ(T4Yhx1AB^%}k?>6wHtP_3*ELOD5XI9f-IJow`4vmEYhceT?; zNPYDql5m&IjqCAFKBqjPhNL zSZ*n|hC_|p0^uoWI5>xX|fU36J)p#uyO%s)ayI%04Te0u4#yE*fR^(E#OrPn=Ju6L>{w_|0@03Ka9@ zEV6G)=9K5~iK4PhjwST?rPUW=dl5tIcRTeIMGOP5eSJ~laMC;%-7+A1N%2}y@u~PJ z#PFOS3Mko0&${c%%4~^eXLYEIx~$uhX))2&;%@M>Iyn}pBn=|b6kkeh0A1Q_h;)n6=fig`% zGQ@Q5Qg@+GG;+i&;>5%`K*cBrBg5fCpZpOj;~Oj%? zX&@3eW}D!3M<y`w8G6_E9HMln}xcA~`1WG!22q zyb}+f>hJvNVhIjXb`W#L9fZLLXT3TgujffGik%14h6KZ$oxV`{Xd8JknSvnm1wFLm z5|ISLf#m{+vg74c8s`~M=NZihE)JLZ^GAnTHYKDmBwLutDSiVF`Y$n42phObG5{vK z5TINlJ}L$xVTO}~m}4}UFR4SyS=c>t+#WYpJCB!0Lo=1wY)1b8wbQI+>0wLS9DxGXO{{W?CI?*L+ zA9pKiSrP#A3WEdzz(7*e&>2Z`0}tYcrL?ywdZy3?LJ{IHK3)YPmVk1F)Mru#3d$73 zc?;1)5KY$A``&b^041|N0LDv!C~}2ilD`KA<^lh zVpuv&1uDc(2&Drw_5#f;z7Neh>mbDBA?{*>P(Xo$Bh{It8Bot@uXZywm0j(1ub8lE z;f8^qcyIl={#(UWLoX-?@>r~oQduk}8a@T+N}9!jpXe~8l6He3okSH4LtI(;=O{c% z(!rxJU>~xF!UKq*;dhv_ioEPjE1F^*>?Gz1tP>Kl;O#5Qm{gO$A~Jeznd2#P)k7qV zLEt-81+grB)B8m@O_$*eydQ#%DH@>;Ij=Mc0a)2xTNPSZOjz#D`0>&q3X*zx^5USXNC=*v_UHI7AMlHAOW*w0h5rBz=T9>K0CLH@ z0K=@o9+*?S*x4BS>i6Uii_Cqhte#l$SEEi4fbkFN!O*C$KCJd$$!1>b3BeLP^p~zk zcvClbbUfQYA&l;xC*9!q{{W|(f0XdlN-TB>F4ze4Q-`1V!RzP#NdEvW;d!!sdAuCW z06b1I9#SPpH;$VQ(y)nTPHD#P^PVbG{b+y&k}lYg)Jw@Y3^B@1D>a~RyrI9jX#nw` zDnq3163b(4^+>ULzYD_u00~f89abO(1oBdeqezbYlSG7>C;>f4M~(jgw?9Grf5IYE zj5q%P1>t|o`O;F66YW#atKB*uWC}Cu_EwT6)oeS)L$y5QY(ocobG3rhOW`Nvs2B;K z1^iUAAK+i^lwA;m+83aRf!-%kAS9dS_jJkbMh-d87lY&e-);U=!%I99ymR8cKl2mU z&-?-YTf)C|L?hciEZybqyh}L>z4)hP5EMAPU0>%sSE~I$@{fQfz`f?w3nbtg*}sU~ z%umy{3ImN20#r6^4ABNm&s7zYgkpL6vY#?jvc&fk6!1wJnyn&w7lg;> zPxyu}hzWvf<2+OGWJn)mdv1M8ul&b_{{SuLWY-{`IZz;u$;9?h&gK)EA19lrW9_Kt zMi@Q`u|zYXxG?)Dq02N3lJW6Fj8wQw4=ETyptKu)IbKv*tC=TM0Del~2E;N-- zm`%HaC^??52OgLyr&37m6HQ5UuTMosG_OBowFQ4QV}VQncSd6iBp9+B_Tlq@C<;g( z63K*>l4%o|1vp|ED2Jen6{PGYVts4XNxBT*mHtq%)r0%Brz26XD%48Tkq*n=39HOc zu4vDSb(L2D;u<^3ZrSx`lK~C|zl%Eyi>(bj)Tu5YNIc*n@VD=W{4DM`G6GqN62Neo zy^#ConwpkzgBZv`3}bCOG4T|S;j!bBnB-wMg{SfuqDc)<8r1u%l%$|z2WnTOLrB)# zp`h4Ks3c3rj_xr%tC;Jm&pTIHDj8as55k@&BooO*FCWCH0#F~7MiEyDZ|-g3D7;HT za@d<4?DPp{06``(NCAfgSsX`a<0v@qhh1?)lPbe?&L*dla2-KFQzW4wD@uZcDD%&M zHVmW-acqK!0s|{G4Zx4!B-MYd0~GS2LF2n30WzlwONKI!0kne<6ebY+h?+%Uk0B91 zjY28Q5D1<=Y(TF@Wp?fsDS}rHXQ2F0(}wH!ZI6Tng0MegaPR>J>F8W!OP!PDt}2l$)HGt zq`YO(f}WmL>&9RK72)JWB%6fQ2S`TA&@ZB92jr^?uTPY}k;|RfGF=sQ@djc`FurIP zBzSR1NQJR<5TOClWatucw}6Zs{{YIXxK1KMa$Ms=G{zK3xa2AT!MocM9b%)`bIJnv_5@p(&O{8B(BC!eSH&IGkgO z5b(UnfO?ZCRd00ge^&_2fv-Fz=9glhz^yV5LiI?}NuF2#053E|?D1dtG~lu{$YA60 zuTv?P!0-1|q=1a_P0z8NloLOSa|Zr;589D5!3jL^SV+Jes{#_F>D2{yvCdKVmO>gj znnfQgqGVYBYNN`f8TzXEYr@$X{1Y}(abWcGPY4Y8phWO5xO#wbZGHHvIjsYY#bKI` zi~+%Cek^%9k8al$$^6Hut1TZ0H|ma;JC7ufsyN`BNBKn%;PriINFG7x?m6^!K22oz=E0FijAKuKl>Gh24_ zsP_ecRXXhgy2O7G0>K5jt3!7aco9TIBo7T%xmyr{t!**ttZU;3T=li!kwde^?}+a| zbdgVsUz!C1T_*H+i!p&F1F7-qt%5LQ$4{CgoPa<+EQ00g5saTaSY3}Ak)JfG4^xHx z`=#>6`k$Yw!wFJnTOMnm9SBYB^ArKCtuJn@f_u1oYvjntl;!g3zRW0yJ?IqW<{uRt z3FK)^jSw33JGBb+0dNkxuaX9;4!b4Ed_> zc5x6rF+|V+F+X%rp9I6r6~_X?1ILFoM~~1SKHrK)*`ER6`=}|C2Yw$l7g0(SdHh*= QDA+poVky!_d-H$)*|}NRQvd(} literal 0 HcmV?d00001 diff --git a/notebooks/intermediate/img/debugging.jpg b/notebooks/intermediate/img/debugging.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a5892581ea04951cb9405c7ae1d6d42d92353791 GIT binary patch literal 55137 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 E*>ZieGXMYp literal 0 HcmV?d00001 diff --git a/notebooks/intermediate/img/high_quality_code.png b/notebooks/intermediate/img/high_quality_code.png new file mode 100644 index 0000000000000000000000000000000000000000..1a3439cb5ab3ca45ee2b5e6b1b9d35666783ef17 GIT binary patch literal 133588 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
O3 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%0D%f=M3{RDv2Vn89Pa!`LEave$YCrZtyqW&Gkpda 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

JlMDS@nZ|C-xb* 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

yyqQ*wZHkaJ!X)xG`O4-IyWwVgH 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

  • Jt`dY{+MmLoJ&r%z9 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

    q>c#>?ya>ckLf7B;N8UVs zZ)5-PdR{8rP0jqxM0lfp$d7Ui3DU*73ezkOfTItR-3BqNLMUv>lDT;+vhp-NJh*Vq z*@QC^SE30(d_=4P$|lUla;)1)G6%8Zo!P`3F4Sxm`+1Be24f$hmOzmN8hK>6RCH9; zH6@H{n6A~3zq>xR8f0f}(>m*+3X0vG4x6FOjv*^qNxk`i`D7M@jslzXk1r&2+?}+o zgYMg0+qR>-)nkIFkPAOEwtlBgOnsL%nkA7|`qMlYsUbt^!KqhHKWqFgn^mrz=tb74n3!)i(bOb2nC?5%llMDTTT=AWmP5)i>+y`5*>_|j zDWWr`91y5~HBg(^SHzQy<1})v_EyI{n|#!mSDboV?(wZ$7U$pAu#+5nBtbmWR7QL< zY-%B=*?4Fm$E|{T3+dzsdw42eKJ@C#I0jePERkrYQyN@dc_Y;YtDVAOvr?|-6ih}S z*eb=kL$hB3FqT3h&Cw>ZNtnh>1kM&vI=`;Qc&Par9Ktx*}O~ zvPBt}2DBFL>)_$NiqWs^8jkq~wMi4|k{fG>L|z&i=_vcc_8eJxP{nvEMvAyk!3@M& z4B#VJW7H|t;m;yW135zOSx%u)gd>WKF_>z`XX9iRU+4fnZ&o3-`1?@)$E|32AIY$+ ziPU&}{cl*5GK+YcP!KHxw`^M@C4^L}1^F^y)L8yxzt$R#9{JhGLL`3lv5}bqCCBEV z`YV)YZXsYVd2&RV8U1|d(!{BKLjhweK`vUSZW8eB#n_ed6XPry5i7$45^IjS3Dc}G zNgXdXH2QlcmKjs?Am3w`2GE9AR`+xq2kW5kt(AFYE>bj+^2IjRn{$4~^U1f0cPsl> z!@%IWglL$r2I)!h-)lpRmF)YD%!1GgV}y5h65&4ef1ogMUF2gqbt9=PsK-gQ+M3s1 z=A6}<^Jq?aBjTQ!ZciIZP2T{LFDJlA@jG;!$Zs; z+W_f%INzune{}(~R%b$L)F)TPnQ^VoiF_%)Qhv^ky`fgmMnrt9?}=kkJq1#&%-IjM z!jld6+~H-u?jI@$a+(yH3#C5=O)BQ^H|c$E*=XaBc8;6Q#qsHGR{L{#@zlQt1fXf% zIm>0D`uEKc2>l5R7&$468QSacvXOlkWt^l2%qUz#JCqgI+6%f?aP*d36?aSts6F%v zb6cBr?Xi`r{8=Kx3v@FD(Q|FU{EEtwDDw4fzQ-x zdOwCVDA;HIGpX6bkYN!Hr5Xnkgqw0(tXG>e1RH&p7hLd!d52H z(DQ^6`PqV-k&uD+J^JYHE%ykbXHZ`_&@hy|(T%JyGQfA2!DuWJ@uYtoyq%p94HRQI zp{UEv`3I~T%bo=-YGGyzKAJi}hBu_G0gO!{6q5X!VSvw0Oqtm{(oHwo-}ulS(?&P= z(HP)kSQ$#6j_UcVzS0XCUV%^zywf!uO5LECHH75*S`o)waubZl^rx;(bB#>m51LGw zB}>ue)_{h_yd*(90)pie`HSLkcRW|3pvnuZlw#d&JFmrYQWnJ9ZLgtK$ffu}$P0=b zDZ^8g?9&pVOms6`o@dP2c0vi-HcaDAi*8$zJD6n?l&$Od$b`;~^w`H|H@#P3VcFlw z6KP7G0eCs%slayl4Xc!!o8=9{Vc@1t6tGm;%m~swPyc*zt%#aTt85Y3a2UD_jcR|B zHQ$Si+z9U|^~QDb=E#+|*H4+p4bInmQ!f8qP#(Pap^5@MsvTw0q{?UUV*XhUft2El zh90khyu5dZLuqiXP)EXTyA2z1FS7JWk)M%qq?7Pjv#WQ>@C4ZCjB+?6VMZATq|Ls% zM5^@L#V%Skvqzi)ZL&}Y9K2;)C$QcX+N*5fl}uYrpnxyr)H(T3=`G-W`ty`fW+fy} z;62CLP^ByO9z0I1=|_Js=L!Us>5z6+SA2x>1^ug zf|$<~3bn&jJqwEZDnE%EnYd~7d$o*yT|043!v|~7vwCb4)%l%c5>lKhvUml3*;>ES)44R+7 z&1UZfm!Gm0iUTJg%15Uv^oI=^IBqkz=|#Or1)abnas(|H9OqPQvfl3x6?8BCk${;} zi)Wr;A~0r}Z+q{Dnh93K1|oRE$Q_K*Nx}wWVJn1BC_U!(S5|Btq)7(%OE* z_aOeKCr(7Fg%@o6vy5?6pOPdfsT^RA@ib+kW#i~X}B@I_< zT89A-pe3veqNOwvt)$xcut(Ie3CE%1T zAl3X{N@egMOxZ#XLyOTD%||%srEzm9YLCvO!WHNHzIeD;*Jf=Aw^Rt>n-&`LD5k^U zG;NQ`2>Ift#!D22=z&=wOzK=Kel*oW%M0x{9)HKQfdoFeY@CF+@*-IJsQH;3g8QaU zLPSlMM!!=utlOR%u`LOZ#XBydCwis-topD6y2c_U zf8Pnux*r`@n(Tgw&FynZSr==~0vlp3B=Qx; zyX<}}Q-3DCH_Q!vK zZ#?|L;%$8ri@z#&LDb2uYf=Wx_YEp&HWn`{gGB9G{i@rsml@9Ity8Kf3ehyl(9A%n zApiGSBjTJNP0ycelU6_GC*tQ-l;OB1)(7VnltUu%0fs4P@{-m`Wu-F@1_7O#lYVKH zNqlZ`0y3w~s7xkS@z$qYLfAu?e~kOO`OExJWMY07G4D9Tb4Te7}k8iFonAA2;sXr%kTw2MG1wPm?yS;URxYtivO+JSvw_0$QKI5E0HP%l7YMdXb^y0- z5nBqj+(n=kW=0gn{)v?rj)%n%h^}cOR0kSk`@=c19ywNXfW5Hrn^$wjR`W6w(^+ct zXDu7_$oukc9S3^FWqWGQ>W8Ap)qFF9W_6+sB}Jy7Ya8&qVfg9(WpRaEgsB08Cb=w<#VkL76{llFTBHp+T-M^@?!RGV!;uTyDa zC~#;-4fni_AfFaBi-Z-tszO@)nF;BWB|T*8AygcQyndD zBOR!(rd~Naoq(b*#HQ45C6}D-$60ZE4o#PQ1HcPzW@Xu^P$&1+Cc&4VmdC*m3`ZWJ zjw0Q+SYE@>`;)Ed^`enC=x2H;ciX@HWUe=#q&TS{{qvdms)a-?$4A=qhUB3dl8QE* z#)L^nHOeILAQVjd`7Uc@>!|u>MxdMao=D~LMWa#k9DRtU4I8F zqM;B@8=5cyD{VuIm}B|7;+2_>2~osbOcdIP!`AOou&f73&hZaR|DOLi6>}JCw;`zH z2vIFUs<0mq?0`HdPRmtIsW!?C!X)lY)h)I=^}NKyUDw{AQHq$izE`ld@LIea;N^NyQovg^;$OE<>6*W2H(+)2+Lo>?T)2}XoNm#{6K%NhAXJvaeI{V_a+(D ziiu1_xiS(Lke%28-Ik7X=s5kc!nRiUh>b(0Na78oP!Wq)-D*bmOMviQjsW`#SFJQJkHsUw`J2~ARrLV4b_W1>~&ZaAIv#o2(^ zXiZyi9;4@k62Ud(dLYfYn%ntRY_f0Y-bURa-i2BocGSwm&TTV;>2PnRAk<2Kka$h9H`{8n$+o zx>yVNsXvc-U5;}7(d3#IuIE^$+E|<_%L?~N2?{t%STC(wYYTq+kqLOz5qQu=19B+l zjZ!LHWmMd`t0H+G+@c6EfJovnZplbF^+jXzeJAc~rAiJEyZ^1CfM~kqwGno@SG)|z zsMDa0+nvc?kX*gobb7RU^9Q9L?olcA;|&n zPj=eaOmOl}>X+|dmgJdn4DW{40F>&CO?AHrYrgRjZg#4%Ur~xHK(2f>R=#7fXvVN6 z-x~w8AyBs_$x_Ztab;d_C~ziUTvlpWTLykExw=Ef{p;$b;x-2-$gU4lyV$H-MP%f z4DgUJFro*4jdu;>pCk=As*qf&&=y>O%F887P!s0mZpP4;>abA+Ma>9MR^OTidEG@V zT8Ivj^Hss*BC8a%<^_^R(eeSz(J%RN(?T3bgK!QXTlk-m^Uw#;uFQ@rM4)8KG1oow zymJuz@CWi2UPD#IEI;gKBvq5}B9V0RCAy>3D=%#Ie+6;|jrnRSs|PdIE`J z81+rT07!5U<3pBU@RMbV%w0k&m9ewU0=y>G2F#W;ke=$GFy`MIowdLd&zzCw2jU)V z8ZwD00(kkR%guL#77}9m*WBIB1b7U8F1SVAbIufylo&c{pc+J+h%A&SXI6H8&ok1r z2ZzZ8c9>c`Dyi4;F#iDU&{96^+Bkbc_Aaev_aGiqQQd;Tv(Oa~5Jvd`r`e}K)O6yT zVz{7Eqk%>Vdm{9e!o!^t1b zQZQfhrofnrA%nj-DDfL@1wUZ?QZh0NqLxZxmLBX25Hes*>~U*jmOOvL(Ek8Gm6SP@ z{{X$vQh#z(;XuO@ArZDCdu6#`p=3!iVqPB%GjAdo{8`RPux71=NULnDu$WQGgDE_p zR3%rsD3jY0At-7VA1NMzVrtFDomA0AV7;uOi_eSJADs*q^&)H5aAOVbOb3p zvccyDsk8q872!q9e?QfuY2jyn zsxQo@5sH|C8GHu^Owz6soz4W346BLW5{h|4l&f7jjERI$@iq_{nE|3+3|gwfY$r9?)*fH~0A<|d>aE|58M1qYif~n- zBQn9nN8-QpyVL9|c!=dd!MJDrijy}@Ng%+Q&O~{tVhs}dNrb+p!;n!X$-&1#1c6n> zf(fY3w}w_cCz6eh?)C1uxd)o;sviwG^%O)r%m|1eBo;&{q-#2i-Z(_yYZRE|wOI10 z6J11LB?(f%q99bjC1OD~oAAO+2uT7#B-z-fbTNdWtO+$44`l#RYMB;aL} zr~<-HgTY6MjSC_~4CBP|txh6W!j705`QFG)WN<p z2qwVXm7~n~rb+M$ts(ya6k#W9>dUrxW{6Q!;|CN&%+NR_VuYPQ{{U>!_+F}D=mCwv zTf>YHL5Rg7Y7asmsI3afa;Qh*gP4z^Q`*Z@+Wkdd&sg;f0uSh+JXptU>R{?9sxli z4g>BemP)h+f0mmck3m_O0X63ZbHU~cV9P&^i2&I~XQz9q1%y!&u4k#rh7;nXV7JYc z%Yonk008;E14l* zTtnK6oPjNI0^oLzITy`5kmyTU5VP!yF(QZ`H*o;uqp?|=#R4wXu&WZU=_(pg2w5Cb b&ZAO9l;JEg->rZHQV~RDM+%-2Jm3G>{-)AU literal 0 HcmV?d00001 diff --git a/notebooks/intermediate/img/prints.jpg b/notebooks/intermediate/img/prints.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dfe9d56049da3ec632e01f00b5fd8890800bf67c GIT binary patch literal 21118 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

    AA62-KtRlQ zV32SKIG_kJ1Z&fQ*Rd5|ZgMwg9jft+7QqrXXHU)5Tk=H$F zk}b-nMct9pC#6_he06mPIpUi+ZORov7yxIC(?C!b@ROB0Nb9>l)||1j6Oo=t89$|1 zW{i-ItCBJIYA5nwBo^2YPSn7JD0OVc<7xY$zW2A|Ria5^xC%0=>Pjm%MtwgjyDKy0 zK>!o?m}hqx?Nu&NIK{I;Ce`*Vu-scw%wHCR4ufO@HnVsgt0OP8%;C=TWM^fkPkSe0}KsG<)0xWXD1_p^rjFGB7i0j zyC;G4;{t-Lr)e&yIqApNk{!4zR2&@h(-`KgywMH7HtcW+1P+5ed8ELKQVJNIv)38V zKKZ8Y7*T+zIw?FFMRMGnlbjxUiX~mVpg%4FB;-;7?H|lW_6kn{f5-aMLIui@3V=Rt zzlA*}3>C4Q;CoY)870_=1F-|@Xc-UP1PuBd9+cCcGv>%N^2Y<)ueC(YkP3{S%bv6V z!p*bg9CL%|QK&9RD#b~`z{wxy)}-6HysVXCF^u&DQW+T#F;ykTMmx|1N<~>S{APFp%29PCJqS z&#*=XBn0Yh{C$?L^c2zG!D#{0}i zR;!S2m=#fm$M?Haum;s~xyU*D)qNaDicj9@&p)MCKry?Xpqy2NU5rX~1HAxE9Aa4s zB<<)n@s29OOB%2N2xLDuwm9R~tBF^k%Hxs+SThxc>c0y4xCxk*+emi{61 zBA3i!;zS@ealpno;{&1NwM19~>@)Im0B`G2r<`&VX<>o^^{E0!xQs*?D0Xv}AacIg zrJKo^g0f{eBox43^UzdlDPA#xdX6|gwHivO`9MIG4c|lX;1(?bN79XLhJ}T ih6YD|zgn7S5=4UsB=B>d+*NraJc6Kt22N@22mjfqvi*<% literal 0 HcmV?d00001 diff --git a/notebooks/intermediate/img/reinvent.jpg b/notebooks/intermediate/img/reinvent.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a39d811d9216309f0f85e9850c3468cdd9e00ba1 GIT binary patch literal 32737 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

    f+vl}6-?pSF%kQ5W9Hv) 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⪻&#)&gF^x)7Y8ba*WtDIF4mT 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

    vqCtTtP|33u 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 literal 0 HcmV?d00001 diff --git a/notebooks/intermediate/img/virtualenvs.jpg b/notebooks/intermediate/img/virtualenvs.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8b5514f65a26da1f06b91fe484d3b2428f2acc2c GIT binary patch literal 31928 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%0AWoq~nXUZZBh_Ws|B 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 T!l=9leLm8Ut2C\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Why\n", + "* Isolation\n", + "* Different projects have different dependency versions\n", + "* You don't want to mess up the system Python" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tooling\n", + "`pipenv` is currently the recommended tool for dependency management but [\"consider other tools such as pip when pipenv does not meet your use case\"](https://packaging.python.org/guides/tool-recommendations/#application-dependency-management). If `pipenv` doesn't fit your use case, I recommend using `virtualenvwrapper` for managing virtual environments and `pip` for package management. On the other hand, if you're working on only a couple of projects, built-in [`venv`](https://docs.python.org/3/library/venv.html) will do just fine.\n", + "#### [`pipenv`](https://pipenv.readthedocs.io/en/latest/)\n", + "* Basically combines `pip` and `virtualenv` under single CLI\n", + "* [Pipfile](https://pipenv.readthedocs.io/en/latest/basics/#example-pipfile) which replaces the need for requirements.txt and requirements-dev.txt \n", + "* [Pipfile.lock](https://pipenv.readthedocs.io/en/latest/basics/#example-pipfile-lock) which pins dependencies, this means deterministic builds\n", + "* Possibility to visualize the [dependency graph](https://pipenv.readthedocs.io/en/latest/#pipenv-graph)\n", + "* [Compatible with `pyenv`](https://pipenv.readthedocs.io/en/latest/advanced/#automatic-python-installation)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### [`virtualenvwrapper`](https://virtualenvwrapper.readthedocs.io/en/latest/)\n", + "* If you are using Windows command prompt: [`virtualenvwrapper-win`](https://pypi.org/project/virtualenvwrapper-win/)\n", + "* Like the name suggests, a wrapper around [`virtualenv`](https://pypi.org/project/virtualenv/)\n", + "* Eases the workflow for creating, deleting, and (de)activating your virtual environments" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### [`pyenv`](https://github.com/pyenv/pyenv)\n", + "* Easily change global / per project Python version \n", + "* Also a tool for installing different Python versions (also different runtimes available, e.g. [PyPy](https://pypy.org/))\n", + "* Useful if you'll need to work with different Python versions" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -24,7 +76,7 @@ "* Make sure that everything works as expected\n", "* Make sure that old stuff works as expected after introducing new features (regression)\n", "* Tests give you confidence while refactoring\n", - "* It documents how your implementation is used \n", + "* Good tests demonstrate the use cases of application, i.e. they also document the implementation \n", "* ..." ] }, @@ -53,7 +105,7 @@ "metadata": {}, "source": [ "#### [`tox`](https://tox.readthedocs.io/en/latest/)\n", - "`tox` makes it simple to test your code against different Python interpreter/language and dependency versions. This is important when you're writing software which should support different Python versions, which is usually the case with library-like packages. On the other hand, if you're developing, say, a web application which will be deployed to a known target platform, testing against multiple different versions is not necessary. However, `tox` makes it also possible to configure, for example, linting and building of docs as part of `tox` run. Thus, it `tox` may simplify the development workflow significantly by wrapping multiple different operations under single command." + "`tox` makes it simple to test your code against different Python interpreter/runtime and dependency versions. This is important when you're writing software which should support different Python versions, which is usually the case with library-like packages. On the other hand, if you're developing, say, a web application which will be deployed to a known target platform, testing against multiple different versions is usually not necessary. However, `tox` makes it also possible to configure, for example, linting as part of `tox` run. Thus, `tox` may simplify the development workflow significantly by wrapping multiple different operations under a single command." ] }, { @@ -70,7 +122,8 @@ "source": [ "### Why\n", "* Easy to read\n", - "* Better maintainability" + "* Better maintainability\n", + "* Better quality == less bugs" ] }, { @@ -78,62 +131,95 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "import this" + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Tooling - code formatters" + "### Tooling - code formatters\n", + "[PEP8](https://www.python.org/dev/peps/pep-0008/?) (see also [\"for humans version\"](https://pep8.org/)) describes the style guidelines for Python code, you should follow them. Luckily, there are awesome tools that handle this for you while you focus on writing code, not formatting it." ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "#### [`yapf`](https://github.com/google/yapf)\n", + "* [PEP8](https://www.python.org/dev/peps/pep-0008/?) compliant code that also looks good\n", + "* Loads of [configuration options](https://github.com/google/yapf#knobs) - but also reasonable defaults" + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Tooling - linters" + "#### [`black`](https://black.readthedocs.io/en/stable/)\n", + "* Note requires Python 3.6+\n", + "* Note \"This is a beta product\" while writing this\n", + "* Uncompromising - not as many configuration options as in `yapf`\n", + "* Good [integration with editors](https://black.readthedocs.io/en/stable/editor_integration.html)\n", + "* Try it in the [playground](https://black.now.sh)" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "### Tooling - linters\n", + "Automatic code formatting is great but in addition to that, you should use static analyzer (linter) to detect potential pitfalls in your code." + ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "#### [`flake8`](http://flake8.pycqa.org/en/latest/)\n", + "* Wraps [`mccabe`](https://pypi.org/project/mccabe/) (complexity checker), [`pycodestyle`](https://pypi.org/project/pycodestyle/) (PEP8), and [`pyflakes`](https://pypi.org/project/pyflakes/) (error checker) " + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Tooling - pre-commit" + "#### [`pylint`](https://pylint.readthedocs.io/en/latest/)\n", + "* More verbose compared to `flake8`\n", + "* Criticized about the default configuration but is easily configurable\n", + "* Gives an overall score" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "#### [`bandit`](https://pypi.org/project/bandit/)\n", + "* Checks for security vulnerabilities" + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Structure your code\n", + "### Tooling - pre-commit\n", + "#### [`pre-commit`](https://pre-commit.com/)\n", + "Ideally, all project contributors should follow the best practices of the project, let it be e.g. respecting PEP8 or making sure there's no linting errors or security vulnerabilities in their change sets. However, as code formatters and linters are (mainly) local tools, this can not be guaranteed. `pre-commit` let's you configure (.pre-commit-config.yaml file) a set of hooks that will be run as pre actions to a commit/push. After a developer has called once `pre-commit install`, these hooks will be then automatically ran prior each commit/push.\n", + "* Run formatting before commit\n", + "* Fail the commit in case linting errors\n", + "* Even exercise the test suite before the code ends up to remote (might be time consuming in most scenarios though)\n", + "* Easy to configure [your own hooks](https://pre-commit.com/#new-hooks) \n", + "* And use the [existing ones](https://github.com/pre-commit/pre-commit-hooks)\n", + "* There's also [pre-push option](https://pre-commit.com/#pre-commit-during-push)\n", + "* Written in Python but supports also other languages, such as Ruby, Go, and Rust\n", + "* Less failed CI builds!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Structure your code and projects\n", "" ] }, @@ -141,219 +227,291 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Why" + "### Why\n", + "* Package and module structure gives an overview about the project\n", + "* Modular design == better reusability" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "### How\n", + "Some general guidelines:\n", + "* Don't put too much stuff into one module\n", + "* Split project into packages\n", + "* Be consistent with your naming conventions" + ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "A few words about structuring your projects. If you're developing, say, a relative big business application, it makes sense to separate some of the non-core business logic packages into a separate project and publish that as separate package. This way the \"main\" repository doesn't get bloated and it's more approachable for newcomers. Additionally, there's a change that you (or someone else) can easily reuse this \"separated\" package in the future, which is often the case e.g. for different kinds of utility functionalities. \n", + "\n", + "Let's take a practical example. If your team has two different applications which interact with the same third party, it's beneficial to implement a separate client library for communication with it. This way a change is needed only in one place (in the client library) if the third party decides to make a backwards incompatible change in their API. " + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Structure your projects" + "### Tooling\n", + "#### [`cookiecutter`](https://cookiecutter.readthedocs.io/en/latest/)\n", + "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Why" + "Cookiecutter is a tool which let's you create projects from predefined templates. \n", + "\n", + "* Rapid set-up of new projects, no need to copy paste from existing ones\n", + "* Consistent development practices across all projects (project structure as well as e.g. `pre-commit`, `tox`, and CI configuration)\n", + "* You can create one yourself or use some of the [existing ones](https://cookiecutter.readthedocs.io/en/latest/readme.html#python)\n", + "* Written in Python but is applicable for non-Python projects as well, even non-programming related directory and file structures" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "## Use continuous integration and deployment\n", + "" + ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "CI & CD belong to the best practices of software development without controversy, no matter what is the technology stack used for development. From Python point of view, CI is the place where we want to make sure that the other best practices described above are followed. For example, in bigger projects, it may not be even practical/possible to run the full test suite on developer's machine." + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## One environment per project\n", - "\n" + "### Why\n", + "* Make sure the tests pass\n", + "* CI is the place where it's possible to run also some time consuming tests which the impatient developers prefer to skip on their local machines\n", + "* Make sure there's no linting errors\n", + "* Ideally, the place to test against all target versions and platforms\n", + "* Overall, CI is the last resort for automatically ensuring the quality \n", + "* Manual deployments are time consuming and error-prone, CD is automated and deterministic\n", + "* You want to automate as much as possible, human time is expensive\n", + "* Minimize the time required for code reviews - what could be detected with automatic tools, should be detected by using those tools. Human time is expensive. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Why" + "### Tooling\n", + "Tooling depends on which git repository manager option you've chosen and what kind of requirements you have. For example:\n", + "* Gitlab has a built-in [integrated CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/)\n", + "* Same for [BitBucket](https://www.atlassian.com/continuous-delivery/continuous-integration-tutorial)\n", + "* If you're using GitHub, see [full list of available tools](https://github.com/marketplace/category/continuous-integration)\n", + "* There's an extensive comparison of different providers in [wikipedia](https://en.wikipedia.org/wiki/Comparison_of_continuous_integration_software)\n" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "## Utilize the capabitilies of your editor" + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Tooling" + "### Why\n", + "* Efficient and fluent development\n", + "* There's plenty of tools to make your daily programming easier, why would you not use them" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "### Tooling\n", + "As there's a number of different editors and IDEs available, not to mention that everyone has their own preferences, I'll just focus on highlighting some of the features of my favorite IDE, PyCharm, which I highly recommend for Python development.\n", + "\n", + "#### [PyCharm](https://www.jetbrains.com/help/pycharm/quick-start-guide.html)\n", + "* Good integration with `pytest`, e.g. run single tests / test classes / test modules\n", + "* Git integration (in case you don't like command line)\n", + "* Easy to configure to use automatic formatting, e.g [`black`](https://github.com/ambv/black#pycharm)\n", + "* Intuitive searching capabilities\n", + "* Refactoring features\n", + "* Debugger\n", + "* Jupyter Notebook integration\n", + "* Free community edition already contains all you need" + ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "## Use existing solutions\n", + "" + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Use continuous integration" + "### Why\n", + "* Python Standard Library is extensive - and stable!\n", + "* There are over 150k packages in [PyPI](https://pypi.org/)\n", + "* Someone has most likely solved the problem you're trying to solve\n", + "* Spend 5 minutes doing a google research before starting to solve a new problem, e.g. [stackoverflow](https://stackoverflow.com/) is a magical place." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Why" + "## Learn how to debug efficiently\n", + "" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "### Why\n", + "* You won't write completely stable code anyway - impossible looking conditions will occur. \n", + "* When something is not working as expected, there are plenty of tools out there to help you figure out what's going on. " + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Utilize the capabitilies of your editor" + "### Tooling - debuggers\n", + "#### [`pdb`](https://docs.python.org/3/library/pdb.html)\n", + "* Part of the Standard Library\n", + "* Sufficient for most use cases" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Why" + "#### [`ipdb`](https://pypi.org/project/ipdb/)\n", + "* Feature rich `pdb` with similar API" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "#### [`pdb++`](https://pypi.org/project/pdbpp/)\n", + "* Drop-in replacement for `pdb` with additional features" + ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "### Tooling - profilers" + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Use existing solutions\n", - "" + "#### [`gprof2dot`](https://github.com/jrfonseca/gprof2dot)\n", + "* Find the performance bottlenecks of your application via illustrative graphs\n", + "* If you're using `pytest` (like you should), see also [`pytest-profiling`](https://pypi.org/project/pytest-profiling/) which is powered by `gprof2dot`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Why" + "#### [`py-spy`](https://github.com/benfred/py-spy)\n", + "* Profile running Python program without the need for modifying the source code or restarting the target process\n", + "* Potential tool for identifying problems of e.g. a web application in production " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "std lib, Pypi" + "#### [`objgraph`](https://mg.pov.lt/objgraph/)\n", + "* Graphs which are useful while hunting memory leaks" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "### Tooling - runtime error tracking\n", + "These are especially useful with web applications as you'll get reports - and notifications - of runtime exceptions with full tracebacks and variable values. This information is often enough for identifying the root cause of the problem, which is a huge benefit considering the time required for implementing and deploying the fix." + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Use Cookiecutter" + "#### [Sentry](https://docs.sentry.io/?platform=python)\n", + "* Complete stack traces with relevant variable (`locals()`) values\n", + "* Browser and OS information of the client\n", + "* Support for other languages as well" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "#### [`rollbar`](https://docs.rollbar.com/docs/python)\n", + "* Very similar to sentry" + ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "While writing this, both sentry and rollbar are free for hobbyist use." + ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "### Tooling - misc" + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Use logging instead of prints\n", + "#### Use logging instead of prints\n", "" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "* [`logging`](https://docs.python.org/3/library/logging.html) is part of the Standard Library\n", + "* With logging you can redirect the output to a file\n", + "* Logs are usually the first place to look at after an end user reports an issue\n", + "* You can specify the runtime level - no need to remove the debug prints" + ] }, { "cell_type": "markdown", "metadata": {}, - "source": [] + "source": [ + "### General guidelines\n", + "* Use Python 3, legacy Python (aka 2.7) will [retire soon](https://pythonclock.org/)\n", + "* Develop in branches. Even if you're the only person in the project, branching makes it possible to easily switch between different features / bug fixes.\n", + "* If you're not developing alone, practice code reviews. It's one of the best ways to learn for both parties.\n", + "* Document your master pieces" + ] } ], "metadata": { From b3872b92c70a4455cb285dc0e857757925eeb374 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 23 Sep 2018 13:21:30 +0200 Subject: [PATCH 23/60] Fix formatting --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 59b3d65..1c9b174 100644 --- a/README.md +++ b/README.md @@ -64,8 +64,8 @@ Python is a powerful language which contains many features not presented in most 1. Other tips and tricks #### Best practices -1. A list of best development practices for Python projects. Most of the practices listed here are also applicable for other languages, however the presented tooling focuses mainly on Python. -[Best practices](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/best_practices.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/best_practices.ipynb) +A list of best development practices for Python projects. Most of the practices listed here are also applicable for other languages, however the presented tooling focuses mainly on Python. +1. [Best practices](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/best_practices.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/best_practices.ipynb) #### General topics 1. [Goodies of the Standard Library - part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/std_lib2_exercise.ipynb) From eb13cd362c940642fa634ac641872af22305b57a Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 23 Sep 2018 14:42:46 +0200 Subject: [PATCH 24/60] Fix ipytest install issue --- .../intermediate/html/pytest_fixtures.html | 73 +++++++++++++------ .../notebooks/pytest_fixtures.ipynb | 2 +- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/notebooks/intermediate/html/pytest_fixtures.html b/notebooks/intermediate/html/pytest_fixtures.html index 935802b..665ffc7 100644 --- a/notebooks/intermediate/html/pytest_fixtures.html +++ b/notebooks/intermediate/html/pytest_fixtures.html @@ -11820,7 +11820,7 @@

    Efficient use of pytest f
    # Let's make sure pytest and ipytest packages are installed
     # ipytest is required for running pytest inside Jupyter notebooks
     import sys
    -!{sys.executable} -m pip install pytest ipytest>=0.3.0
    +!{sys.executable} -m pip install pytest 'ipytest>=0.3.0'
     
     import pytest
     from ipytest import magics, clean_tests
    @@ -11831,6 +11831,31 @@ 

    Efficient use of pytest f

  • +
    +
    + + +
    + +
    + + +
    +
    Requirement already satisfied: pytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (3.5.0)
    +Requirement already satisfied: ipytest>=0.3.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (0.3.0)
    +Requirement already satisfied: attrs>=17.4.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (17.4.0)
    +Requirement already satisfied: pluggy<0.7,>=0.5 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (0.6.0)
    +Requirement already satisfied: setuptools in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (39.0.1)
    +Requirement already satisfied: py>=1.5.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.5.3)
    +Requirement already satisfied: more-itertools>=4.0.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (4.1.0)
    +Requirement already satisfied: six>=1.10.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.11.0)
    +
    +
    +
    + +
    +
    +
    @@ -11961,7 +11986,7 @@

    -
    =================================================================================== test session starts ====================================================================================
    +
    ================================================================================ test session starts =================================================================================
     platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
     rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
     plugins: nbval-0.9.0
    @@ -11974,12 +11999,12 @@ 

    -
    =================================================================================== test session starts ====================================================================================
    +
    ================================================================================ test session starts =================================================================================
     platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
     rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
     plugins: nbval-0.9.0
    @@ -12076,12 +12101,12 @@ 

    -
    =================================================================================== test session starts ====================================================================================
    +
    ================================================================================ test session starts =================================================================================
     platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
     rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
     plugins: nbval-0.9.0
    @@ -12172,12 +12197,12 @@ 

    -
    =================================================================================== test session starts ====================================================================================
    +
    ================================================================================ test session starts =================================================================================
     platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
     rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
     plugins: nbval-0.9.0
    @@ -12247,12 +12272,12 @@ 

    Fixture scope -
    =================================================================================== test session starts ====================================================================================
    +
    ================================================================================ test session starts =================================================================================
     platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
     rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
     plugins: nbval-0.9.0
    @@ -12337,12 +12362,12 @@ 

    Fixture scope @@ -12403,7 +12428,7 @@

    Setup-teardown behaviour -
    =================================================================================== test session starts ====================================================================================
    +
    ================================================================================ test session starts =================================================================================
     platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
     rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
     plugins: nbval-0.9.0
    @@ -12416,12 +12441,12 @@ 

    Setup-teardown behaviour @@ -12481,7 +12506,7 @@

    Using fixtures automatically -
    =================================================================================== test session starts ====================================================================================
    +
    ================================================================================ test session starts =================================================================================
     platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
     rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
     plugins: nbval-0.9.0
    @@ -12493,12 +12518,12 @@ 

    Using fixtures automatically=0.3.0\n", + "!{sys.executable} -m pip install pytest 'ipytest>=0.3.0'\n", "\n", "import pytest\n", "from ipytest import magics, clean_tests\n", From ea5d4a36ff5da82065eeae34c8f891117428b03a Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Mon, 24 Sep 2018 21:03:59 +0200 Subject: [PATCH 25/60] Fix some typos --- notebooks/intermediate/html/std_lib2.html | 14 +++++++------- notebooks/intermediate/notebooks/std_lib2.ipynb | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/notebooks/intermediate/html/std_lib2.html b/notebooks/intermediate/html/std_lib2.html index b9b0f6b..a0a8d32 100644 --- a/notebooks/intermediate/html/std_lib2.html +++ b/notebooks/intermediate/html/std_lib2.html @@ -11857,7 +11857,7 @@

    Encoding

    -
    type: <class 'str'> data: {"a": 1, "some_list": [1, 2, 3], "b": true, "c": null, "nested": {"foo": "bar"}}
    +
    type: <class 'str'> data: {"c": null, "b": true, "some_list": [1, 2, 3], "a": 1, "nested": {"foo": "bar"}}
     
    @@ -11897,7 +11897,7 @@

    Decoding

    -
    type: <class 'dict'> data: {'a': 1, 'some_list': [1, 2, 3], 'b': True, 'c': None, 'nested': {'foo': 'bar'}}
    +
    type: <class 'dict'> data: {'c': None, 'nested': {'foo': 'bar'}, 'b': True, 'some_list': [1, 2, 3], 'a': 1}
     
    @@ -11939,7 +11939,7 @@

    self.creds = (username, password) def fetch_some_data(self): - print('Here we could for example fetch data from 3rd API and return the data.') + print('Here we could for example fetch data from 3rd party API and return the data.') print('Now we will just return some random number between 1-100.') return random.randint(1, 100) @@ -12066,7 +12066,7 @@

    print('All good, woop woop!') -test_do_something_fancy() # This just for the sake of example +test_do_something_fancy() # This is just for the sake of example

    @@ -12252,7 +12252,7 @@

    -
    {'odd': [1, 3, 3, 5, 7], 'even': [2, 4, 2, 6]}
    +
    {'even': [2, 4, 2, 6], 'odd': [1, 3, 3, 5, 7]}
     
    @@ -12300,7 +12300,7 @@

    -
    defaultdict(<class 'list'>, {'odd': [1, 3, 3, 5, 7], 'even': [2, 4, 2, 6]})
    +
    defaultdict(<class 'list'>, {'even': [2, 4, 2, 6], 'odd': [1, 3, 3, 5, 7]})
     
    @@ -12347,7 +12347,7 @@

    -
    defaultdict(<class 'int'>, {'odd_count': 5, 'even_count': 4})
    +
    defaultdict(<class 'int'>, {'even_count': 4, 'odd_count': 5})
     
    diff --git a/notebooks/intermediate/notebooks/std_lib2.ipynb b/notebooks/intermediate/notebooks/std_lib2.ipynb index 04be8cb..aac47c7 100644 --- a/notebooks/intermediate/notebooks/std_lib2.ipynb +++ b/notebooks/intermediate/notebooks/std_lib2.ipynb @@ -94,7 +94,7 @@ " self.creds = (username, password)\n", " \n", " def fetch_some_data(self):\n", - " print('Here we could for example fetch data from 3rd API and return the data.')\n", + " print('Here we could for example fetch data from 3rd party API and return the data.')\n", " print('Now we will just return some random number between 1-100.')\n", " return random.randint(1, 100)\n", "\n", @@ -175,7 +175,7 @@ " print('All good, woop woop!')\n", " \n", " \n", - "test_do_something_fancy() # This just for the sake of example" + "test_do_something_fancy() # This is just for the sake of example" ] }, { From 4f4290b4a9ab1c6083569e9f7c6c149ce1295c79 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sun, 30 Sep 2018 16:41:14 +0200 Subject: [PATCH 26/60] Ignore sync scripts --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 340057c..f9071de 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ .idea* .pytest_cache* .tox* -*pycache* \ No newline at end of file +*pycache* +sync-*.sh \ No newline at end of file From 0d199a8bed524c73ed48a466c73e8357d50dd5e5 Mon Sep 17 00:00:00 2001 From: Manohar Ganta Date: Sat, 27 Oct 2018 18:10:34 +0530 Subject: [PATCH 27/60] copy() under lists are mutable --- notebooks/beginner/notebooks/lists.ipynb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/notebooks/beginner/notebooks/lists.ipynb b/notebooks/beginner/notebooks/lists.ipynb index b0c5a20..ef4dd3d 100644 --- a/notebooks/beginner/notebooks/lists.ipynb +++ b/notebooks/beginner/notebooks/lists.ipynb @@ -141,6 +141,8 @@ "source": [ "original = [1, 2, 3]\n", "modified = list(original) # Note list() \n", + "# Alternatively, you can use copy method\n", + "# modified = original.copy()\n", "modified[0] = 99\n", "print('original: {}, modified: {}'.format(original, modified))" ] @@ -308,7 +310,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.6.4" } }, "nbformat": 4, From 08ea8b70d3705cd58e317bc01269f8d306d8fba6 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sat, 27 Oct 2018 14:58:49 +0200 Subject: [PATCH 28/60] Sync html with the notebook --- notebooks/beginner/html/lists.html | 4 +++- notebooks/beginner/notebooks/lists.ipynb | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/notebooks/beginner/html/lists.html b/notebooks/beginner/html/lists.html index b7c291f..e5603d9 100644 --- a/notebooks/beginner/html/lists.html +++ b/notebooks/beginner/html/lists.html @@ -11777,7 +11777,7 @@ } $( document ).ready(function(){ - show=false; +show=false; $('div.output').hide() }); @@ -12121,6 +12121,8 @@

    List are mutable
    original = [1, 2, 3]
     modified = list(original)  # Note list() 
    +# Alternatively, you can use copy method
    +# modified = original.copy()
     modified[0] = 99
     print('original: {}, modified: {}'.format(original, modified))
     
    diff --git a/notebooks/beginner/notebooks/lists.ipynb b/notebooks/beginner/notebooks/lists.ipynb index ef4dd3d..0a08876 100644 --- a/notebooks/beginner/notebooks/lists.ipynb +++ b/notebooks/beginner/notebooks/lists.ipynb @@ -310,7 +310,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.4" + "version": "3.5.4" } }, "nbformat": 4, From a37f269fe759443f708d58d596599eeb6b1a03a1 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 9 Jul 2020 05:12:42 +0200 Subject: [PATCH 29/60] Travis CI: Add Python 3.8 to testing --- .travis.yml | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 234fff8..9b5710e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,7 @@ -sudo: false +os: linux +dist: focal language: python -install: -- pip install jupyter -- pip install tox -- pip install nbval -- pip install pytest - - -stages: - - test - jobs: include: - python: 3.5 @@ -19,8 +10,8 @@ jobs: env: TOXENV=py36 - python: 3.7 env: TOXENV=py37 - dist: xenial - sudo: true + - python: 3.8 + env: TOXENV=py38 -script: -- tox +install: pip install jupyter nbval pytest tox +script: tox From 1cdc0f35e8d0f156181a90303c27a4642f292a60 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 9 Jul 2020 05:14:00 +0200 Subject: [PATCH 30/60] tox.ini: Add py38 --- tox.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index b503cc3..c697cfc 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,8 @@ skipsdist = True envlist = py35, py36, - py37 + py37, + py38 skip_missing_interpreters = true [testenv] @@ -11,4 +12,4 @@ deps = nbval jupyter commands = - pytest --nbval notebooks \ No newline at end of file + pytest --nbval notebooks From 895c5422a98fe05499a97233cb8125bdf12b850a Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Tue, 18 Apr 2023 09:48:17 +0300 Subject: [PATCH 31/60] Get rid of unneeded stuff --- .travis.yml | 17 -------- tox.ini | 15 ------- utils/post_save_hook.py | 97 ----------------------------------------- 3 files changed, 129 deletions(-) delete mode 100644 .travis.yml delete mode 100644 tox.ini delete mode 100644 utils/post_save_hook.py diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9b5710e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -os: linux -dist: focal -language: python - -jobs: - include: - - python: 3.5 - env: TOXENV=py35 - - python: 3.6 - env: TOXENV=py36 - - python: 3.7 - env: TOXENV=py37 - - python: 3.8 - env: TOXENV=py38 - -install: pip install jupyter nbval pytest tox -script: tox diff --git a/tox.ini b/tox.ini deleted file mode 100644 index c697cfc..0000000 --- a/tox.ini +++ /dev/null @@ -1,15 +0,0 @@ -[tox] -skipsdist = True -envlist = py35, - py36, - py37, - py38 -skip_missing_interpreters = true - -[testenv] -deps = - pytest - nbval - jupyter -commands = - pytest --nbval notebooks diff --git a/utils/post_save_hook.py b/utils/post_save_hook.py deleted file mode 100644 index daf2b6f..0000000 --- a/utils/post_save_hook.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -Jupyter post_save_hook script for generating .py/.html files automatically when .ipynb file is saved. - -Add the content to your jupyter_notebook_config.py. The location is usually $HOME/.jupyter/jupyter_notebook_config.py. -If you don't have one yet, you can generate the file: jupyter notebook --generate-config -""" - -import json -import os -from subprocess import check_call - -SAVE_PY = False # Save .py files (location is
    /py/) -SAVE_HTML = True # Save .html files (location is /html/) - -# Run notebook before saving py/html. Note: this won't affect to the state of the .ipynb file. -RUN_NB_BEFORE_SAVE = True - -# Skip saving of files which name contains of the following -DONT_SAVE = {'exercise', 'copy', 'untitled'} - -# Add beatufil "Toggle output" button at the top of html page -USE_TOGGLE_BTN_IN_HTML = True - -TOGGLE_OUTPUT_BTN = { - "cell_type": - "raw", - "metadata": {}, - "source": [ - "\n", "\n", - "\n", - " \n", "\n", "" - ] -} - - -def _run_cmd(cmd, cwd=None): - check_call(cmd.split(), cwd=cwd) - - -def post_save(model, os_path, contents_manager): - if model['type'] != 'notebook' or not (SAVE_PY or SAVE_HTML): - return - - dir_, fname = os.path.split(os_path) - - for word in DONT_SAVE: - if word.lower() in fname.lower(): - return - - source, tmp_name = fname, None - out_file_base, _ = os.path.splitext(fname) - - if RUN_NB_BEFORE_SAVE: - tmp_name = 'tmp_{}'.format(fname) - cmd = 'jupyter nbconvert --to notebook --execute --ExecutePreprocessor.timeout=30 --output {} {}'.format( - tmp_name, os_path) - _run_cmd(cmd, cwd=dir_) - source = tmp_name - - if SAVE_PY: - out_dir_py = os.path.join(os.path.dirname(dir_), 'py') - os.makedirs(out_dir_py, exist_ok=True) - cmd = 'jupyter nbconvert --to python --output-dir {} --output {}.py {}'.format( - out_dir_py, out_file_base, source) - _run_cmd(cmd, cwd=dir_) - - if SAVE_HTML: - if USE_TOGGLE_BTN_IN_HTML and RUN_NB_BEFORE_SAVE: - with open(os.path.join(dir_, source), 'r+') as tmp_source: - content = json.loads(tmp_source.read()) - content['cells'] = [TOGGLE_OUTPUT_BTN] + content.get( - 'cells', []) - tmp_source.seek(0) - tmp_source.write(json.dumps(content)) - tmp_source.truncate() - - out_dir_html = os.path.join(os.path.dirname(dir_), 'html') - os.makedirs(out_dir_html, exist_ok=True) - cmd = 'jupyter nbconvert --to html --output-dir {} --output {}.html {}'.format( - out_dir_html, out_file_base, source) - _run_cmd(cmd, cwd=dir_) - - if tmp_name: - tmp_file = os.path.join(dir_, tmp_name) - if os.path.exists(tmp_file): - os.remove(tmp_file) - -c.FileContentsManager.post_save_hook = post_save \ No newline at end of file From b62bc6a84fa96ec4a1026f7ab25e1f76f81a6b00 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Tue, 18 Apr 2023 09:48:25 +0300 Subject: [PATCH 32/60] Update year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index a798ba0..c77d8c1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 jerry-git +Copyright (c) 2023 jerry-git Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 3038adda0ff3b39bbc5e291ac4f4bfa89f76fb3f Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Tue, 18 Apr 2023 09:48:43 +0300 Subject: [PATCH 33/60] Add pre-commit config --- .pre-commit-config.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..a2296f5 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,13 @@ +repos: + - repo: local + hooks: + - id: clear-nb-output + name: clear-nb-output + files: \.ipynb$ + language: system + entry: jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace + - id: black + name: black + entry: black + language: system + files: \.(py|ipynb)$ From 906ba3626cce7e0cd768941d9b78401c7c14a473 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Tue, 18 Apr 2023 09:52:58 +0300 Subject: [PATCH 34/60] Add requirements file for dev deps --- dev-requirements.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 dev-requirements.txt diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 0000000..e3f4c05 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1,5 @@ +black[jupyter] +jupyter +nbval +pre-commit +pytest From c790fee8bf2697706acfc2fb159cb7101d667f54 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Tue, 18 Apr 2023 09:53:20 +0300 Subject: [PATCH 35/60] Add script for converting notebooks to html --- scripts/notebook_to_html.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 scripts/notebook_to_html.py diff --git a/scripts/notebook_to_html.py b/scripts/notebook_to_html.py new file mode 100644 index 0000000..d39f83a --- /dev/null +++ b/scripts/notebook_to_html.py @@ -0,0 +1,36 @@ +from pathlib import Path +import subprocess +import sys + + +def main(): + path = sys.argv[1] + if path.strip().lower() == "all": + convert_all_notebooks_to_html() + else: + convert_notebook_to_html(path) + + +def convert_all_notebooks_to_html(): + notebook_dir = Path(__file__).parent.parent / "notebooks" + for directory in ( + notebook_dir / "beginner" / "notebooks", + notebook_dir / "intermediate" / "notebooks", + ): + for notebook_path in directory.glob("*.ipynb"): + convert_notebook_to_html(notebook_path) + + +def convert_notebook_to_html(notebook_path): + path = Path(notebook_path) + if not path.exists(): + raise SystemExit(f"Invalid path {path}") + + output_dir = path.parent.parent / "html" + + cmd = f"jupyter nbconvert --to html --execute --ExecutePreprocessor.timeout=30 --output-dir {output_dir} {path.absolute()}" + subprocess.check_call(cmd.split()) + + +if __name__ == "__main__": + main() From 3c0ef8ac7d79d3680ba44845a24aee812e6871d4 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Wed, 19 Apr 2023 09:53:39 +0300 Subject: [PATCH 36/60] Ignore tmp.txt --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f9071de..bd511d4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ .pytest_cache* .tox* *pycache* -sync-*.sh \ No newline at end of file +sync-*.sh +tmp.txt From f47a4239c5bf969ba0948d7313f77a381834b646 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Wed, 19 Apr 2023 10:01:49 +0300 Subject: [PATCH 37/60] Ignore my_log.txt --- .gitignore | 1 + notebooks/beginner/notebooks/my_log.txt | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 notebooks/beginner/notebooks/my_log.txt diff --git a/.gitignore b/.gitignore index bd511d4..b7fdea9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ *pycache* sync-*.sh tmp.txt +my_log.txt diff --git a/notebooks/beginner/notebooks/my_log.txt b/notebooks/beginner/notebooks/my_log.txt deleted file mode 100644 index 1a87c50..0000000 --- a/notebooks/beginner/notebooks/my_log.txt +++ /dev/null @@ -1,2 +0,0 @@ -2018-09-21 23:17:54,486 | MyFileLogger | WARNING | Oops something is going to happen -2018-09-21 23:17:54,486 | MyFileLogger | ERROR | John Doe visits our place From fb4b0e6be9d266b9f63c4839fa4bf9aba36edc5b Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Wed, 19 Apr 2023 10:22:59 +0300 Subject: [PATCH 38/60] Add numbering and regenerate html Also fixed some ipytest things --- ...ercise.ipynb => 01_strings_exercise.ipynb} | 28 +- ...ercise.ipynb => 02_numbers_exercise.ipynb} | 3 +- ...e.ipynb => 03_conditionals_exercise.ipynb} | 14 +- ...exercise.ipynb => 04_lists_exercise.ipynb} | 21 +- ...e.ipynb => 05_dictionaries_exercise.ipynb} | 35 +- ...cise.ipynb => 06_for_loops_exercise.ipynb} | 17 +- ...cise.ipynb => 07_functions_exercise.ipynb} | 18 +- ...rcise.ipynb => 08_testing1_exercise.ipynb} | 5 +- ...xercise.ipynb => 09_recap1_exercise.ipynb} | 34 +- ...ercise.ipynb => 10_file_io_exercise.ipynb} | 14 +- ...ercise.ipynb => 11_classes_exercise.ipynb} | 16 +- ...ise.ipynb => 12_exceptions_exercise.ipynb} | 16 +- ...cise.ipynb => 14_debugging_exercise.ipynb} | 10 +- ...rcise.ipynb => 15_std_lib1_exercise.ipynb} | 9 +- ...rcise.ipynb => 16_testing2_exercise.ipynb} | 7 +- ...xercise.ipynb => 19_recap2_exercise.ipynb} | 53 +- notebooks/beginner/html/01_strings.html | 16216 +++++++++++++++ notebooks/beginner/html/02_numbers.html | 15613 +++++++++++++++ notebooks/beginner/html/03_conditionals.html | 15893 +++++++++++++++ notebooks/beginner/html/04_lists.html | 15917 +++++++++++++++ notebooks/beginner/html/05_dictionaries.html | 15843 +++++++++++++++ notebooks/beginner/html/06_for_loops.html | 15577 +++++++++++++++ notebooks/beginner/html/07_functions.html | 15675 +++++++++++++++ notebooks/beginner/html/08_testing1.html | 15376 +++++++++++++++ notebooks/beginner/html/10_file_io.html | 15414 +++++++++++++++ notebooks/beginner/html/11_classes.html | 15744 +++++++++++++++ notebooks/beginner/html/12_exceptions.html | 15380 +++++++++++++++ .../html/13_modules_and_packages.html | 15231 ++++++++++++++ notebooks/beginner/html/14_debugging.html | 15247 ++++++++++++++ notebooks/beginner/html/15_std_lib.html | 15973 +++++++++++++++ notebooks/beginner/html/16_testing2.html | 15487 +++++++++++++++ notebooks/beginner/html/17_venv.html | 15205 ++++++++++++++ .../beginner/html/18_project_structure.html | 15251 ++++++++++++++ notebooks/beginner/html/classes.html | 12335 ------------ notebooks/beginner/html/conditionals.html | 12397 ------------ notebooks/beginner/html/debugging.html | 11919 ----------- notebooks/beginner/html/dictionaries.html | 12410 ------------ notebooks/beginner/html/exceptions.html | 12025 ----------- notebooks/beginner/html/file_io.html | 12053 ------------ notebooks/beginner/html/for_loops.html | 12192 ------------ notebooks/beginner/html/functions.html | 12274 ------------ notebooks/beginner/html/lists.html | 12472 ------------ .../beginner/html/modules_and_packages.html | 11903 ----------- notebooks/beginner/html/numbers.html | 12216 ------------ .../beginner/html/project_structure.html | 11925 ----------- notebooks/beginner/html/std_lib.html | 12517 ------------ notebooks/beginner/html/strings.html | 12711 ------------ notebooks/beginner/html/testing1.html | 12007 ----------- notebooks/beginner/html/testing2.html | 12097 ------------ notebooks/beginner/html/venv.html | 11874 ----------- .../{strings.ipynb => 01_strings.ipynb} | 70 +- .../{numbers.ipynb => 02_numbers.ipynb} | 40 +- ...nditionals.ipynb => 03_conditionals.ipynb} | 115 +- .../notebooks/{lists.ipynb => 04_lists.ipynb} | 60 +- ...ctionaries.ipynb => 05_dictionaries.ipynb} | 92 +- .../{for_loops.ipynb => 06_for_loops.ipynb} | 10 +- .../{functions.ipynb => 07_functions.ipynb} | 48 +- .../{testing1.ipynb => 08_testing1.ipynb} | 14 +- .../{file_io.ipynb => 10_file_io.ipynb} | 34 +- .../{classes.ipynb => 11_classes.ipynb} | 90 +- .../{exceptions.ipynb => 12_exceptions.ipynb} | 38 +- ...es.ipynb => 13_modules_and_packages.ipynb} | 0 .../{debugging.ipynb => 14_debugging.ipynb} | 8 +- .../{std_lib.ipynb => 15_std_lib.ipynb} | 122 +- .../{testing2.ipynb => 16_testing2.ipynb} | 42 +- .../notebooks/{venv.ipynb => 17_venv.ipynb} | 0 ...cture.ipynb => 18_project_structure.ipynb} | 4 +- ...rcise.ipynb => 01_std_lib2_exercise.ipynb} | 56 +- ...ynb => 05_idiomatic_python_exercise.ipynb} | 66 +- .../intermediate/html/01_best_practices.html | 15945 +++++++++++++++ .../intermediate/html/01_idiomatic_loops.html | 16013 +++++++++++++++ .../intermediate/html/01_pytest_fixtures.html | 15902 +++++++++++++++ notebooks/intermediate/html/01_std_lib2.html | 15788 +++++++++++++++ .../intermediate/html/02_idiomatic_dicts.html | 15879 +++++++++++++++ .../intermediate/html/03_idiomatic_misc1.html | 16410 ++++++++++++++++ .../intermediate/html/04_idiomatic_misc2.html | 16268 +++++++++++++++ .../intermediate/html/best_practices.html | 12473 ------------ .../intermediate/html/idiomatic_dicts.html | 12431 ------------ .../intermediate/html/idiomatic_loops.html | 12544 ------------ .../intermediate/html/idiomatic_misc1.html | 12875 ------------ .../intermediate/html/idiomatic_misc2.html | 12761 ------------ .../intermediate/html/pytest_fixtures.html | 12542 ------------ notebooks/intermediate/html/std_lib2.html | 12366 ------------ ...ractices.ipynb => 01_best_practices.ipynb} | 0 ...c_loops.ipynb => 01_idiomatic_loops.ipynb} | 20 +- ...ixtures.ipynb => 01_pytest_fixtures.ipynb} | 95 +- .../{std_lib2.ipynb => 01_std_lib2.ipynb} | 89 +- ...c_dicts.ipynb => 02_idiomatic_dicts.ipynb} | 40 +- ...c_misc1.ipynb => 03_idiomatic_misc1.ipynb} | 107 +- ...c_misc2.ipynb => 04_idiomatic_misc2.ipynb} | 121 +- 90 files changed, 378126 insertions(+), 296121 deletions(-) rename notebooks/beginner/exercises/{strings_exercise.ipynb => 01_strings_exercise.ipynb} (82%) rename notebooks/beginner/exercises/{numbers_exercise.ipynb => 02_numbers_exercise.ipynb} (97%) rename notebooks/beginner/exercises/{conditionals_exercise.ipynb => 03_conditionals_exercise.ipynb} (82%) rename notebooks/beginner/exercises/{lists_exercise.ipynb => 04_lists_exercise.ipynb} (83%) rename notebooks/beginner/exercises/{dictionaries_exercise.ipynb => 05_dictionaries_exercise.ipynb} (71%) rename notebooks/beginner/exercises/{for_loops_exercise.ipynb => 06_for_loops_exercise.ipynb} (85%) rename notebooks/beginner/exercises/{functions_exercise.ipynb => 07_functions_exercise.ipynb} (83%) rename notebooks/beginner/exercises/{testing1_exercise.ipynb => 08_testing1_exercise.ipynb} (91%) rename notebooks/beginner/exercises/{recap1_exercise.ipynb => 09_recap1_exercise.ipynb} (79%) rename notebooks/beginner/exercises/{file_io_exercise.ipynb => 10_file_io_exercise.ipynb} (85%) rename notebooks/beginner/exercises/{classes_exercise.ipynb => 11_classes_exercise.ipynb} (90%) rename notebooks/beginner/exercises/{exceptions_exercise.ipynb => 12_exceptions_exercise.ipynb} (88%) rename notebooks/beginner/exercises/{debugging_exercise.ipynb => 14_debugging_exercise.ipynb} (87%) rename notebooks/beginner/exercises/{std_lib1_exercise.ipynb => 15_std_lib1_exercise.ipynb} (90%) rename notebooks/beginner/exercises/{testing2_exercise.ipynb => 16_testing2_exercise.ipynb} (96%) rename notebooks/beginner/exercises/{recap2_exercise.ipynb => 19_recap2_exercise.ipynb} (80%) create mode 100644 notebooks/beginner/html/01_strings.html create mode 100644 notebooks/beginner/html/02_numbers.html create mode 100644 notebooks/beginner/html/03_conditionals.html create mode 100644 notebooks/beginner/html/04_lists.html create mode 100644 notebooks/beginner/html/05_dictionaries.html create mode 100644 notebooks/beginner/html/06_for_loops.html create mode 100644 notebooks/beginner/html/07_functions.html create mode 100644 notebooks/beginner/html/08_testing1.html create mode 100644 notebooks/beginner/html/10_file_io.html create mode 100644 notebooks/beginner/html/11_classes.html create mode 100644 notebooks/beginner/html/12_exceptions.html create mode 100644 notebooks/beginner/html/13_modules_and_packages.html create mode 100644 notebooks/beginner/html/14_debugging.html create mode 100644 notebooks/beginner/html/15_std_lib.html create mode 100644 notebooks/beginner/html/16_testing2.html create mode 100644 notebooks/beginner/html/17_venv.html create mode 100644 notebooks/beginner/html/18_project_structure.html delete mode 100644 notebooks/beginner/html/classes.html delete mode 100644 notebooks/beginner/html/conditionals.html delete mode 100644 notebooks/beginner/html/debugging.html delete mode 100644 notebooks/beginner/html/dictionaries.html delete mode 100644 notebooks/beginner/html/exceptions.html delete mode 100644 notebooks/beginner/html/file_io.html delete mode 100644 notebooks/beginner/html/for_loops.html delete mode 100644 notebooks/beginner/html/functions.html delete mode 100644 notebooks/beginner/html/lists.html delete mode 100644 notebooks/beginner/html/modules_and_packages.html delete mode 100644 notebooks/beginner/html/numbers.html delete mode 100644 notebooks/beginner/html/project_structure.html delete mode 100644 notebooks/beginner/html/std_lib.html delete mode 100644 notebooks/beginner/html/strings.html delete mode 100644 notebooks/beginner/html/testing1.html delete mode 100644 notebooks/beginner/html/testing2.html delete mode 100644 notebooks/beginner/html/venv.html rename notebooks/beginner/notebooks/{strings.ipynb => 01_strings.ipynb} (75%) rename notebooks/beginner/notebooks/{numbers.ipynb => 02_numbers.ipynb} (82%) rename notebooks/beginner/notebooks/{conditionals.ipynb => 03_conditionals.ipynb} (58%) rename notebooks/beginner/notebooks/{lists.ipynb => 04_lists.ipynb} (75%) rename notebooks/beginner/notebooks/{dictionaries.ipynb => 05_dictionaries.ipynb} (66%) rename notebooks/beginner/notebooks/{for_loops.ipynb => 06_for_loops.ipynb} (91%) rename notebooks/beginner/notebooks/{functions.ipynb => 07_functions.ipynb} (86%) rename notebooks/beginner/notebooks/{testing1.ipynb => 08_testing1.ipynb} (95%) rename notebooks/beginner/notebooks/{file_io.ipynb => 10_file_io.ipynb} (76%) rename notebooks/beginner/notebooks/{classes.ipynb => 11_classes.ipynb} (82%) rename notebooks/beginner/notebooks/{exceptions.ipynb => 12_exceptions.ipynb} (82%) rename notebooks/beginner/notebooks/{modules_and_packages.ipynb => 13_modules_and_packages.ipynb} (100%) rename notebooks/beginner/notebooks/{debugging.ipynb => 14_debugging.ipynb} (95%) rename notebooks/beginner/notebooks/{std_lib.ipynb => 15_std_lib.ipynb} (70%) rename notebooks/beginner/notebooks/{testing2.ipynb => 16_testing2.ipynb} (88%) rename notebooks/beginner/notebooks/{venv.ipynb => 17_venv.ipynb} (100%) rename notebooks/beginner/notebooks/{project_structure.ipynb => 18_project_structure.ipynb} (96%) rename notebooks/intermediate/exercises/{std_lib2_exercise.ipynb => 01_std_lib2_exercise.ipynb} (82%) rename notebooks/intermediate/exercises/{idiomatic_python_exercise.ipynb => 05_idiomatic_python_exercise.ipynb} (87%) create mode 100644 notebooks/intermediate/html/01_best_practices.html create mode 100644 notebooks/intermediate/html/01_idiomatic_loops.html create mode 100644 notebooks/intermediate/html/01_pytest_fixtures.html create mode 100644 notebooks/intermediate/html/01_std_lib2.html create mode 100644 notebooks/intermediate/html/02_idiomatic_dicts.html create mode 100644 notebooks/intermediate/html/03_idiomatic_misc1.html create mode 100644 notebooks/intermediate/html/04_idiomatic_misc2.html delete mode 100644 notebooks/intermediate/html/best_practices.html delete mode 100644 notebooks/intermediate/html/idiomatic_dicts.html delete mode 100644 notebooks/intermediate/html/idiomatic_loops.html delete mode 100644 notebooks/intermediate/html/idiomatic_misc1.html delete mode 100644 notebooks/intermediate/html/idiomatic_misc2.html delete mode 100644 notebooks/intermediate/html/pytest_fixtures.html delete mode 100644 notebooks/intermediate/html/std_lib2.html rename notebooks/intermediate/notebooks/{best_practices.ipynb => 01_best_practices.ipynb} (100%) rename notebooks/intermediate/notebooks/{idiomatic_loops.ipynb => 01_idiomatic_loops.ipynb} (94%) rename notebooks/intermediate/notebooks/{pytest_fixtures.ipynb => 01_pytest_fixtures.ipynb} (82%) rename notebooks/intermediate/notebooks/{std_lib2.ipynb => 01_std_lib2.ipynb} (79%) rename notebooks/intermediate/notebooks/{idiomatic_dicts.ipynb => 02_idiomatic_dicts.ipynb} (87%) rename notebooks/intermediate/notebooks/{idiomatic_misc1.ipynb => 03_idiomatic_misc1.ipynb} (82%) rename notebooks/intermediate/notebooks/{idiomatic_misc2.ipynb => 04_idiomatic_misc2.ipynb} (81%) diff --git a/notebooks/beginner/exercises/strings_exercise.ipynb b/notebooks/beginner/exercises/01_strings_exercise.ipynb similarity index 82% rename from notebooks/beginner/exercises/strings_exercise.ipynb rename to notebooks/beginner/exercises/01_strings_exercise.ipynb index 38aee8b..66a97be 100644 --- a/notebooks/beginner/exercises/strings_exercise.ipynb +++ b/notebooks/beginner/exercises/01_strings_exercise.ipynb @@ -14,7 +14,7 @@ "metadata": {}, "outputs": [], "source": [ - "original = ' Python strings are COOL! '\n", + "original = \" Python strings are COOL! \"\n", "lower_cased = original._____\n", "stripped = ____.strip()\n", "stripped_lower_cased = original._____._____" @@ -35,9 +35,9 @@ }, "outputs": [], "source": [ - "assert lower_cased == ' python strings are cool! '\n", - "assert stripped == 'Python strings are COOL!'\n", - "assert stripped_lower_cased == 'python strings are cool!'" + "assert lower_cased == \" python strings are cool! \"\n", + "assert stripped == \"Python strings are COOL!\"\n", + "assert stripped_lower_cased == \"python strings are cool!\"" ] }, { @@ -56,7 +56,7 @@ }, "outputs": [], "source": [ - "ugly = ' tiTle of MY new Book\\n\\n'" + "ugly = \" tiTle of MY new Book\\n\\n\"" ] }, { @@ -66,7 +66,7 @@ "outputs": [], "source": [ "# Your implementation:\n", - "pretty = 'TODO'" + "pretty = \"TODO\"" ] }, { @@ -84,8 +84,8 @@ }, "outputs": [], "source": [ - "print('pretty: {}'.format(pretty))\n", - "assert pretty == 'Title Of My New Book'" + "print(\"pretty: {}\".format(pretty))\n", + "assert pretty == \"Title Of My New Book\"" ] }, { @@ -104,9 +104,9 @@ }, "outputs": [], "source": [ - "verb = 'is'\n", - "language = 'Python'\n", - "punctuation = '!'" + "verb = \"is\"\n", + "language = \"Python\"\n", + "punctuation = \"!\"" ] }, { @@ -116,7 +116,7 @@ "outputs": [], "source": [ "# Your implementation:\n", - "sentence = 'TODO'" + "sentence = \"TODO\"" ] }, { @@ -127,8 +127,8 @@ }, "outputs": [], "source": [ - "print('sentence: {}'.format(sentence))\n", - "assert sentence == 'Learning Python is fun!'" + "print(\"sentence: {}\".format(sentence))\n", + "assert sentence == \"Learning Python is fun!\"" ] } ], diff --git a/notebooks/beginner/exercises/numbers_exercise.ipynb b/notebooks/beginner/exercises/02_numbers_exercise.ipynb similarity index 97% rename from notebooks/beginner/exercises/numbers_exercise.ipynb rename to notebooks/beginner/exercises/02_numbers_exercise.ipynb index 9b25a95..262a438 100644 --- a/notebooks/beginner/exercises/numbers_exercise.ipynb +++ b/notebooks/beginner/exercises/02_numbers_exercise.ipynb @@ -43,7 +43,6 @@ }, "outputs": [], "source": [ - "\n", "assert result == 50" ] }, @@ -57,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ diff --git a/notebooks/beginner/exercises/conditionals_exercise.ipynb b/notebooks/beginner/exercises/03_conditionals_exercise.ipynb similarity index 82% rename from notebooks/beginner/exercises/conditionals_exercise.ipynb rename to notebooks/beginner/exercises/03_conditionals_exercise.ipynb index e0e045c..061c2c1 100644 --- a/notebooks/beginner/exercises/conditionals_exercise.ipynb +++ b/notebooks/beginner/exercises/03_conditionals_exercise.ipynb @@ -16,7 +16,7 @@ }, "outputs": [], "source": [ - "name = 'John Doe'" + "name = \"John Doe\"" ] }, { @@ -27,19 +27,19 @@ "source": [ "if ____:\n", " print('Name \"{}\" is more than 20 chars long'.format(name))\n", - " length_description = 'long'\n", + " length_description = \"long\"\n", "elif ____:\n", " print('Name \"{}\" is more than 15 chars long'.format(name))\n", - " length_description = 'semi long'\n", + " length_description = \"semi long\"\n", "elif ____:\n", " print('Name \"{}\" is more than 10 chars long'.format(name))\n", - " length_description = 'semi long'\n", + " length_description = \"semi long\"\n", "elif ____:\n", " print('Name \"{}\" is 8, 9 or 10 chars long'.format(name))\n", - " length_description = 'semi short'\n", + " length_description = \"semi short\"\n", "else:\n", " print('Name \"{}\" is a short name'.format(name))\n", - " length_description = 'short'" + " length_description = \"short\"" ] }, { @@ -50,7 +50,7 @@ }, "outputs": [], "source": [ - "assert length_description == 'semi short'" + "assert length_description == \"semi short\"" ] } ], diff --git a/notebooks/beginner/exercises/lists_exercise.ipynb b/notebooks/beginner/exercises/04_lists_exercise.ipynb similarity index 83% rename from notebooks/beginner/exercises/lists_exercise.ipynb rename to notebooks/beginner/exercises/04_lists_exercise.ipynb index 9c7645b..ea284b6 100644 --- a/notebooks/beginner/exercises/lists_exercise.ipynb +++ b/notebooks/beginner/exercises/04_lists_exercise.ipynb @@ -18,15 +18,15 @@ "my_list = ____\n", "\n", "# Let's add some values\n", - "my_list.____('Python')\n", - "my_list.____('is ok')\n", - "my_list.____('sometimes')\n", + "my_list.____(\"Python\")\n", + "my_list.____(\"is ok\")\n", + "my_list.____(\"sometimes\")\n", "\n", "# Let's remove 'sometimes'\n", - "my_list.____('sometimes')\n", + "my_list.____(\"sometimes\")\n", "\n", "# Let's change the second item\n", - "my_list[____] = 'is neat'" + "my_list[____] = \"is neat\"" ] }, { @@ -38,7 +38,7 @@ "outputs": [], "source": [ "# Let's verify that it's correct\n", - "assert my_list == ['Python', 'is neat']" + "assert my_list == [\"Python\", \"is neat\"]" ] }, { @@ -56,7 +56,7 @@ }, "outputs": [], "source": [ - "original = ['I', 'am', 'learning', 'hacking', 'in']" + "original = [\"I\", \"am\", \"learning\", \"hacking\", \"in\"]" ] }, { @@ -77,8 +77,8 @@ }, "outputs": [], "source": [ - "assert original == ['I', 'am', 'learning', 'hacking', 'in']\n", - "assert modified == ['I', 'am', 'learning', 'lists', 'in', 'Python']" + "assert original == [\"I\", \"am\", \"learning\", \"hacking\", \"in\"]\n", + "assert modified == [\"I\", \"am\", \"learning\", \"lists\", \"in\", \"Python\"]" ] }, { @@ -115,8 +115,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "editable": false, - "scrolled": true + "editable": false }, "outputs": [], "source": [ diff --git a/notebooks/beginner/exercises/dictionaries_exercise.ipynb b/notebooks/beginner/exercises/05_dictionaries_exercise.ipynb similarity index 71% rename from notebooks/beginner/exercises/dictionaries_exercise.ipynb rename to notebooks/beginner/exercises/05_dictionaries_exercise.ipynb index 06b3b07..76cb804 100644 --- a/notebooks/beginner/exercises/dictionaries_exercise.ipynb +++ b/notebooks/beginner/exercises/05_dictionaries_exercise.ipynb @@ -16,10 +16,10 @@ }, "outputs": [], "source": [ - "first_name = 'John'\n", - "last_name = 'Doe'\n", - "favorite_hobby = 'Python'\n", - "sports_hobby = 'gym'\n", + "first_name = \"John\"\n", + "last_name = \"Doe\"\n", + "favorite_hobby = \"Python\"\n", + "sports_hobby = \"gym\"\n", "age = 82" ] }, @@ -41,11 +41,7 @@ }, "outputs": [], "source": [ - "assert my_dict == {\n", - " 'name': 'John Doe',\n", - " 'age': 82,\n", - " 'hobbies': ['Python', 'gym']\n", - " }" + "assert my_dict == {\"name\": \"John Doe\", \"age\": 82, \"hobbies\": [\"Python\", \"gym\"]}" ] }, { @@ -64,10 +60,10 @@ }, "outputs": [], "source": [ - "dict1 = dict(key1='This is not that hard', key2='Python is still cool')\n", - "dict2 = {'key1': 123, 'special_key': 'secret'}\n", - "# This is also a away to initialize a dict (list of tuples) \n", - "dict3 = dict([('key2', 456), ('keyX', 'X')])" + "dict1 = dict(key1=\"This is not that hard\", key2=\"Python is still cool\")\n", + "dict2 = {\"key1\": 123, \"special_key\": \"secret\"}\n", + "# This is also a away to initialize a dict (list of tuples)\n", + "dict3 = dict([(\"key2\", 456), (\"keyX\", \"X\")])" ] }, { @@ -89,16 +85,13 @@ }, "outputs": [], "source": [ - "assert my_dict == {'key1': 123, 'key2': 456, 'keyX': 'X'}\n", - "assert special_value == 'secret'\n", + "assert my_dict == {\"key1\": 123, \"key2\": 456, \"keyX\": \"X\"}\n", + "assert special_value == \"secret\"\n", "\n", "# Let's check that the originals are untouched\n", - "assert dict1 == {\n", - " 'key1': 'This is not that hard',\n", - " 'key2': 'Python is still cool'\n", - " }\n", - "assert dict2 == {'key1': 123, 'special_key': 'secret'}\n", - "assert dict3 == {'key2': 456, 'keyX': 'X'}" + "assert dict1 == {\"key1\": \"This is not that hard\", \"key2\": \"Python is still cool\"}\n", + "assert dict2 == {\"key1\": 123, \"special_key\": \"secret\"}\n", + "assert dict3 == {\"key2\": 456, \"keyX\": \"X\"}" ] } ], diff --git a/notebooks/beginner/exercises/for_loops_exercise.ipynb b/notebooks/beginner/exercises/06_for_loops_exercise.ipynb similarity index 85% rename from notebooks/beginner/exercises/for_loops_exercise.ipynb rename to notebooks/beginner/exercises/06_for_loops_exercise.ipynb index eae36c6..e429308 100644 --- a/notebooks/beginner/exercises/for_loops_exercise.ipynb +++ b/notebooks/beginner/exercises/06_for_loops_exercise.ipynb @@ -14,7 +14,7 @@ "metadata": {}, "outputs": [], "source": [ - "words = ['PYTHON', 'JOHN', 'chEEse', 'hAm', 'DOE', '123']\n", + "words = [\"PYTHON\", \"JOHN\", \"chEEse\", \"hAm\", \"DOE\", \"123\"]\n", "upper_case_words = []\n", "\n", "for ____ in words:\n", @@ -30,7 +30,7 @@ }, "outputs": [], "source": [ - "assert upper_case_words == ['PYTHON', 'JOHN', 'DOE']" + "assert upper_case_words == [\"PYTHON\", \"JOHN\", \"DOE\"]" ] }, { @@ -49,7 +49,7 @@ }, "outputs": [], "source": [ - "magic_dict = dict(val1=44, val2='secret value', val3=55.0, val4=1)" + "magic_dict = dict(val1=44, val2=\"secret value\", val3=55.0, val4=1)" ] }, { @@ -114,7 +114,16 @@ }, "outputs": [], "source": [ - "assert my_list == ['odd', 'odd', 'even', 'even', 'odd', 'five even', 'five even', 'five odd']" + "assert my_list == [\n", + " \"odd\",\n", + " \"odd\",\n", + " \"even\",\n", + " \"even\",\n", + " \"odd\",\n", + " \"five even\",\n", + " \"five even\",\n", + " \"five odd\",\n", + "]" ] } ], diff --git a/notebooks/beginner/exercises/functions_exercise.ipynb b/notebooks/beginner/exercises/07_functions_exercise.ipynb similarity index 83% rename from notebooks/beginner/exercises/functions_exercise.ipynb rename to notebooks/beginner/exercises/07_functions_exercise.ipynb index 64f891e..6682f56 100644 --- a/notebooks/beginner/exercises/functions_exercise.ipynb +++ b/notebooks/beginner/exercises/07_functions_exercise.ipynb @@ -51,7 +51,7 @@ }, "outputs": [], "source": [ - "WANTED_PEOPLE = ['John Doe', 'Clint Eastwood', 'Chuck Norris']" + "WANTED_PEOPLE = [\"John Doe\", \"Clint Eastwood\", \"Chuck Norris\"]" ] }, { @@ -71,13 +71,13 @@ }, "outputs": [], "source": [ - "people_to_check1 = ['Donald Duck', 'Clint Eastwood', 'John Doe', 'Barack Obama']\n", + "people_to_check1 = [\"Donald Duck\", \"Clint Eastwood\", \"John Doe\", \"Barack Obama\"]\n", "wanted1 = find_wanted_people(people_to_check1)\n", "assert len(wanted1) == 2\n", - "assert 'John Doe' in wanted1\n", - "assert 'Clint Eastwood'in wanted1\n", + "assert \"John Doe\" in wanted1\n", + "assert \"Clint Eastwood\" in wanted1\n", "\n", - "people_to_check2 = ['Donald Duck', 'Mickey Mouse', 'Zorro', 'Superman', 'Robin Hood']\n", + "people_to_check2 = [\"Donald Duck\", \"Mickey Mouse\", \"Zorro\", \"Superman\", \"Robin Hood\"]\n", "wanted2 = find_wanted_people(people_to_check2)\n", "assert wanted2 == []" ] @@ -107,10 +107,10 @@ }, "outputs": [], "source": [ - "assert average_length_of_words('only four lett erwo rdss') == 4\n", - "assert average_length_of_words('one two three') == 3.7\n", - "assert average_length_of_words('one two three four') == 3.8\n", - "assert average_length_of_words('') == 0" + "assert average_length_of_words(\"only four lett erwo rdss\") == 4\n", + "assert average_length_of_words(\"one two three\") == 3.7\n", + "assert average_length_of_words(\"one two three four\") == 3.8\n", + "assert average_length_of_words(\"\") == 0" ] } ], diff --git a/notebooks/beginner/exercises/testing1_exercise.ipynb b/notebooks/beginner/exercises/08_testing1_exercise.ipynb similarity index 91% rename from notebooks/beginner/exercises/testing1_exercise.ipynb rename to notebooks/beginner/exercises/08_testing1_exercise.ipynb index f202c21..ea7219c 100644 --- a/notebooks/beginner/exercises/testing1_exercise.ipynb +++ b/notebooks/beginner/exercises/08_testing1_exercise.ipynb @@ -8,13 +8,14 @@ "source": [ "# Required boilerplate\n", "import sys\n", + "\n", "!{sys.executable} -m pip install pytest\n", "!{sys.executable} -m pip install ipytest\n", "\n", "import ipytest.magics\n", "import pytest\n", "\n", - "__file__ = 'testing1_exercise.ipynb'" + "__file__ = \"testing1_exercise.ipynb\"" ] }, { @@ -34,7 +35,7 @@ "outputs": [], "source": [ "def get_divisible_by_five(numbers):\n", - " '''Returns a list of numbers which are divisible by five in the list got as an argument'''\n", + " \"\"\"Returns a list of numbers which are divisible by five in the list got as an argument\"\"\"\n", " result = []\n", " for num in numbers:\n", " if not num % 5:\n", diff --git a/notebooks/beginner/exercises/recap1_exercise.ipynb b/notebooks/beginner/exercises/09_recap1_exercise.ipynb similarity index 79% rename from notebooks/beginner/exercises/recap1_exercise.ipynb rename to notebooks/beginner/exercises/09_recap1_exercise.ipynb index ea0d342..1212ccb 100644 --- a/notebooks/beginner/exercises/recap1_exercise.ipynb +++ b/notebooks/beginner/exercises/09_recap1_exercise.ipynb @@ -16,7 +16,7 @@ }, "outputs": [], "source": [ - "VOWELS = ['a', 'e', 'i', 'o', 'u']" + "VOWELS = [\"a\", \"e\", \"i\", \"o\", \"u\"]" ] }, { @@ -36,8 +36,8 @@ }, "outputs": [], "source": [ - "assert super_vowels('hi wassup!') == 'hI wAssUp!'\n", - "assert super_vowels('HOw aRE You?') == 'hOw ArE yOU?'" + "assert super_vowels(\"hi wassup!\") == \"hI wAssUp!\"\n", + "assert super_vowels(\"HOw aRE You?\") == \"hOw ArE yOU?\"" ] }, { @@ -65,25 +65,19 @@ }, "outputs": [], "source": [ - "board_of_5 = (\n", - "' * * \\n'\n", - "'* * *\\n'\n", - "' * * \\n'\n", - "'* * *\\n'\n", - "' * * \\n'\n", - ")\n", + "board_of_5 = \" * * \\n\" \"* * *\\n\" \" * * \\n\" \"* * *\\n\" \" * * \\n\"\n", "\n", "board_of_10 = (\n", - "' * * * * *\\n'\n", - "'* * * * * \\n'\n", - "' * * * * *\\n'\n", - "'* * * * * \\n'\n", - "' * * * * *\\n'\n", - "'* * * * * \\n'\n", - "' * * * * *\\n'\n", - "'* * * * * \\n'\n", - "' * * * * *\\n'\n", - "'* * * * * \\n'\n", + " \" * * * * *\\n\"\n", + " \"* * * * * \\n\"\n", + " \" * * * * *\\n\"\n", + " \"* * * * * \\n\"\n", + " \" * * * * *\\n\"\n", + " \"* * * * * \\n\"\n", + " \" * * * * *\\n\"\n", + " \"* * * * * \\n\"\n", + " \" * * * * *\\n\"\n", + " \"* * * * * \\n\"\n", ")\n", "\n", "assert get_playing_board(5) == board_of_5\n", diff --git a/notebooks/beginner/exercises/file_io_exercise.ipynb b/notebooks/beginner/exercises/10_file_io_exercise.ipynb similarity index 85% rename from notebooks/beginner/exercises/file_io_exercise.ipynb rename to notebooks/beginner/exercises/10_file_io_exercise.ipynb index 40ea966..2fcb284 100644 --- a/notebooks/beginner/exercises/file_io_exercise.ipynb +++ b/notebooks/beginner/exercises/10_file_io_exercise.ipynb @@ -14,7 +14,7 @@ "\n", "# Constants for the exercises:\n", "WORKING_DIR = os.getcwd()\n", - "DATA_DIR = os.path.join(os.path.dirname(WORKING_DIR), 'data')" + "DATA_DIR = os.path.join(os.path.dirname(WORKING_DIR), \"data\")" ] }, { @@ -35,7 +35,7 @@ " sum_ = 0 # A common way to use variable names that collide with built-in/keyword words is to add underscore\n", " with ____(input_file, ____) as ____:\n", " for line in ____:\n", - " ____ = line.strip() # Remove potential white space \n", + " ____ = line.strip() # Remove potential white space\n", " ____ += float(____)\n", " return ____" ] @@ -48,7 +48,7 @@ }, "outputs": [], "source": [ - "in_file = os.path.join(DATA_DIR, 'numbers.txt')\n", + "in_file = os.path.join(DATA_DIR, \"numbers.txt\")\n", "assert sum_numbers_in_file(in_file) == 189.5" ] }, @@ -77,13 +77,13 @@ }, "outputs": [], "source": [ - "in_file1 = os.path.join(DATA_DIR, 'simple_file.txt')\n", - "in_file2 = os.path.join(DATA_DIR, 'simple_file_with_empty_lines.txt')\n", + "in_file1 = os.path.join(DATA_DIR, \"simple_file.txt\")\n", + "in_file2 = os.path.join(DATA_DIR, \"simple_file_with_empty_lines.txt\")\n", "\n", - "expected_file_1 = ['First', 'Second', 'Third', 'And']\n", + "expected_file_1 = [\"First\", \"Second\", \"Third\", \"And\"]\n", "assert find_first_words(in_file1) == expected_file_1\n", "\n", - "expected_file_2 = ['The', '', 'First', 'nonsense', '', 'Then']\n", + "expected_file_2 = [\"The\", \"\", \"First\", \"nonsense\", \"\", \"Then\"]\n", "assert find_first_words(in_file2) == expected_file_2" ] } diff --git a/notebooks/beginner/exercises/classes_exercise.ipynb b/notebooks/beginner/exercises/11_classes_exercise.ipynb similarity index 90% rename from notebooks/beginner/exercises/classes_exercise.ipynb rename to notebooks/beginner/exercises/11_classes_exercise.ipynb index 5e60c49..2313b1c 100644 --- a/notebooks/beginner/exercises/classes_exercise.ipynb +++ b/notebooks/beginner/exercises/11_classes_exercise.ipynb @@ -18,10 +18,10 @@ " def __init__(self, var1, ____):\n", " self.____ = var1\n", " self.____ = _____\n", - " \n", + "\n", " def calculate_power(self):\n", - " return self.____ ** ____.____\n", - " \n", + " return self.____**____.____\n", + "\n", " def calculate_sum(____, var3):\n", " return ____.____ + ____.____ + var3" ] @@ -80,16 +80,16 @@ }, "outputs": [], "source": [ - "assert StringManipulator.__doc__ == 'Docstring of StringManipulator'\n", - "assert StringManipulator.category == 'Manipulator'\n", + "assert StringManipulator.__doc__ == \"Docstring of StringManipulator\"\n", + "assert StringManipulator.category == \"Manipulator\"\n", "\n", - "str_manip = StringManipulator('cOOL pyThON')\n", + "str_manip = StringManipulator(\"cOOL pyThON\")\n", "\n", "str_manip.reverse_words()\n", - "assert str_manip.get_manipulated() == 'pyThON cOOL'\n", + "assert str_manip.get_manipulated() == \"pyThON cOOL\"\n", "\n", "str_manip.make_title()\n", - "assert str_manip.get_manipulated() == 'Python Cool'" + "assert str_manip.get_manipulated() == \"Python Cool\"" ] }, { diff --git a/notebooks/beginner/exercises/exceptions_exercise.ipynb b/notebooks/beginner/exercises/12_exceptions_exercise.ipynb similarity index 88% rename from notebooks/beginner/exercises/exceptions_exercise.ipynb rename to notebooks/beginner/exercises/12_exceptions_exercise.ipynb index 61278cf..68e2e8f 100644 --- a/notebooks/beginner/exercises/exceptions_exercise.ipynb +++ b/notebooks/beginner/exercises/12_exceptions_exercise.ipynb @@ -34,10 +34,10 @@ "outputs": [], "source": [ "list1 = [1, 2, 3]\n", - "list2 = ['1', 2.5, '3.0']\n", - "list3 = ['', '1']\n", + "list2 = [\"1\", 2.5, \"3.0\"]\n", + "list3 = [\"\", \"1\"]\n", "list4 = []\n", - "list5 = ['John', 'Doe', 'was', 'here']\n", + "list5 = [\"John\", \"Doe\", \"was\", \"here\"]\n", "nasty_list = [KeyError(), [], dict()]\n", "\n", "assert sum_of_list(list1) == 6\n", @@ -74,24 +74,24 @@ "outputs": [], "source": [ "# These should not raise\n", - "verify_short_string('short') \n", - "verify_short_string('10 chars')\n", + "verify_short_string(\"short\")\n", + "verify_short_string(\"10 chars\")\n", "\n", "# This should raise\n", "try:\n", - " verify_short_string('this is long')\n", + " verify_short_string(\"this is long\")\n", "except TooLongString as e:\n", " # This is ok\n", " pass\n", "else:\n", " # This means that there was no exception\n", - " assert False " + " assert False" ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, diff --git a/notebooks/beginner/exercises/debugging_exercise.ipynb b/notebooks/beginner/exercises/14_debugging_exercise.ipynb similarity index 87% rename from notebooks/beginner/exercises/debugging_exercise.ipynb rename to notebooks/beginner/exercises/14_debugging_exercise.ipynb index d19bc83..6bfbf4e 100644 --- a/notebooks/beginner/exercises/debugging_exercise.ipynb +++ b/notebooks/beginner/exercises/14_debugging_exercise.ipynb @@ -19,7 +19,7 @@ "def stripped_reversed_lowercase(original):\n", " # Set a breakpoint here and start debugging\n", " stripped = original.lstrip()\n", - " reversed = ' '.join(reversed(stripped))\n", + " reversed = \" \".join(reversed(stripped))\n", " reversed.lower()\n", " return reversed" ] @@ -33,15 +33,15 @@ "outputs": [], "source": [ "# Let's verify it works\n", - "original = ' \\n Original String '\n", + "original = \" \\n Original String \"\n", "result = stripped_reversed_lowercase(original)\n", - "assert result == 'gnirts lanigiro'" + "assert result == \"gnirts lanigiro\"" ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -55,7 +55,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.10.3" } }, "nbformat": 4, diff --git a/notebooks/beginner/exercises/std_lib1_exercise.ipynb b/notebooks/beginner/exercises/15_std_lib1_exercise.ipynb similarity index 90% rename from notebooks/beginner/exercises/std_lib1_exercise.ipynb rename to notebooks/beginner/exercises/15_std_lib1_exercise.ipynb index 5e5eedf..4897a12 100644 --- a/notebooks/beginner/exercises/std_lib1_exercise.ipynb +++ b/notebooks/beginner/exercises/15_std_lib1_exercise.ipynb @@ -8,6 +8,7 @@ "source": [ "# pytz will be needed in the exercise\n", "import sys\n", + "\n", "!{sys.executable} -m pip install pytz" ] }, @@ -85,11 +86,11 @@ }, "outputs": [], "source": [ - "assert utc_dt.isoformat() == '2000-01-01T10:00:00+00:00'\n", - "assert sydney_dt.isoformat() == '2000-01-01T21:00:00+11:00'\n", - "assert la_dt.isoformat() == '2000-01-01T02:00:00-08:00'\n", + "assert utc_dt.isoformat() == \"2000-01-01T10:00:00+00:00\"\n", + "assert sydney_dt.isoformat() == \"2000-01-01T21:00:00+11:00\"\n", + "assert la_dt.isoformat() == \"2000-01-01T02:00:00-08:00\"\n", "\n", - "print('All good!')" + "print(\"All good!\")" ] } ], diff --git a/notebooks/beginner/exercises/testing2_exercise.ipynb b/notebooks/beginner/exercises/16_testing2_exercise.ipynb similarity index 96% rename from notebooks/beginner/exercises/testing2_exercise.ipynb rename to notebooks/beginner/exercises/16_testing2_exercise.ipynb index cab0169..d3862db 100644 --- a/notebooks/beginner/exercises/testing2_exercise.ipynb +++ b/notebooks/beginner/exercises/16_testing2_exercise.ipynb @@ -8,13 +8,14 @@ "source": [ "# Required boilerplate\n", "import sys\n", + "\n", "!{sys.executable} -m pip install pytest\n", "!{sys.executable} -m pip install ipytest\n", "\n", "import ipytest.magics\n", "import pytest\n", "\n", - "__file__ = 'testing2_exercise.ipynb'" + "__file__ = \"testing2_exercise.ipynb\"" ] }, { @@ -57,14 +58,14 @@ "\n", " def complete(self, number):\n", " if number not in self._todo:\n", - " raise TodoNotFound('{} not in todos'.format(number))\n", + " raise TodoNotFound(\"{} not in todos\".format(number))\n", "\n", " task = self._todo.pop(number)\n", " self._done[number] = task\n", "\n", " def remove(self, number):\n", " if number not in self._todo:\n", - " raise TodoNotFound('{} not in todos'.format(number))\n", + " raise TodoNotFound(\"{} not in todos\".format(number))\n", "\n", " del self._todo[number]" ] diff --git a/notebooks/beginner/exercises/recap2_exercise.ipynb b/notebooks/beginner/exercises/19_recap2_exercise.ipynb similarity index 80% rename from notebooks/beginner/exercises/recap2_exercise.ipynb rename to notebooks/beginner/exercises/19_recap2_exercise.ipynb index bd6b2d5..e5811e5 100644 --- a/notebooks/beginner/exercises/recap2_exercise.ipynb +++ b/notebooks/beginner/exercises/19_recap2_exercise.ipynb @@ -21,8 +21,8 @@ "PAPER = 2\n", "SCISSORS = 3\n", "\n", - "PLAYER_WINS = 'Player wins!! Woop woop!'\n", - "COMPUTER_WINS = 'Robocop wins :-('\n", + "PLAYER_WINS = \"Player wins!! Woop woop!\"\n", + "COMPUTER_WINS = \"Robocop wins :-(\"\n", "TIE = \"It's a tie!\"" ] }, @@ -32,7 +32,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Your implementation here\n" + "# Your implementation here" ] }, { @@ -49,20 +49,21 @@ "outputs": [], "source": [ "def play_rps():\n", - " print('Welcome to play rock-paper-scissors')\n", - " print('The options are:\\nrock: 1\\npaper: 2\\nscissors: 3')\n", + " print(\"Welcome to play rock-paper-scissors\")\n", + " print(\"The options are:\\nrock: 1\\npaper: 2\\nscissors: 3\")\n", "\n", " result = TIE\n", " while result == TIE:\n", - " player_choice = input('Give your choice\\n')\n", - " \n", - " if not player_choice in ['1', '2', '3']:\n", - " print('Invalid choice')\n", + " player_choice = input(\"Give your choice\\n\")\n", + "\n", + " if not player_choice in [\"1\", \"2\", \"3\"]:\n", + " print(\"Invalid choice\")\n", " continue\n", - " \n", + "\n", " result = rock_paper_scissors(int(player_choice))\n", - " \n", - "if __name__ == '__main__':\n", + "\n", + "\n", + "if __name__ == \"__main__\":\n", " play_rps()" ] }, @@ -109,7 +110,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Your implementation here\n" + "# Your implementation here" ] }, { @@ -128,9 +129,10 @@ "outputs": [], "source": [ "import os\n", + "\n", "WORKING_DIR = os.getcwd()\n", - "DATA_DIR = os.path.join(os.path.dirname(WORKING_DIR), 'data')\n", - "DATA_FILE = os.path.join(DATA_DIR, 'random_data.txt')\n", + "DATA_DIR = os.path.join(os.path.dirname(WORKING_DIR), \"data\")\n", + "DATA_FILE = os.path.join(DATA_DIR, \"random_data.txt\")\n", "\n", "da = DataAnalyzer(DATA_FILE)\n", "\n", @@ -144,13 +146,14 @@ "print(report)\n", "\n", "expected_report = (\n", - "'Report for random_data.txt\\n'\n", - "'samples: 20\\n'\n", - "'average: 49.35\\n'\n", - "'median: 47.50\\n'\n", - "'max: 94.00\\n'\n", - "'min: 4.00')\n", - "assert report == expected_report " + " \"Report for random_data.txt\\n\"\n", + " \"samples: 20\\n\"\n", + " \"average: 49.35\\n\"\n", + " \"median: 47.50\\n\"\n", + " \"max: 94.00\\n\"\n", + " \"min: 4.00\"\n", + ")\n", + "assert report == expected_report" ] }, { @@ -168,12 +171,12 @@ }, "outputs": [], "source": [ - "EMPTY_FILE = os.path.join(DATA_DIR, 'empty_file.txt')\n", + "EMPTY_FILE = os.path.join(DATA_DIR, \"empty_file.txt\")\n", "try:\n", " da_empty = DataAnalyzer(EMPTY_FILE)\n", "except NoData:\n", - " print('All ok :)')\n", - "else: # There was no exception\n", + " print(\"All ok :)\")\n", + "else: # There was no exception\n", " assert False" ] } diff --git a/notebooks/beginner/html/01_strings.html b/notebooks/beginner/html/01_strings.html new file mode 100644 index 0000000..5355ce0 --- /dev/null +++ b/notebooks/beginner/html/01_strings.html @@ -0,0 +1,16216 @@ + + + + + +01_strings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/02_numbers.html b/notebooks/beginner/html/02_numbers.html new file mode 100644 index 0000000..ae0fc6e --- /dev/null +++ b/notebooks/beginner/html/02_numbers.html @@ -0,0 +1,15613 @@ + + + + + +02_numbers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/03_conditionals.html b/notebooks/beginner/html/03_conditionals.html new file mode 100644 index 0000000..160f64f --- /dev/null +++ b/notebooks/beginner/html/03_conditionals.html @@ -0,0 +1,15893 @@ + + + + + +03_conditionals + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/04_lists.html b/notebooks/beginner/html/04_lists.html new file mode 100644 index 0000000..979781e --- /dev/null +++ b/notebooks/beginner/html/04_lists.html @@ -0,0 +1,15917 @@ + + + + + +04_lists + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/05_dictionaries.html b/notebooks/beginner/html/05_dictionaries.html new file mode 100644 index 0000000..6eaa9fc --- /dev/null +++ b/notebooks/beginner/html/05_dictionaries.html @@ -0,0 +1,15843 @@ + + + + + +05_dictionaries + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/06_for_loops.html b/notebooks/beginner/html/06_for_loops.html new file mode 100644 index 0000000..933d5bc --- /dev/null +++ b/notebooks/beginner/html/06_for_loops.html @@ -0,0 +1,15577 @@ + + + + + +06_for_loops + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/07_functions.html b/notebooks/beginner/html/07_functions.html new file mode 100644 index 0000000..6a34ddc --- /dev/null +++ b/notebooks/beginner/html/07_functions.html @@ -0,0 +1,15675 @@ + + + + + +07_functions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/08_testing1.html b/notebooks/beginner/html/08_testing1.html new file mode 100644 index 0000000..386da09 --- /dev/null +++ b/notebooks/beginner/html/08_testing1.html @@ -0,0 +1,15376 @@ + + + + + +08_testing1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/10_file_io.html b/notebooks/beginner/html/10_file_io.html new file mode 100644 index 0000000..de470b5 --- /dev/null +++ b/notebooks/beginner/html/10_file_io.html @@ -0,0 +1,15414 @@ + + + + + +10_file_io + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/11_classes.html b/notebooks/beginner/html/11_classes.html new file mode 100644 index 0000000..0df09e5 --- /dev/null +++ b/notebooks/beginner/html/11_classes.html @@ -0,0 +1,15744 @@ + + + + + +11_classes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/12_exceptions.html b/notebooks/beginner/html/12_exceptions.html new file mode 100644 index 0000000..4e15a10 --- /dev/null +++ b/notebooks/beginner/html/12_exceptions.html @@ -0,0 +1,15380 @@ + + + + + +12_exceptions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/13_modules_and_packages.html b/notebooks/beginner/html/13_modules_and_packages.html new file mode 100644 index 0000000..db32a4d --- /dev/null +++ b/notebooks/beginner/html/13_modules_and_packages.html @@ -0,0 +1,15231 @@ + + + + + +13_modules_and_packages + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/14_debugging.html b/notebooks/beginner/html/14_debugging.html new file mode 100644 index 0000000..0ce26e2 --- /dev/null +++ b/notebooks/beginner/html/14_debugging.html @@ -0,0 +1,15247 @@ + + + + + +14_debugging + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/15_std_lib.html b/notebooks/beginner/html/15_std_lib.html new file mode 100644 index 0000000..b8263d6 --- /dev/null +++ b/notebooks/beginner/html/15_std_lib.html @@ -0,0 +1,15973 @@ + + + + + +15_std_lib + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/16_testing2.html b/notebooks/beginner/html/16_testing2.html new file mode 100644 index 0000000..d4c189c --- /dev/null +++ b/notebooks/beginner/html/16_testing2.html @@ -0,0 +1,15487 @@ + + + + + +16_testing2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/17_venv.html b/notebooks/beginner/html/17_venv.html new file mode 100644 index 0000000..6f3ea05 --- /dev/null +++ b/notebooks/beginner/html/17_venv.html @@ -0,0 +1,15205 @@ + + + + + +17_venv + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/18_project_structure.html b/notebooks/beginner/html/18_project_structure.html new file mode 100644 index 0000000..17fb4b0 --- /dev/null +++ b/notebooks/beginner/html/18_project_structure.html @@ -0,0 +1,15251 @@ + + + + + +18_project_structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/beginner/html/classes.html b/notebooks/beginner/html/classes.html deleted file mode 100644 index 78d9d42..0000000 --- a/notebooks/beginner/html/classes.html +++ /dev/null @@ -1,12335 +0,0 @@ - - - -tmp_classes - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    class MyFirstClass:
    -    def __init__(self, name):
    -        self.name = name
    -
    -    def greet(self):
    -        print('Hello {}!'.format(self.name))
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [2]:
    -
    -
    -
    my_instance = MyFirstClass('John Doe')
    -print('my_instance: {}'.format(my_instance))
    -print('type: {}'.format(type(my_instance)))
    -print('my_instance.name: {}'.format(my_instance.name))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    my_instance: <__main__.MyFirstClass object at 0x106a18588>
    -type: <class '__main__.MyFirstClass'>
    -my_instance.name: John Doe
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Methods

    The functions inside classes are called methods. They are used similarly as functions.

    - -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    alice = MyFirstClass(name='Alice')
    -alice.greet()
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Hello Alice!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    __init__()

    __init__() is a special method that is used for initialising instances of the class. It's called when you create an instance of the class.

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    class Example:
    -    def __init__(self):
    -        print('Now we are inside __init__')
    -        
    -print('creating instance of Example')
    -example = Example()
    -print('instance created')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    creating instance of Example
    -Now we are inside __init__
    -instance created
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    __init__() is typically used for initialising instance variables of your class. These can be listed as arguments after self. To be able to access these instance variables later during your instance's lifetime, you have to save them into self. self is the first argument of the methods of your class and it's your access to the instance variables and other methods.

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    class Example:
    -    def __init__(self, var1, var2):
    -        self.first_var = var1
    -        self.second_var = var2
    -        
    -    def print_variables(self):
    -        print('{} {}'.format(self.first_var, self.second_var))
    -        
    -e = Example('abc', 123)
    -e.print_variables()
    -    
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    abc 123
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    __str__()

    __str__() is a special method which is called when an instance of the class is converted to string (e.g. when you want to print the instance). In other words, by defining __str__ method for your class, you can decide what's the printable version of the instances of your class. The method should return a string.

    - -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    class Person:
    -    def __init__(self, name, age):
    -        self.name = name
    -        self.age = age
    -        
    -    def __str__(self):
    -        return 'Person: {}'.format(self.name)
    -    
    -jack = Person('Jack', 82)
    -print('This is the string presentation of jack: {}'.format(jack))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    This is the string presentation of jack: Person: Jack
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Class variables vs instance variables

    Class variables are shared between all the instances of that class whereas instance variables can hold different values between different instances of that class.

    - -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    class Example:
    -    # These are class variables
    -    name = 'Example class'
    -    description = 'Just an example of a simple class'
    -
    -    def __init__(self, var1):
    -        # This is an instance variable
    -        self.instance_variable = var1
    -
    -    def show_info(self):
    -        info = 'instance_variable: {}, name: {}, description: {}'.format(
    -            self.instance_variable, Example.name, Example.description)
    -        print(info)
    -
    -
    -inst1 = Example('foo')
    -inst2 = Example('bar')
    -
    -# name and description have identical values between instances
    -assert inst1.name == inst2.name == Example.name
    -assert inst1.description == inst2.description == Example.description
    -
    -# If you change the value of a class variable, it's changed across all instances
    -Example.name = 'Modified name'
    -inst1.show_info()
    -inst2.show_info()
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    instance_variable: foo, name: Modified name, description: Just an example of a simple class
    -instance_variable: bar, name: Modified name, description: Just an example of a simple class
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Public vs private

    In python there's now strict separation for private/public methods or instance variables. The convention is to start the name of the method or instance variable with underscore if it should be treated as private. Private means that it should not be accessed from outside of the class.

    -

    For example, let's consider that we have a Person class which has age as an instance variable. We want that age is not directly accessed (e.g. changed) after the instance is created. In Python, this would be:

    - -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    class Person:
    -    def __init__(self, age):
    -        self._age = age
    -        
    -example_person = Person(age=15)
    -# You can't do this:
    -# print(example_person.age)
    -# Nor this:
    -# example_person.age = 16
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    If you want the age to be readable but not writable, you can use property:

    - -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    class Person:
    -    def __init__(self, age):
    -        self._age = age
    -        
    -    @property
    -    def age(self):
    -        return self._age
    -        
    -example_person = Person(age=15)
    -# Now you can do this:
    -print(example_person.age)
    -# But not this:
    -#example_person.age = 16
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    15
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    This way you can have a controlled access to the instance variables of your class:

    - -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    class Person:
    -    def __init__(self, age):
    -        self._age = age
    -        
    -    @property
    -    def age(self):
    -        return self._age
    -    
    -    def celebrate_birthday(self):
    -        self._age += 1
    -        print('Happy bday for {} years old!'.format(self._age))
    -        
    -example_person = Person(age=15)
    -example_person.celebrate_birthday()
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Happy bday for 16 years old!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Introduction to inheritance

    -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    class Animal:
    -    def greet(self):
    -        print('Hello, I am an animal')
    -
    -    @property
    -    def favorite_food(self):
    -        return 'beef'
    -
    -
    -class Dog(Animal):
    -    def greet(self):
    -        print('wof wof')
    -
    -
    -class Cat(Animal):
    -    @property
    -    def favorite_food(self):
    -        return 'fish'
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [12]:
    -
    -
    -
    dog = Dog()
    -dog.greet()
    -print("Dog's favorite food is {}".format(dog.favorite_food))
    -
    -cat = Cat()
    -cat.greet()
    -print("Cat's favorite food is {}".format(cat.favorite_food))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    wof wof
    -Dog's favorite food is beef
    -Hello, I am an animal
    -Cat's favorite food is fish
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/conditionals.html b/notebooks/beginner/html/conditionals.html deleted file mode 100644 index 7f500c1..0000000 --- a/notebooks/beginner/html/conditionals.html +++ /dev/null @@ -1,12397 +0,0 @@ - - - -tmp_conditionals - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Conditionals

    -
    -
    -
    -
    -
    -
    -
    -

    Testing truth value

    -
    -
    -
    -
    -
    -
    -
    -

    bool

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    print('type of True and False: {}'.format(type(True)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    type of True and False: <class 'bool'>
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [2]:
    -
    -
    -
    print('0: {}, 1: {}'.format(bool(0), bool(1)))
    -print('empty list: {}, list with values: {}'.format(bool([]), bool(['woop'])))
    -print('empty dict: {}, dict with values: {}'.format(bool({}), bool({'Python': 'cool'})))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0: False, 1: True
    -empty list: False, list with values: True
    -empty dict: False, dict with values: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    ==, !=, >, <, >=, <=

    -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    print('1 == 0: {}'.format(1 == 0))
    -print('1 != 0: {}'.format(1 != 0))
    -print('1 > 0: {}'.format(1 > 0))
    -print('1 > 1: {}'.format(1 > 1))
    -print('1 < 0: {}'.format(1 < 0))
    -print('1 < 1: {}'.format(1 < 1))
    -print('1 >= 0: {}'.format(1 >= 0))
    -print('1 >= 1: {}'.format(1 >= 1))
    -print('1 <= 0: {}'.format(1 <= 0))
    -print('1 <= 1: {}'.format(1 <= 1))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    1 == 0: False
    -1 != 0: True
    -1 > 0: True
    -1 > 1: False
    -1 < 0: False
    -1 < 1: False
    -1 >= 0: True
    -1 >= 1: True
    -1 <= 0: False
    -1 <= 1: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    You can combine these:

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    print('1 <= 2 <= 3: {}'.format(1 <= 2 <= 3))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    1 <= 2 <= 3: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    and, or, not

    -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    python_is_cool = True
    -java_is_cool = False
    -empty_list = []
    -secret_value = 3.14
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [6]:
    -
    -
    -
    print('Python and java are both cool: {}'.format(python_is_cool and java_is_cool))
    -print('secret_value and python_is_cool: {}'.format(secret_value and python_is_cool))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Python and java are both cool: False
    -secret_value and python_is_cool: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [7]:
    -
    -
    -
    print('Python or java is cool: {}'.format(python_is_cool or java_is_cool))
    -print('1 >= 1.1 or 2 < float("1.4"): {}'.format(1 >= 1.1 or 2 < float('1.4')))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Python or java is cool: True
    -1 >= 1.1 or 2 < float("1.4"): False
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [8]:
    -
    -
    -
    print('Java is not cool: {}'.format(not java_is_cool))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Java is not cool: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    You can combine multiple statements, execution order is from left to right. You can control the execution order by using brackets.

    - -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    print(bool(not java_is_cool or secret_value and  python_is_cool or empty_list))
    -print(bool(not (java_is_cool or secret_value and  python_is_cool or empty_list)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    True
    -False
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    if

    -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    statement = True
    -if statement:
    -    print('statement is True')
    -    
    -if not statement:
    -    print('statement is not True')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    statement is True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [11]:
    -
    -
    -
    empty_list = []
    -# With if and elif, conversion to `bool` is implicit
    -if empty_list:
    -    print('empty list will not evaluate to True')  # this won't be executed
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [12]:
    -
    -
    -
    val = 3
    -if 0 <= val < 1 or val == 3:
    -    print('Value is positive and less than one or value is three')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Value is positive and less than one or value is three
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    if-else

    -
    -
    -
    -
    -
    -
    In [13]:
    -
    -
    -
    my_dict = {}
    -if my_dict:
    -    print('there is something in my dict')
    -else:
    -    print('my dict is empty :(')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    my dict is empty :(
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    if-elif-else

    -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    val = 88
    -if val >= 100:
    -    print('value is equal or greater than 100')
    -elif val > 10:
    -    print('value is greater than 10 but less than 100')
    -else:
    -    print('value is equal or less than 10')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    value is greater than 10 but less than 100
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    You can have as many elif statements as you need. In addition, else at the end is not mandatory.

    - -
    -
    -
    -
    -
    -
    In [15]:
    -
    -
    -
    greeting = 'Hello fellow Pythonista!'
    -language = 'Italian'
    -
    -if language == 'Swedish':
    -    greeting = 'Hejsan!'
    -elif language == 'Finnish':
    -    greeting = 'Latua perkele!'
    -elif language == 'Spanish':
    -    greeting = 'Hola!'
    -elif language == 'German':
    -    greeting = 'Guten Tag!'
    -    
    -print(greeting)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Hello fellow Pythonista!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    For more detailed overview about conditionals, check this tutorial from Real Python.

    - -
    -
    -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/debugging.html b/notebooks/beginner/html/debugging.html deleted file mode 100644 index 5930372..0000000 --- a/notebooks/beginner/html/debugging.html +++ /dev/null @@ -1,11919 +0,0 @@ - - - -tmp_debugging - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Debugging with pdb

    Your program does not always behave how you would expect it to behave. If the origin of the mistake is unclear, debugging is usually the most effective to find the root cause of the unexpected behavior. The Python Standard Library has a built-in debugger which is a powerful tool for solving any issues related to your code.

    - -
    -
    -
    -
    -
    -
    -
    -

    import pdb; pdb.set_trace()

    The basic use case for debugging is that you want to stop the execution of your program at some certain point and monitor variable values or program execution in general from that specific point onward. You stop the execution at the point you want by setting a breakpoint into code by import pdb; pdb.set_trace() (note in Python versions >= 3.7, there's a shortcut: breakpoint()).

    -

    When you execute your program, the execution will stop at this point and will enter to interactive debugger session. You can add as many breakpoints into your code as you want.

    - -
    -
    -
    -
    -
    -
    -
    -

    Useful commands

    See the full list here.

    -
      -
    • h or help: Prints a list of available commands. If you give an argument, e.g. help continue, prints help of the continue command.
    • -
    • l or list: List a piece of code around the current position.
    • -
    • n or next: Execute next line.
    • -
    • s or step: Same as next but "steps into" the function called in the next line.
    • -
    • c or continue: Continue execution until next breakpoint.
    • -
    • r or return: Continue execution until the return of current function.
    • -
    • q or quit: Quit debugger and abort program execution.
    • -
    -

    Note that you can see the value of any variable by typing the variable name during the debugging session. You can also execute arbitrary code during the debugging session.

    - -
    -
    -
    -
    -
    -
    -
    -

    Let's see how it works

    Uncomment the import pdb; pdb.set_trace() lines and execute the cell. Execute the program line by line by using the commands defined above. Try all the above mentioned commands at least once. Pay attention to the difference between n and s.

    - -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    class SuperGreeter:
    -    def __init__(self, people_to_greet):
    -        self.people = people_to_greet
    -
    -    def greet(self):
    -        for person in self.people:
    -            if person.islower():
    -                self._greet_street_style(person)
    -            elif len(person) > 7:
    -                self._greet_hawaii(person)
    -            else:
    -                self._greet_polite(person)
    -            
    -    def _greet_polite(self, name):
    -        greeting = "G'day {}! How are you doing?".format(name)
    -        print(greeting)
    -
    -    def _greet_street_style(self, name):
    -        # import pdb; pdb.set_trace()  # UNCOMMENT
    -        name = name.upper()
    -        print('WASSUP {}!?'.format(name))
    -
    -    def _greet_hawaii(self, name):
    -        print('Aloha {}!'.format(name))
    -
    -
    -def main():
    -    people = ['John Doe', 'Donald', 'Lisa', 'alex']
    -    # import pdb; pdb.set_trace()  # UNCOMMENT
    -    greeter = SuperGreeter(people)
    -    greeter.greet()
    -
    -
    -main()
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Aloha John Doe!
    -G'day Donald! How are you doing?
    -G'day Lisa! How are you doing?
    -WASSUP ALEX!?
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/dictionaries.html b/notebooks/beginner/html/dictionaries.html deleted file mode 100644 index 46c6c58..0000000 --- a/notebooks/beginner/html/dictionaries.html +++ /dev/null @@ -1,12410 +0,0 @@ - - - -tmp_dictionaries - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Dictionaries

    Collections of key-value pairs.

    - -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    my_empty_dict = {}  # alternative: my_empty_dict = dict()
    -print('dict: {}, type: {}'.format(my_empty_dict, type(my_empty_dict)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    dict: {}, type: <class 'dict'>
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Initialization

    -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    dict1 = {'value1': 1.6, 'value2': 10, 'name': 'John Doe'}
    -dict2 = dict(value1=1.6, value2=10, name='John Doe')
    -
    -print(dict1)
    -print(dict2)
    -
    -print('equal: {}'.format(dict1 == dict2))
    -print('length: {}'.format(len(dict1)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'value1': 1.6, 'name': 'John Doe', 'value2': 10}
    -{'value2': 10, 'name': 'John Doe', 'value1': 1.6}
    -equal: True
    -length: 3
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    dict.keys(), dict.values(), dict.items()

    -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    print('keys: {}'.format(dict1.keys()))
    -print('values: {}'.format(dict1.values()))
    -print('items: {}'.format(dict1.items()))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    keys: dict_keys(['value1', 'name', 'value2'])
    -values: dict_values([1.6, 'John Doe', 10])
    -items: dict_items([('value1', 1.6), ('name', 'John Doe'), ('value2', 10)])
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Accessing and setting values

    -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    my_dict = {}
    -my_dict['key1'] = 'value1'
    -my_dict['key2'] = 99
    -my_dict['key1'] = 'new value'  # overriding existing value
    -print(my_dict)
    -print('value of key1: {}'.format(my_dict['key1']))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'key2': 99, 'key1': 'new value'}
    -value of key1: new value
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Accessing a nonexistent key will raise KeyError (see dict.get() for workaround):

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    # print(my_dict['nope'])
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Deleting

    -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    my_dict = {'key1': 'value1', 'key2': 99, 'keyX': 'valueX'}
    -del my_dict['keyX']
    -print(my_dict)
    -
    -# Usually better to make sure that the key exists (see also pop() and popitem())
    -key_to_delete = 'my_key'
    -if key_to_delete in my_dict:
    -    del my_dict[key_to_delete]
    -else:
    -    print('{key} is not in {dictionary}'.format(key=key_to_delete, dictionary=my_dict))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'key2': 99, 'key1': 'value1'}
    -my_key is not in {'key2': 99, 'key1': 'value1'}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Dictionaries are mutable

    -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    my_dict = {'ham': 'good', 'carrot': 'semi good'}
    -my_other_dict = my_dict
    -my_other_dict['carrot'] = 'super tasty'
    -my_other_dict['sausage'] = 'best ever'
    -print('my_dict: {}\nother: {}'.format(my_dict, my_other_dict))
    -print('equal: {}'.format(my_dict == my_other_dict))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    my_dict: {'carrot': 'super tasty', 'ham': 'good', 'sausage': 'best ever'}
    -other: {'carrot': 'super tasty', 'ham': 'good', 'sausage': 'best ever'}
    -equal: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Create a new dict if you want to have a copy:

    - -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    my_dict = {'ham': 'good', 'carrot': 'semi good'}
    -my_other_dict = dict(my_dict)
    -my_other_dict['beer'] = 'decent'
    -print('my_dict: {}\nother: {}'.format(my_dict, my_other_dict))
    -print('equal: {}'.format(my_dict == my_other_dict))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    my_dict: {'carrot': 'semi good', 'ham': 'good'}
    -other: {'beer': 'decent', 'carrot': 'semi good', 'ham': 'good'}
    -equal: False
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    -

    dict.get()

    Returns None if key is not in dict. However, you can also specify default return value which will be returned if key is not present in the dict.

    - -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    my_dict = {'a': 1, 'b': 2, 'c': 3}
    -d = my_dict.get('d')
    -print('d: {}'.format(d))
    -
    -d = my_dict.get('d', 'my default value')
    -print('d: {}'.format(d))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    d: None
    -d: my default value
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    dict.pop()

    -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    my_dict = dict(food='ham', drink='beer', sport='football')
    -print('dict before pops: {}'.format(my_dict))
    -
    -food = my_dict.pop('food')
    -print('food: {}'.format(food))
    -print('dict after popping food: {}'.format(my_dict))
    -
    -food_again = my_dict.pop('food', 'default value for food')
    -print('food again: {}'.format(food_again))
    -print('dict after popping food again: {}'.format(my_dict))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    dict before pops: {'sport': 'football', 'drink': 'beer', 'food': 'ham'}
    -food: ham
    -dict after popping food: {'sport': 'football', 'drink': 'beer'}
    -food again: default value for food
    -dict after popping food again: {'sport': 'football', 'drink': 'beer'}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    dict.setdefault()

    Returns the value of key defined as first parameter. If the key is not present in the dict, adds key with default value (second parameter).

    - -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    my_dict = {'a': 1, 'b': 2, 'c': 3}
    -a = my_dict.setdefault('a', 'my default value')
    -d = my_dict.setdefault('d', 'my default value')
    -print('a: {}\nd: {}\nmy_dict: {}'.format(a, d, my_dict))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    a: 1
    -d: my default value
    -my_dict: {'a': 1, 'c': 3, 'b': 2, 'd': 'my default value'}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    dict.update()

    Merge two dicts

    - -
    -
    -
    -
    -
    -
    In [12]:
    -
    -
    -
    dict1 = {'a': 1, 'b': 2}
    -dict2 = {'c': 3}
    -dict1.update(dict2)
    -print(dict1)
    -
    -# If they have same keys:
    -dict1.update({'c': 4})
    -print(dict1)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'a': 1, 'c': 3, 'b': 2}
    -{'a': 1, 'c': 4, 'b': 2}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    The keys of a dict have to be immutable

    -
    -
    -
    -
    -
    -
    -
    -

    Thus you can not use e.g. a list or a dict as key because they are mutable types -:

    - -
    -
    -
    -
    -
    -
    In [13]:
    -
    -
    -
    # bad_dict = {['my_list'], 'value'}  # Raises TypeError
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Values can be mutable

    - -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    good_dict = {'my key': ['Python', 'is', 'still', 'cool']}
    -print(good_dict)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'my key': ['Python', 'is', 'still', 'cool']}
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/exceptions.html b/notebooks/beginner/html/exceptions.html deleted file mode 100644 index 0e31e35..0000000 --- a/notebooks/beginner/html/exceptions.html +++ /dev/null @@ -1,12025 +0,0 @@ - - - -tmp_exceptions - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Exceptions

    When something goes wrong an exception is raised. For example, if you try to divide by zero, ZeroDivisionError is raised or if you try to access a nonexistent key in a dictionary, KeyError is raised.

    - -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    empty_dict = {}
    -# empty_dict['key']  # Uncomment to see the traceback
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    try-except structure

    If you know that a block of code can fail in some manner, you can use try-except structure to handle potential exceptions in a desired way.

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    # Let's try to open a file that does not exist
    -file_name = 'not_existing.txt'
    -
    -try:
    -    with open(file_name, 'r') as my_file:
    -        print('File is successfully open')
    -        
    -except FileNotFoundError as e:
    -    print('Uups, file: {} not found'.format(file_name))
    -    print('Exception: {} was raised'.format(e))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Uups, file: not_existing.txt not found
    -Exception: [Errno 2] No such file or directory: 'not_existing.txt' was raised
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    If you don't know the type of exceptions that a code block can possibly raise, you can use Exception which catches all exceptions. In addition, you can have multiple except statements.

    - -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    def calculate_division(var1, var2):
    -    result = 0
    -    
    -    try:
    -        result = var1 / var2
    -    except ZeroDivisionError as ex1:
    -        print("Can't divide by zero")
    -    except Exception as ex2:
    -        print('Exception: {}'.format(ex2))
    -
    -    return result
    -
    -result1 = calculate_division(3, 3)
    -print('result1: {}'.format(result1))
    -
    -result2 = calculate_division(3, '3')
    -print('result2: {}'.format(result2))
    -
    -result3 = calculate_division(3, 0)
    -print('result3: {}'.format(result3))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    result1: 1.0
    -Exception: unsupported operand type(s) for /: 'int' and 'str'
    -result2: 0
    -Can't divide by zero
    -result3: 0
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    try-except can be also in outer scope:

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    def calculate_division(var1, var2):
    -    return var1 / var2
    -
    -try:
    -    result = calculate_division(3, '3')
    -except Exception as e:
    -    print(e)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    unsupported operand type(s) for /: 'int' and 'str'
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Creating your custom exceptions

    In your own applications, you can use custom exceptions for signaling users about errors which occur during your application run time.

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    import math
    -
    -# Define your own exception
    -class NegativeNumbersNotSupported(Exception):
    -    pass
    -
    -# Dummy example how to use your custom exception
    -def secret_calculation(number1, number2):
    -    if number1 < 0 or number2 < 0:
    -        msg = 'Negative number in at least one of the parameters: {}, {}'.format(
    -            number1, number2)
    -        raise NegativeNumbersNotSupported(msg)
    -
    -    return math.sqrt(number1) + math.sqrt(number2)
    -
    -# Uncomment to see the traceback
    -# result = secret_calculation(-1, 1)
    -
    - -
    -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/file_io.html b/notebooks/beginner/html/file_io.html deleted file mode 100644 index 5cb4038..0000000 --- a/notebooks/beginner/html/file_io.html +++ /dev/null @@ -1,12053 +0,0 @@ - - - -tmp_file_io - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    File I/O

    Reading and writing files.

    - -
    -
    -
    -
    -
    -
    -
    -

    Working with paths

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    import os
    -
    -current_file = os.path.realpath('file_io.ipynb')  
    -print('current file: {}'.format(current_file))
    -# Note: in .py files you can get the path of current file by __file__
    -
    -current_dir = os.path.dirname(current_file)  
    -print('current directory: {}'.format(current_dir))
    -# Note: in .py files you can get the dir of current file by os.path.dirname(__file__)
    -
    -data_dir = os.path.join(os.path.dirname(current_dir), 'data')
    -print('data directory: {}'.format(data_dir))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    current file: /Users/jerry/github/jerry-git/learn-python3/notebooks/beginner/notebooks/file_io.ipynb
    -current directory: /Users/jerry/github/jerry-git/learn-python3/notebooks/beginner/notebooks
    -data directory: /Users/jerry/github/jerry-git/learn-python3/notebooks/beginner/data
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Checking if path exists

    -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    print('exists: {}'.format(os.path.exists(data_dir)))
    -print('is file: {}'.format(os.path.isfile(data_dir)))
    -print('is directory: {}'.format(os.path.isdir(data_dir)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    exists: True
    -is file: False
    -is directory: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Reading files

    -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    file_path = os.path.join(data_dir, 'simple_file.txt')
    -
    -with open(file_path, 'r') as simple_file:
    -    for line in simple_file:
    -        print(line.strip())
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    First line
    -Second line
    -Third
    -And so the story goes!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    The with statement is for obtaining a context manager that will be used as an execution context for the commands inside the with. Context managers guarantee that certain operations are done when exiting the context.

    -

    In this case, the context manager guarantees that simple_file.close() is implicitly called when exiting the context. This is a way to make developers life easier: you don't have to remember to explicitly close the file you openened nor be worried about an exception occuring while the file is open. Unclosed file maybe a source of a resource leak. Thus, prefer using with open() structure always with file I/O.

    -

    To have an example, the same as above without the with.

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    file_path = os.path.join(data_dir, 'simple_file.txt')
    -
    -# THIS IS NOT THE PREFERRED WAY
    -simple_file = open(file_path, 'r')
    -for line in simple_file:
    -    print(line.strip())
    -simple_file.close()  # This has to be called explicitly 
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    First line
    -Second line
    -Third
    -And so the story goes!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Writing files

    -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    new_file_path = os.path.join(data_dir, 'new_file.txt')
    -
    -with open(new_file_path, 'w') as my_file:
    -    my_file.write('This is my first file that I wrote with Python.')
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Now go and check that there is a new_file.txt in the data directory. After that you can delete the file by:

    - -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    if os.path.exists(new_file_path):  # make sure it's there
    -    os.remove(new_file_path)
    -
    - -
    -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/for_loops.html b/notebooks/beginner/html/for_loops.html deleted file mode 100644 index 75fbacb..0000000 --- a/notebooks/beginner/html/for_loops.html +++ /dev/null @@ -1,12192 +0,0 @@ - - - -tmp_for_loops - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -

    Looping lists

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    my_list = [1, 2, 3, 4, 'Python', 'is', 'neat']
    -for item in my_list:
    -    print(item)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    1
    -2
    -3
    -4
    -Python
    -is
    -neat
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    break

    Stop the execution of the loop.

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    for item in my_list:
    -    if item == 'Python':
    -        break
    -    print(item)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    1
    -2
    -3
    -4
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    continue

    Continue to the next item without executing the lines occuring after continue inside the loop.

    - -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    for item in my_list:
    -    if item == 1:
    -        continue
    -    print(item)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    2
    -3
    -4
    -Python
    -is
    -neat
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    enumerate()

    In case you need to also know the index:

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    for idx, val in enumerate(my_list):
    -    print('idx: {}, value: {}'.format(idx, val))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    idx: 0, value: 1
    -idx: 1, value: 2
    -idx: 2, value: 3
    -idx: 3, value: 4
    -idx: 4, value: Python
    -idx: 5, value: is
    -idx: 6, value: neat
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Looping dictionaries

    -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    my_dict = {'hacker': True, 'age': 72, 'name': 'John Doe'}
    -for val in my_dict:
    -    print(val)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    age
    -name
    -hacker
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [6]:
    -
    -
    -
    for key, val in my_dict.items():
    -    print('{}={}'.format(key, val))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    age=72
    -name=John Doe
    -hacker=True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    range()

    -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    for number in range(5):
    -    print(number)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0
    -1
    -2
    -3
    -4
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [8]:
    -
    -
    -
    for number in range(2, 5):
    -    print(number)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    2
    -3
    -4
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [9]:
    -
    -
    -
    for number in range(0, 10, 2):  # last one is step
    -    print(number)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0
    -2
    -4
    -6
    -8
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/functions.html b/notebooks/beginner/html/functions.html deleted file mode 100644 index a746d44..0000000 --- a/notebooks/beginner/html/functions.html +++ /dev/null @@ -1,12274 +0,0 @@ - - - -tmp_functions - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Functions

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    def my_first_function():
    -    print('Hello world!')
    -
    -print('type: {}'.format(my_first_function))
    -
    -my_first_function()  # Calling a function
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    type: <function my_first_function at 0x1068d98c8>
    -Hello world!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Arguments

    -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    def greet_us(name1, name2):
    -    print('Hello {} and {}!'.format(name1, name2))
    -
    -greet_us('John Doe', 'Superman')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Hello John Doe and Superman!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [3]:
    -
    -
    -
    # Function with return value
    -def strip_and_lowercase(original):
    -    modified = original.strip().lower()
    -    return modified
    -
    -uggly_string = '  MixED CaSe '
    -pretty = strip_and_lowercase(uggly_string)
    -print('pretty: {}'.format(pretty))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    pretty: mixed case
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Keyword arguments

    -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    def my_fancy_calculation(first, second, third):
    -    return first + second - third 
    -
    -print(my_fancy_calculation(3, 2, 1))
    -
    -print(my_fancy_calculation(first=3, second=2, third=1))
    -
    -# With keyword arguments you can mix the order
    -print(my_fancy_calculation(third=1, first=3, second=2))
    -
    -# You can mix arguments and keyword arguments but you have to start with arguments
    -print(my_fancy_calculation(3, third=1, second=2))  
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    4
    -4
    -4
    -4
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Default arguments

    -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    def create_person_info(name, age, job=None, salary=300):
    -    info = {'name': name, 'age': age, 'salary': salary}
    -    
    -    # Add 'job' key only if it's provided as parameter
    -    if job:  
    -        info.update(dict(job=job))
    -        
    -    return info
    -
    -person1 = create_person_info('John Doe', 82)  # use default values for job and salary
    -person2 = create_person_info('Lisa Doe', 22, 'hacker', 10000)
    -print(person1)
    -print(person2)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'name': 'John Doe', 'age': 82, 'salary': 300}
    -{'name': 'Lisa Doe', 'age': 22, 'salary': 10000, 'job': 'hacker'}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Don't use mutable objects as default arguments!

    - -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    def append_if_multiple_of_five(number, magical_list=[]):
    -    if number % 5 == 0:
    -        magical_list.append(number)
    -    return magical_list
    -
    -print(append_if_multiple_of_five(100))
    -print(append_if_multiple_of_five(105))
    -print(append_if_multiple_of_five(123))
    -print(append_if_multiple_of_five(123, []))
    -print(append_if_multiple_of_five(123))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    [100]
    -[100, 105]
    -[100, 105]
    -[]
    -[100, 105]
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Here's how you can achieve desired behavior:

    - -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    def append_if_multiple_of_five(number, magical_list=None):
    -    if not magical_list:
    -        magical_list = []
    -    if number % 5 == 0:
    -        magical_list.append(number)
    -    return magical_list
    -
    -print(append_if_multiple_of_five(100))
    -print(append_if_multiple_of_five(105))
    -print(append_if_multiple_of_five(123))
    -print(append_if_multiple_of_five(123, []))
    -print(append_if_multiple_of_five(123))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    [100]
    -[105]
    -[]
    -[]
    -[]
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Docstrings

    Strings for documenting your functions, methods, modules and variables.

    - -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    def print_sum(val1, val2):
    -    """Function which prints the sum of given arguments."""
    -    print('sum: {}'.format(val1 + val2))
    -
    -print(help(print_sum))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Help on function print_sum in module __main__:
    -
    -print_sum(val1, val2)
    -    Function which prints the sum of given arguments.
    -
    -None
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [9]:
    -
    -
    -
    def calculate_sum(val1, val2):
    -    """This is a longer docstring defining also the args and the return value. 
    -
    -    Args:
    -        val1: The first parameter.
    -        val2: The second parameter.
    -
    -    Returns:
    -        The sum of val1 and val2.
    -        
    -    """
    -    return val1 + val2
    -
    -print(help(calculate_sum))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Help on function calculate_sum in module __main__:
    -
    -calculate_sum(val1, val2)
    -    This is a longer docstring defining also the args and the return value. 
    -    
    -    Args:
    -        val1: The first parameter.
    -        val2: The second parameter.
    -    
    -    Returns:
    -        The sum of val1 and val2.
    -
    -None
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    pass statement

    pass is a statement which does nothing when it's executed. It can be used e.g. a as placeholder to make the code syntatically correct while sketching the functions and/or classes of your application. For example, the following is valid Python.

    - -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    def my_function(some_argument):
    -    pass
    -
    -def my_other_function():
    -    pass
    -
    - -
    -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/lists.html b/notebooks/beginner/html/lists.html deleted file mode 100644 index e5603d9..0000000 --- a/notebooks/beginner/html/lists.html +++ /dev/null @@ -1,12472 +0,0 @@ - - - -tmp_lists - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    my_empty_list = []
    -print('empty list: {}, type: {}'.format(my_empty_list, type(my_empty_list)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    empty list: [], type: <class 'list'>
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [2]:
    -
    -
    -
    list_of_ints = [1, 2, 6, 7]
    -list_of_misc = [0.2, 5, 'Python', 'is', 'still fun', '!']
    -print('lengths: {} and {}'.format(len(list_of_ints), len(list_of_misc)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    lengths: 4 and 6
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Accessing values

    -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    my_list = ['Python', 'is', 'still', 'cool']
    -print(my_list[0])
    -print(my_list[3])
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Python
    -cool
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [4]:
    -
    -
    -
    coordinates = [[12.0, 13.3], [0.6, 18.0], [88.0, 1.1]]  # two dimensional
    -print('first coordinate: {}'.format(coordinates[0]))
    -print('second element of first coordinate: {}'.format(coordinates[0][1]))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    first coordinate: [12.0, 13.3]
    -second element of first coordinate: 13.3
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Updating values

    -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    my_list = [0, 1, 2, 3, 4, 5]
    -my_list[0] = 99
    -print(my_list)
    -
    -# remove first value
    -del my_list[0]
    -print(my_list)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    [99, 1, 2, 3, 4, 5]
    -[1, 2, 3, 4, 5]
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Checking if certain value is present in list

    -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    languages = ['Java', 'C++', 'Go', 'Python', 'JavaScript']
    -if 'Python' in languages:
    -    print('Python is there!')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Python is there!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [7]:
    -
    -
    -
    if 6 not in [1, 2, 3, 7]:
    -    print('number 6 is not present')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    number 6 is not present
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    List are mutable

    -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    original = [1, 2, 3]
    -modified = original
    -modified[0] = 99
    -print('original: {}, modified: {}'.format(original, modified))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    original: [99, 2, 3], modified: [99, 2, 3]
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    You can get around this by creating new list:

    - -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    original = [1, 2, 3]
    -modified = list(original)  # Note list() 
    -# Alternatively, you can use copy method
    -# modified = original.copy()
    -modified[0] = 99
    -print('original: {}, modified: {}'.format(original, modified))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    original: [1, 2, 3], modified: [99, 2, 3]
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    list.append()

    -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    my_list = [1]
    -my_list.append('ham')
    -print(my_list)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    [1, 'ham']
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    list.remove()

    -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    my_list = ['Python', 'is', 'sometimes', 'fun']
    -my_list.remove('sometimes')
    -print(my_list)
    -
    -# If you are not sure that the value is in list, better to check first:
    -if 'Java' in my_list:
    -    my_list.remove('Java')
    -else:
    -    print('Java is not part of this story.')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ['Python', 'is', 'fun']
    -Java is not part of this story.
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    list.sort()

    -
    -
    -
    -
    -
    -
    In [12]:
    -
    -
    -
    numbers = [8, 1, 6, 5, 10]
    -numbers.sort()
    -print('numbers: {}'.format(numbers))
    -
    -numbers.sort(reverse=True)
    -print('numbers reversed: {}'.format(numbers))
    -
    -words = ['this', 'is', 'a', 'list', 'of', 'words']
    -words.sort()
    -print('words: {}'.format(words))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    numbers: [1, 5, 6, 8, 10]
    -numbers reversed: [10, 8, 6, 5, 1]
    -words: ['a', 'is', 'list', 'of', 'this', 'words']
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    sorted(list)

    While list.sort() sorts the list in-place, sorted(list) returns a new list and leaves the original untouched:

    - -
    -
    -
    -
    -
    -
    In [13]:
    -
    -
    -
    numbers = [8, 1, 6, 5, 10]
    -sorted_numbers = sorted(numbers)
    -print('numbers: {}, sorted: {}'.format(numbers, sorted_numbers))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    numbers: [8, 1, 6, 5, 10], sorted: [1, 5, 6, 8, 10]
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    list.extend()

    -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    first_list = ['beef', 'ham']
    -second_list = ['potatoes',1 ,3]
    -first_list.extend(second_list)
    -print('first: {}, second: {}'.format(first_list, second_list))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    first: ['beef', 'ham', 'potatoes', 1, 3], second: ['potatoes', 1, 3]
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Alternatively you can also extend lists by summing them:

    - -
    -
    -
    -
    -
    -
    In [15]:
    -
    -
    -
    first = [1, 2, 3]
    -second = [4, 5]
    -first += second  # same as: first = first + second
    -print('first: {}'.format(first))
    -
    -# If you need a new list
    -summed = first + second
    -print('summed: {}'.format(summed))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    first: [1, 2, 3, 4, 5]
    -summed: [1, 2, 3, 4, 5, 4, 5]
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    list.reverse()

    -
    -
    -
    -
    -
    -
    In [16]:
    -
    -
    -
    my_list = ['a', 'b', 'ham']
    -my_list.reverse()
    -print(my_list)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ['ham', 'b', 'a']
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/modules_and_packages.html b/notebooks/beginner/html/modules_and_packages.html deleted file mode 100644 index 9c4674b..0000000 --- a/notebooks/beginner/html/modules_and_packages.html +++ /dev/null @@ -1,11903 +0,0 @@ - - - -tmp_modules_and_packages - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Modules and packages

    Module is a Python source code file, i.e. a file with .py extension.

    -

    Package is a directory which contains __init__.py file and can contain python modules and other packages.

    -
    - -
    -
    -
    -
    -
    -
    -
    -

    Why to organize your code into modules and packages

      -
    • Maintainability
    • -
    • Reusability
    • -
    • Namespacing
    • -
    • People unfamiliar with your project can get a clear overview just by looking at the directory structure of your project
    • -
    • Searching for certain functionality or class is easy
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    How to use

    Let's use the following directory structure as an example:

    - -
    food_store/
    -    __init__.py
    -
    -    product/
    -        __init__.py
    -
    -        fruit/
    -            __init__.py
    -            apple.py
    -            banana.py
    -
    -        drink/
    -            __init__.py
    -            juice.py
    -            milk.py
    -            beer.py
    -
    -    cashier/
    -        __ini__.py
    -        receipt.py
    -        calculator.py
    -

    Let's consider that banana.py file contains:

    -
    def get_available_brands():
    -    return ['chiquita']
    -
    -
    -class Banana:
    -    def __init__(self, brand='chiquita'):
    -        if brand not in get_available_brands():
    -            raise ValueError('Unkown brand: {}'.format(brand))
    -        self._brand = brand
    -
    - -
    -
    -
    -
    -
    -
    -
    -

    Importing

    Let's say that we need access Banana class from banana.py file inside receipt.py. We can achive this by importing at the beginning of receipt.py:

    -
    from food_store.product.fruit.banana import Banana
    -
    -# then it's used like this
    -my_banana = Banana()
    -
    -

    If we need to access multiple classes or functions from banana.py file:

    -
    from food_store.product.fruit import banana
    -
    -# then it's used like this
    -brands = banana.get_available_brands()
    -my_banana = banana.Banana()
    -
    - -
    -
    -
    -
    -
    -
    -
    -

    A comprehensive introduction to modules and packages can be found here.

    - -
    -
    -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/numbers.html b/notebooks/beginner/html/numbers.html deleted file mode 100644 index 3572b15..0000000 --- a/notebooks/beginner/html/numbers.html +++ /dev/null @@ -1,12216 +0,0 @@ - - - -tmp_numbers - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -

    int

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    my_int = 6
    -print('value: {}, type: {}'.format(my_int, type(my_int)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    value: 6, type: <class 'int'>
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    float

    -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    my_float = float(my_int)
    -print('value: {}, type: {}'.format(my_float, type(my_float)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    value: 6.0, type: <class 'float'>
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Note that division of ints produces float:

    - -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    print(1 / 1)
    -print(6 / 5)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    1.0
    -1.2
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Be aware of the binary floating-point pitfalls (see Decimal for workaround):

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    val = 0.1 + 0.1 + 0.1
    -print(val == 0.3)
    -print(val)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    False
    -0.30000000000000004
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Floor division //, modulus %, power **

    -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    7 // 5
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[5]:
    - - - - -
    -
    1
    -
    - -
    - -
    -
    - -
    -
    -
    -
    In [6]:
    -
    -
    -
    7 % 5
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[6]:
    - - - - -
    -
    2
    -
    - -
    - -
    -
    - -
    -
    -
    -
    In [7]:
    -
    -
    -
    2 ** 3
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[7]:
    - - - - -
    -
    8
    -
    - -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [8]:
    -
    -
    -
    from decimal import Decimal
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [9]:
    -
    -
    -
    from_float = Decimal(0.1)
    -from_str = Decimal('0.1')
    -print('from float: {}\nfrom string: {}'.format(from_float, from_str))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    from float: 0.1000000000000000055511151231257827021181583404541015625
    -from string: 0.1
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [10]:
    -
    -
    -
    my_decimal = Decimal('0.1')
    -sum_of_decimals = my_decimal + my_decimal + my_decimal
    -print(sum_of_decimals == Decimal('0.3'))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Operator precedence in calculations

    Mathematical operator precedence applies. Use brackets if you want to change the execution order:

    - -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    print(1 + 2**2 * 3 / 6) # 1 + 4 * 3 / 6 == 1 + 12 / 6 == 1 + 2
    -print((1 + 2**2) * 3 / 6)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    3.0
    -2.5
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/project_structure.html b/notebooks/beginner/html/project_structure.html deleted file mode 100644 index a634496..0000000 --- a/notebooks/beginner/html/project_structure.html +++ /dev/null @@ -1,11925 +0,0 @@ - - - -tmp_project_structure - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Project structure

    -
    -
    -
    -
    -
    -
    -
    -

    Python script

    Python is a great language for building small helper tools for various different kinds of tasks. Such small tools can be often expressed as a single file Python script.

    -

    Here is an example structure for a Python script (aka executable Python module).

    - -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    # the content of my_script.py
    -
    -# imports
    -import logging
    -
    -# constants
    -LOGGER = logging.getLogger()
    -
    -
    -def magical_function():
    -    LOGGER.warning('We are about to do some magical stuff')
    -
    -
    -def main():
    -    # The actual logic of the script
    -    magical_function()
    -
    -
    -if __name__ == '__main__':
    -    main()
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    We are about to do some magical stuff
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Python package

    An example structure for a python project:

    - -
    my_project/
    -    README.md
    -    requirements.txt
    -    setup.py
    -
    -    src/
    -        my_project/
    -            __init__.py
    -            my_module.py
    -            other_module.py
    -
    -            my_pkg1/
    -                __init__.py
    -                my_third_module.py
    -
    -    tests/
    -        conftest.py
    -        test_module.py
    -        test_other_module.py
    -
    -        my_pkg1/
    -            test_my_third_module.py
    -
      -
    • requirements.txt lists the Python packages from which my_project depends on.
        -
      • these can be installed by running pip install -r requirements
      • -
      -
    • -
    • setup.py is a file in which you include relevant information about your project and the file is also used for packaging your project. Here's a minimal example of a setup.py:
    • -
    -
    '''Minimal setup.py file'''
    -
    -from setuptools import setup, find_packages
    -
    -setup(
    -    name='my_project',
    -    version='0.1',
    -    packages=find_packages(where="src"),
    -    package_dir={"": "src"})
    -
    -
      -
    • Once you have the setup.py file in place, you can install your project in editable mode by running pip install -e . in the root directory of your project. In editable mode the installed version is updated when you make changes to the source code files.
    • -
    - -
    -
    -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/std_lib.html b/notebooks/beginner/html/std_lib.html deleted file mode 100644 index b6251fe..0000000 --- a/notebooks/beginner/html/std_lib.html +++ /dev/null @@ -1,12517 +0,0 @@ - - - -tmp_std_lib - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Goodies of the Python Standard Library

    The Python Standard Libary is part of your Python installation. It contains a wide range of packages which may be helpful while building your Python masterpieces. This notebook lists some of the commonly used packages and their main functionalities.

    - -
    -
    -
    -
    -
    -
    -
    -

    datetime for working with dates and times

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    import datetime as dt
    -
    -local_now = dt.datetime.now()
    -print('local now: {}'.format(local_now))
    -
    -utc_now = dt.datetime.utcnow()
    -print('utc now: {}'.format(utc_now))
    -
    -# You can access any value separately:
    -print('{} {} {} {} {} {}'.format(local_now.year, local_now.month,
    -                                 local_now.day, local_now.hour,
    -                                 local_now.minute, local_now.second))
    -
    -print('date: {}'.format(local_now.date()))
    -print('time: {}'.format(local_now.time()))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    local now: 2018-09-19 22:44:15.396930
    -utc now: 2018-09-19 20:44:15.397085
    -2018 9 19 22 44 15
    -date: 2018-09-19
    -time: 22:44:15.396930
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    strftime()

    For string formatting the datetime

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    formatted1 = local_now.strftime('%Y/%m/%d-%H:%M:%S')
    -print(formatted1)
    -
    -formatted2 = local_now.strftime('date: %Y-%m-%d time:%H:%M:%S')
    -print(formatted2)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    2018/09/19-22:44:15
    -date: 2018-09-19 time:22:44:15
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    strptime()

    For converting a datetime string into a datetime object

    - -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    my_dt = dt.datetime.strptime('2000-01-01 10:00:00', '%Y-%m-%d %H:%M:%S')
    -print('my_dt: {}'.format(my_dt))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    my_dt: 2000-01-01 10:00:00
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    timedelta

    For working with time difference.

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    tomorrow = local_now + dt.timedelta(days=1)
    -print('tomorrow this time: {}'.format(tomorrow))
    -
    -delta = tomorrow - local_now
    -print('tomorrow - now = {}'.format(delta))
    -print('days: {}, seconds: {}'.format(delta.days, delta.seconds))
    -print('total seconds: {}'.format(delta.total_seconds()))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    tomorrow this time: 2018-09-20 22:44:15.396930
    -tomorrow - now = 1 day, 0:00:00
    -days: 1, seconds: 0
    -total seconds: 86400.0
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Working with timezones

    Let's first make sure pytz is installed.

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    import sys
    -!{sys.executable} -m pip install pytz
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Requirement already satisfied: pytz in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (2018.4)
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [6]:
    -
    -
    -
    import datetime as dt
    -import pytz
    -
    -naive_utc_now = dt.datetime.utcnow()
    -print('naive utc now: {}, tzinfo: {}'.format(naive_utc_now, naive_utc_now.tzinfo))
    -
    -# Localizing naive datetimes
    -UTC_TZ = pytz.timezone('UTC')
    -utc_now = UTC_TZ.localize(naive_utc_now)
    -print('utc now: {}, tzinfo: {}'.format(utc_now, utc_now.tzinfo))
    -
    -# Converting localized datetimes to different timezone
    -PARIS_TZ = pytz.timezone('Europe/Paris')
    -paris_now = PARIS_TZ.normalize(utc_now)
    -print('Paris: {}, tzinfo: {}'.format(paris_now, paris_now.tzinfo))
    -
    -NEW_YORK_TZ = pytz.timezone('America/New_York')
    -ny_now = NEW_YORK_TZ.normalize(utc_now)
    -print('New York: {}, tzinfo: {}'.format(ny_now, ny_now.tzinfo))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    naive utc now: 2018-09-19 20:44:16.308229, tzinfo: None
    -utc now: 2018-09-19 20:44:16.308229+00:00, tzinfo: UTC
    -Paris: 2018-09-19 22:44:16.308229+02:00, tzinfo: Europe/Paris
    -New York: 2018-09-19 16:44:16.308229-04:00, tzinfo: America/New_York
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    NOTE: If your project uses datetimes heavily, you may want to take a look at external libraries, such as Pendulum and Maya, which make working with datetimes easier for certain use cases.

    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    import logging
    -
    -# Handy way for getting a dedicated logger for every module separately
    -logger = logging.getLogger(__name__)
    -logger.setLevel(logging.WARNING)
    -
    -logger.debug('This is debug')
    -logger.info('This is info')
    -logger.warning('This is warning')
    -logger.error('This is error')
    -logger.critical('This is critical')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    This is warning
    -This is error
    -This is critical
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Logging expections

    There's a neat exception function in logging module which will automatically log the stack trace in addition to user defined log entry.

    - -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    try:
    -    path_calculation = 1 / 0
    -except ZeroDivisionError:
    -    logging.exception('All went south in my calculation')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ERROR:root:All went south in my calculation
    -Traceback (most recent call last):
    -  File "<ipython-input-8-ccd7d25e79b7>", line 2, in <module>
    -    path_calculation = 1 / 0
    -ZeroDivisionError: division by zero
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Formatting log entries

    -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    import logging
    -
    -# This is only required for Jupyter notebook environment
    -from importlib import reload
    -reload(logging)
    -
    -my_format = '%(asctime)s | %(name)-12s | %(levelname)-10s | %(message)s'
    -logging.basicConfig(format=my_format)
    -
    -logger = logging.getLogger('MyLogger')
    -
    -logger.warning('Something bad is going to happen')
    -logger.error('Uups, it already happened')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    2018-09-19 22:44:16,365 | MyLogger     | WARNING    | Something bad is going to happen
    -2018-09-19 22:44:16,366 | MyLogger     | ERROR      | Uups, it already happened
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Logging to a file

    -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    import os
    -import logging
    -
    -# This is only required for Jupyter notebook environment
    -from importlib import reload
    -reload(logging)
    -
    -logger = logging.getLogger('MyFileLogger')
    -
    -# Let's define a file_handler for our logger
    -log_path = os.path.join(os.getcwd(), 'my_log.txt')
    -file_handler = logging.FileHandler(log_path)
    -
    -# And a nice format
    -formatter = logging.Formatter('%(asctime)s | %(name)-12s | %(levelname)-10s | %(message)s')
    -file_handler.setFormatter(formatter)
    -
    -logger.addHandler(file_handler)
    -
    -# If you want to see it also in the console, add another handler for it
    -# logger.addHandler(logging.StreamHandler())
    -
    -logger.warning('Oops something is going to happen')
    -logger.error('John Doe visits our place')
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    random for random number generation

    -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    import random
    -
    -rand_int = random.randint(1, 100)
    -print('random integer between 1-100: {}'.format(rand_int))
    -
    -rand = random.random()
    -print('random float between 0-1: {}'.format(rand))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    random integer between 1-100: 33
    -random float between 0-1: 0.10137384902353497
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    If you need pseudo random numbers, you can set the seed for random. This will reproduce the output (try running the cell multiple times):

    - -
    -
    -
    -
    -
    -
    In [12]:
    -
    -
    -
    import random
    -
    -random.seed(5)  # Setting the seed
    -
    -# Let's print 10 random numbers
    -for _ in range(10):
    -    print(random.random())
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0.6229016948897019
    -0.7417869892607294
    -0.7951935655656966
    -0.9424502837770503
    -0.7398985747399307
    -0.922324996665417
    -0.029005228283614737
    -0.46562265437810535
    -0.9433567169983137
    -0.6489745531369242
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    re for regular expressions

    -
    -
    -
    -
    -
    -
    -
    -

    Searching occurences

    -
    -
    -
    -
    -
    -
    In [13]:
    -
    -
    -
    import re
    -
    -secret_code = 'qwret 8sfg12f5 fd09f_df'
    -# "r" at the beginning means raw format, use it with regular expression patterns
    -search_pattern = r'(g12)' 
    -
    -match = re.search(search_pattern, secret_code)
    -print('match: {}'.format(match))
    -print('match.group(): {}'.format(match.group()))
    -
    -numbers_pattern = r'[0-9]'
    -numbers_match = re.findall(numbers_pattern, secret_code)
    -print('numbers: {}'.format(numbers_match))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    match: <_sre.SRE_Match object; span=(9, 12), match='g12'>
    -match.group(): g12
    -numbers: ['8', '1', '2', '5', '0', '9']
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Variable validation

    -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    import re
    -
    -def validate_only_lower_case_letters(to_validate):
    -    pattern = r'^[a-z]+$'
    -    return bool(re.match(pattern, to_validate))
    -
    -print(validate_only_lower_case_letters('thisshouldbeok'))
    -print(validate_only_lower_case_letters('thisshould notbeok'))
    -print(validate_only_lower_case_letters('Thisshouldnotbeok'))
    -print(validate_only_lower_case_letters('thisshouldnotbeok1'))
    -print(validate_only_lower_case_letters(''))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    True
    -False
    -False
    -False
    -False
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/strings.html b/notebooks/beginner/html/strings.html deleted file mode 100644 index 39d0fe1..0000000 --- a/notebooks/beginner/html/strings.html +++ /dev/null @@ -1,12711 +0,0 @@ - - - -tmp_strings - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    my_string = 'Python is my favorite programming language!'
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [2]:
    -
    -
    -
    my_string
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[2]:
    - - - - -
    -
    'Python is my favorite programming language!'
    -
    - -
    - -
    -
    - -
    -
    -
    -
    In [3]:
    -
    -
    -
    type(my_string)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[3]:
    - - - - -
    -
    str
    -
    - -
    - -
    -
    - -
    -
    -
    -
    In [4]:
    -
    -
    -
    len(my_string)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[4]:
    - - - - -
    -
    43
    -
    - -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Respecting PEP8 with long strings

    -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    long_story = ('Lorem ipsum dolor sit amet, consectetur adipiscing elit.' 
    -              'Pellentesque eget tincidunt felis. Ut ac vestibulum est.' 
    -              'In sed ipsum sit amet sapien scelerisque bibendum. Sed ' 
    -              'sagittis purus eu diam fermentum pellentesque.')
    -long_story
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[5]:
    - - - - -
    -
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit.Pellentesque eget tincidunt felis. Ut ac vestibulum est.In sed ipsum sit amet sapien scelerisque bibendum. Sed sagittis purus eu diam fermentum pellentesque.'
    -
    - -
    - -
    -
    - -
    -
    -
    -
    -
    -

    str.replace()

    -
    -
    -
    -
    -
    -
    -
    -

    If you don't know how it works, you can always check the help:

    - -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    help(str.replace)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Help on method_descriptor:
    -
    -replace(...)
    -    S.replace(old, new[, count]) -> str
    -    
    -    Return a copy of S with all occurrences of substring
    -    old replaced by new.  If the optional argument count is
    -    given, only the first count occurrences are replaced.
    -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    This will not modify my_string because replace is not done in-place.

    - -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    my_string.replace('a', '?')
    -print(my_string)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Python is my favorite programming language!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    You have to store the return value of replace instead.

    - -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    my_modified_string = my_string.replace('is', 'will be')
    -print(my_modified_string)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Python will be my favorite programming language!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    str.format()

    -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    secret = '{} is cool'.format('Python')
    -print(secret)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Python is cool
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [10]:
    -
    -
    -
    print('My name is {} {}, you can call me {}.'.format('John', 'Doe', 'John'))
    -# is the same as:
    -print('My name is {first} {family}, you can call me {first}.'.format(first='John', family='Doe'))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    My name is John Doe, you can call me John.
    -My name is John Doe, you can call me John.
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    str.join()

    -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    pandas = 'pandas'
    -numpy = 'numpy'
    -requests = 'requests'
    -cool_python_libs = ', '.join([pandas, numpy, requests])
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [12]:
    -
    -
    -
    print('Some cool python libraries: {}'.format(cool_python_libs))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Some cool python libraries: pandas, numpy, requests
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Alternatives (not as Pythonic and slower):

    - -
    -
    -
    -
    -
    -
    In [13]:
    -
    -
    -
    cool_python_libs = pandas + ', ' + numpy + ', ' + requests
    -print('Some cool python libraries: {}'.format(cool_python_libs))
    -
    -cool_python_libs = pandas
    -cool_python_libs += ', ' + numpy
    -cool_python_libs += ', ' + requests
    -print('Some cool python libraries: {}'.format(cool_python_libs))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Some cool python libraries: pandas, numpy, requests
    -Some cool python libraries: pandas, numpy, requests
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    str.upper(), str.lower(), str.title()

    -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    mixed_case = 'PyTHoN hackER'
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [15]:
    -
    -
    -
    mixed_case.upper()
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[15]:
    - - - - -
    -
    'PYTHON HACKER'
    -
    - -
    - -
    -
    - -
    -
    -
    -
    In [16]:
    -
    -
    -
    mixed_case.lower()
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[16]:
    - - - - -
    -
    'python hacker'
    -
    - -
    - -
    -
    - -
    -
    -
    -
    In [17]:
    -
    -
    -
    mixed_case.title()
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[17]:
    - - - - -
    -
    'Python Hacker'
    -
    - -
    - -
    -
    - -
    -
    -
    -
    -
    -

    str.strip()

    -
    -
    -
    -
    -
    -
    In [18]:
    -
    -
    -
    ugly_formatted = ' \n \t Some story to tell '
    -stripped = ugly_formatted.strip()
    -
    -print('ugly: {}'.format(ugly_formatted))
    -print('stripped: {}'.format(ugly_formatted.strip()))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ugly:  
    - 	 Some story to tell 
    -stripped: Some story to tell
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    str.split()

    -
    -
    -
    -
    -
    -
    In [19]:
    -
    -
    -
    sentence = 'three different words'
    -words = sentence.split()
    -print(words)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ['three', 'different', 'words']
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [20]:
    -
    -
    -
    type(words)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    Out[20]:
    - - - - -
    -
    list
    -
    - -
    - -
    -
    - -
    -
    -
    -
    In [21]:
    -
    -
    -
    secret_binary_data = '01001,101101,11100000'
    -binaries = secret_binary_data.split(',')
    -print(binaries)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ['01001', '101101', '11100000']
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Calling multiple methods in a row

    -
    -
    -
    -
    -
    -
    In [22]:
    -
    -
    -
    ugly_mixed_case = '   ThIS LooKs BAd '
    -pretty = ugly_mixed_case.strip().lower().replace('bad', 'good')
    -print(pretty)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    this looks good
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Note that execution order is from left to right. Thus, this won't work:

    - -
    -
    -
    -
    -
    -
    In [23]:
    -
    -
    -
    pretty = ugly_mixed_case.replace('bad', 'good').strip().lower()
    -print(pretty)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    this looks bad
    -
    -
    -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [24]:
    -
    -
    -
    two_lines = 'First line\nSecond line'
    -print(two_lines)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    First line
    -Second line
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [25]:
    -
    -
    -
    indented = '\tThis will be indented'
    -print(indented)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    	This will be indented
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/testing1.html b/notebooks/beginner/html/testing1.html deleted file mode 100644 index 18e5eef..0000000 --- a/notebooks/beginner/html/testing1.html +++ /dev/null @@ -1,12007 +0,0 @@ - - - -tmp_testing1 - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Testing with pytest - part 1

    -
    -
    -
    -
    -
    -
    -
    -

    Why to write tests?

      -
    • Who wants to perform manual testing?
    • -
    • When you fix a bug or add a new feature, tests are a way to verify that you did not break anything on the way
    • -
    • If you have clear requirements, you can have matching test(s) for each requirement
    • -
    • You don't have to be afraid of refactoring
    • -
    • Tests document your implementation - they show other people use cases of your implementation
    • -
    • This list is endless...
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Test-driven development aka TDD

    In short, the basic idea of TDD is to write tests before writing the actual implementation. Maybe the most significant benefit of the approach is that the developer focuses on writing tests which match with what the program should do. Whereas if the tests are written after the actual implementation, there is a high risk for rushing tests which just show green light for the already written logic.

    -

    Tests are first class citizens in modern, agile software development, which is why it's important to start thinking TDD early during your Python learning path.

    -

    The workflow of TDD can be summarized as follows:

    -
      -
    1. Add a test case(s) for the change / feature / bug fix you are going to implement
    2. -
    3. Run all tests and check that the new one fails
    4. -
    5. Implement required changes
    6. -
    7. Run tests and verify that all pass
    8. -
    9. Refactor
    10. -
    - -
    -
    -
    -
    -
    -
    -
    -

    Running pytest inside notebooks

    These are the steps required to run pytest inside Jupyter cells. You can copy the content of this cell to the top of your notebook which contains tests.

    - -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    # Let's make sure pytest and ipytest packages are installed
    -# ipytest is required for running pytest inside Jupyter notebooks
    -import sys
    -!{sys.executable} -m pip install pytest
    -!{sys.executable} -m pip install ipytest
    -
    -import ipytest.magics
    -import pytest
    -
    -# Filename has to be set explicitly for ipytest 
    -__file__ = 'testing1.ipynb'
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Requirement already satisfied: pytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (3.5.0)
    -Requirement already satisfied: more-itertools>=4.0.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (4.1.0)
    -Requirement already satisfied: setuptools in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (39.0.1)
    -Requirement already satisfied: attrs>=17.4.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (17.4.0)
    -Requirement already satisfied: six>=1.10.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.11.0)
    -Requirement already satisfied: py>=1.5.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.5.3)
    -Requirement already satisfied: pluggy<0.7,>=0.5 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (0.6.0)
    -Requirement already satisfied: ipytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (0.2.2)
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    pytest test cases

    Let's consider we have a function called sum_of_three_numbers for which we want to write a test.

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    # This would be in your e.g. implementation.py
    -def sum_of_three_numbers(num1, num2, num3):
    -    return num1 + num2 + num3
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Pytest test cases are actually quite similar as you have already seen in the exercises. Most of the exercises are structured like pytest test cases by dividing each exercise into three cells:

    -
      -
    1. Setup the variables used in the test
    2. -
    3. Your implementation
    4. -
    5. Verify that your implementation does what is wanted by using assertions
    6. -
    -

    See the example test case below to see the similarities between the exercises and common structure of test cases.

    - -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    %%run_pytest[clean]
    -# Mention this at the top of cells which contain test(s)
    -# This is only required for running pytest in Jupyter notebooks
    -
    -
    -# This would be in your test_implementation.py
    -def test_sum_of_three_numbers():
    -    # 1. Setup the variables used in the test
    -    num1 = 2
    -    num2 = 3
    -    num3 = 5
    -    
    -    # 2. Call the functionality you want to test
    -    result = sum_of_three_numbers(num1, num2, num3)
    -    
    -    # 3. Verify that the outcome is expected
    -    assert result == 10
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    =============================================================== test session starts ================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 1 item
    -
    -testing1.py .                                                                                                                                [100%]
    -
    -============================================================= 1 passed in 0.01 seconds =============================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Now go ahead and change the line assert result == 10 such that the assertion fails to see the output of a failed test.

    - -
    -
    -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/testing2.html b/notebooks/beginner/html/testing2.html deleted file mode 100644 index 4e4ab01..0000000 --- a/notebooks/beginner/html/testing2.html +++ /dev/null @@ -1,12097 +0,0 @@ - - - -tmp_testing2 - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Testing with pytest - part 2

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    # Let's make sure pytest and ipytest packages are installed
    -# ipytest is required for running pytest inside Jupyter notebooks
    -import sys
    -!{sys.executable} -m pip install pytest
    -!{sys.executable} -m pip install ipytest
    -
    -import ipytest.magics
    -import pytest
    -__file__ = 'testing2.ipynb'
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Requirement already satisfied: pytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (3.5.0)
    -Requirement already satisfied: setuptools in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (39.0.1)
    -Requirement already satisfied: attrs>=17.4.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (17.4.0)
    -Requirement already satisfied: more-itertools>=4.0.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (4.1.0)
    -Requirement already satisfied: pluggy<0.7,>=0.5 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (0.6.0)
    -Requirement already satisfied: py>=1.5.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.5.3)
    -Requirement already satisfied: six>=1.10.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.11.0)
    -Requirement already satisfied: ipytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (0.2.2)
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    @pytest.fixture

    Let's consider we have an implemention of Person class which we want to test.

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    # This would be e.g. in person.py
    -class Person:
    -    def __init__(self, first_name, last_name, age):
    -        self.first_name = first_name
    -        self.last_name = last_name
    -        self.age = age
    -    
    -    @property
    -    def full_name(self):
    -        return '{} {}'.format(self.first_name, self.last_name)
    -    
    -    @property
    -    def as_dict(self):
    -        return {'name': self.full_name, 'age': self.age}
    -        
    -    def increase_age(self, years):
    -        if years < 0:
    -            raise ValueError('Can not make people younger :(')
    -        self.age += years
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    You can easily create resusable testing code by using pytest fixtures. If you introduce your fixtures inside conftest.py, the fixtures are available for all your test cases. In general, the location of conftest.py is at the root of your tests directory.

    - -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    # This would be in either conftest.py or test_person.py
    -@pytest.fixture()
    -def default_person():
    -    person = Person(first_name='John', last_name='Doe', age=82)
    -    return person
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Then you can utilize default_person fixture in the actual test cases.

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    %%run_pytest[clean]
    -
    -# These would be in test_person.py
    -def test_full_name(default_person): # Note: we use fixture as an argument of the test case
    -    result = default_person.full_name
    -    assert result == 'John Doe'
    -    
    -    
    -def test_as_dict(default_person):
    -    expected = {'name': 'John Doe', 'age': 82}
    -    result = default_person.as_dict
    -    assert result == expected
    -    
    -    
    -def test_increase_age(default_person):
    -    default_person.increase_age(1)
    -    assert default_person.age == 83
    -    
    -    default_person.increase_age(10)
    -    assert default_person.age == 93
    -    
    -    
    -def test_increase_age_with_negative_number(default_person):
    -    with pytest.raises(ValueError):
    -        default_person.increase_age(-1)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================================= test session starts =================================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 4 items
    -
    -testing2.py ....                                                                                                                                                                                                [100%]
    -
    -============================================================================================== 4 passed in 0.02 seconds ===============================================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    By using a fixture, we could use the same default_person for all our four test cases!

    -

    In the test_increase_age_with_negative_number we used pytest.raises to verify that an exception is raised.

    - -
    -
    -
    -
    -
    -
    -
    -

    @pytest.mark.parametrize

    Sometimes you want to test the same functionality with multiple different inputs. pytest.mark.parametrize is your solution for defining multiple different inputs with expected outputs. Let's consider the following implementation of replace_names function.

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    # This would be e.g. in string_manipulate.py
    -def replace_names(original_str, new_name):
    -    """Replaces names (uppercase words) of original_str by new_name"""
    -    words = original_str.split()
    -    manipulated_words = [new_name if w.istitle() else w for w in words]
    -    return ' '.join(manipulated_words)
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    We can test the replace_names function with multiple inputs by using pytest.mark.parametrize.

    - -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    %%run_pytest[clean]
    -
    -# This would be in your test module
    -@pytest.mark.parametrize("original,new_name,expected", [
    -        ('this is Lisa', 'John Doe', 'this is John Doe'),
    -        ('how about Frank and Amy', 'John', 'how about John and John'),
    -        ('no names here', 'John Doe', 'no names here'),
    -    ])
    -def test_replace_names(original, new_name, expected):
    -    result = replace_names(original, new_name)
    -    assert result == expected
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================================= test session starts =================================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 3 items
    -
    -testing2.py ...                                                                                                                                                                                                 [100%]
    -
    -================================================================================================== warnings summary ===================================================================================================
    -None
    -  Module already imported so cannot be rewritten: nbval
    -
    --- Docs: http://doc.pytest.org/en/latest/warnings.html
    -======================================================================================== 3 passed, 1 warnings in 0.03 seconds =========================================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/html/venv.html b/notebooks/beginner/html/venv.html deleted file mode 100644 index 4444ed7..0000000 --- a/notebooks/beginner/html/venv.html +++ /dev/null @@ -1,11874 +0,0 @@ - - - -tmp_venv - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Virtual environment

    When working with Python projects, best practice is to have a separate virtual environment for each of them.

    -

    Each virtual environment has its own Python binary. When you install some Python package into your virtual environment, it'll be installed only into that specific environment. This means that you can have different versions of a single Python package in different virtual environments in the same machine. Virtual environments are also useful if you need to use different Python versions in your projects.

    - -
    -
    -
    -
    -
    -
    -
    -

    venv

    -
    -
    -
    -
    -
    -
    -
    -

    Creating new virtual environment

    You can create all your virtual environments into a single directory (for example, .virtualenvs directory inside your home folder). This makes them easier to find.

    - -
    -
    -
    -
    -
    -
    -
    -

    python3 -m venv /path/to/new/environment

    -

    or

    -

    path/to/your/python -m venv /path/to/new/environment

    - -
    -
    -
    -
    -
    -
    -
    -

    Activating the virtual environment

    -
    -
    -
    -
    -
    -
    -
    -

    Windows: path_to_virtual_env\Scripts\activate.bat
    -Posix: source path_to_virtual_env/bin/activate

    - -
    -
    -
    -
    -
    -
    -
    -

    Installing packages

    After activating the newly created virtual environment, you can install new packages by using pip. For example if you want to install pytest:

    -

    python -m pip install pytest

    -

    it'll be installed into path_to_virtual_env/lib//site-packages. Note that the path to site-packages maybe slightly different depending on the operating system you are using.

    -

    You can list the installed packages and their versions by running:

    -

    python -m pip freeze

    - -
    -
    -
    -
    -
    - - - - - - diff --git a/notebooks/beginner/notebooks/strings.ipynb b/notebooks/beginner/notebooks/01_strings.ipynb similarity index 75% rename from notebooks/beginner/notebooks/strings.ipynb rename to notebooks/beginner/notebooks/01_strings.ipynb index c87bba4..fdbb05a 100644 --- a/notebooks/beginner/notebooks/strings.ipynb +++ b/notebooks/beginner/notebooks/01_strings.ipynb @@ -13,7 +13,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_string = 'Python is my favorite programming language!'" + "my_string = \"Python is my favorite programming language!\"" ] }, { @@ -56,10 +56,12 @@ "metadata": {}, "outputs": [], "source": [ - "long_story = ('Lorem ipsum dolor sit amet, consectetur adipiscing elit.' \n", - " 'Pellentesque eget tincidunt felis. Ut ac vestibulum est.' \n", - " 'In sed ipsum sit amet sapien scelerisque bibendum. Sed ' \n", - " 'sagittis purus eu diam fermentum pellentesque.')\n", + "long_story = (\n", + " \"Lorem ipsum dolor sit amet, consectetur adipiscing elit.\"\n", + " \"Pellentesque eget tincidunt felis. Ut ac vestibulum est.\"\n", + " \"In sed ipsum sit amet sapien scelerisque bibendum. Sed \"\n", + " \"sagittis purus eu diam fermentum pellentesque.\"\n", + ")\n", "long_story" ] }, @@ -99,7 +101,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_string.replace('a', '?')\n", + "my_string.replace(\"a\", \"?\")\n", "print(my_string)" ] }, @@ -116,7 +118,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_modified_string = my_string.replace('is', 'will be')\n", + "my_modified_string = my_string.replace(\"is\", \"will be\")\n", "print(my_modified_string)" ] }, @@ -133,7 +135,7 @@ "metadata": {}, "outputs": [], "source": [ - "secret = '{} is cool'.format('Python')\n", + "secret = \"{} is cool\".format(\"Python\")\n", "print(secret)" ] }, @@ -143,9 +145,13 @@ "metadata": {}, "outputs": [], "source": [ - "print('My name is {} {}, you can call me {}.'.format('John', 'Doe', 'John'))\n", + "print(\"My name is {} {}, you can call me {}.\".format(\"John\", \"Doe\", \"John\"))\n", "# is the same as:\n", - "print('My name is {first} {family}, you can call me {first}.'.format(first='John', family='Doe'))" + "print(\n", + " \"My name is {first} {family}, you can call me {first}.\".format(\n", + " first=\"John\", family=\"Doe\"\n", + " )\n", + ")" ] }, { @@ -161,10 +167,10 @@ "metadata": {}, "outputs": [], "source": [ - "pandas = 'pandas'\n", - "numpy = 'numpy'\n", - "requests = 'requests'\n", - "cool_python_libs = ', '.join([pandas, numpy, requests])" + "pandas = \"pandas\"\n", + "numpy = \"numpy\"\n", + "requests = \"requests\"\n", + "cool_python_libs = \", \".join([pandas, numpy, requests])" ] }, { @@ -173,7 +179,7 @@ "metadata": {}, "outputs": [], "source": [ - "print('Some cool python libraries: {}'.format(cool_python_libs))" + "print(\"Some cool python libraries: {}\".format(cool_python_libs))" ] }, { @@ -189,13 +195,13 @@ "metadata": {}, "outputs": [], "source": [ - "cool_python_libs = pandas + ', ' + numpy + ', ' + requests\n", - "print('Some cool python libraries: {}'.format(cool_python_libs))\n", + "cool_python_libs = pandas + \", \" + numpy + \", \" + requests\n", + "print(\"Some cool python libraries: {}\".format(cool_python_libs))\n", "\n", "cool_python_libs = pandas\n", - "cool_python_libs += ', ' + numpy\n", - "cool_python_libs += ', ' + requests\n", - "print('Some cool python libraries: {}'.format(cool_python_libs))" + "cool_python_libs += \", \" + numpy\n", + "cool_python_libs += \", \" + requests\n", + "print(\"Some cool python libraries: {}\".format(cool_python_libs))" ] }, { @@ -211,7 +217,7 @@ "metadata": {}, "outputs": [], "source": [ - "mixed_case = 'PyTHoN hackER'" + "mixed_case = \"PyTHoN hackER\"" ] }, { @@ -254,11 +260,11 @@ "metadata": {}, "outputs": [], "source": [ - "ugly_formatted = ' \\n \\t Some story to tell '\n", + "ugly_formatted = \" \\n \\t Some story to tell \"\n", "stripped = ugly_formatted.strip()\n", "\n", - "print('ugly: {}'.format(ugly_formatted))\n", - "print('stripped: {}'.format(ugly_formatted.strip()))" + "print(\"ugly: {}\".format(ugly_formatted))\n", + "print(\"stripped: {}\".format(ugly_formatted.strip()))" ] }, { @@ -274,7 +280,7 @@ "metadata": {}, "outputs": [], "source": [ - "sentence = 'three different words'\n", + "sentence = \"three different words\"\n", "words = sentence.split()\n", "print(words)" ] @@ -294,8 +300,8 @@ "metadata": {}, "outputs": [], "source": [ - "secret_binary_data = '01001,101101,11100000'\n", - "binaries = secret_binary_data.split(',')\n", + "secret_binary_data = \"01001,101101,11100000\"\n", + "binaries = secret_binary_data.split(\",\")\n", "print(binaries)" ] }, @@ -312,8 +318,8 @@ "metadata": {}, "outputs": [], "source": [ - "ugly_mixed_case = ' ThIS LooKs BAd '\n", - "pretty = ugly_mixed_case.strip().lower().replace('bad', 'good')\n", + "ugly_mixed_case = \" ThIS LooKs BAd \"\n", + "pretty = ugly_mixed_case.strip().lower().replace(\"bad\", \"good\")\n", "print(pretty)" ] }, @@ -330,7 +336,7 @@ "metadata": {}, "outputs": [], "source": [ - "pretty = ugly_mixed_case.replace('bad', 'good').strip().lower()\n", + "pretty = ugly_mixed_case.replace(\"bad\", \"good\").strip().lower()\n", "print(pretty)" ] }, @@ -347,7 +353,7 @@ "metadata": {}, "outputs": [], "source": [ - "two_lines = 'First line\\nSecond line'\n", + "two_lines = \"First line\\nSecond line\"\n", "print(two_lines)" ] }, @@ -357,7 +363,7 @@ "metadata": {}, "outputs": [], "source": [ - "indented = '\\tThis will be indented'\n", + "indented = \"\\tThis will be indented\"\n", "print(indented)" ] } diff --git a/notebooks/beginner/notebooks/numbers.ipynb b/notebooks/beginner/notebooks/02_numbers.ipynb similarity index 82% rename from notebooks/beginner/notebooks/numbers.ipynb rename to notebooks/beginner/notebooks/02_numbers.ipynb index 95f45c5..45af1a7 100644 --- a/notebooks/beginner/notebooks/numbers.ipynb +++ b/notebooks/beginner/notebooks/02_numbers.ipynb @@ -17,13 +17,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "scrolled": true - }, + "metadata": {}, "outputs": [], "source": [ "my_int = 6\n", - "print('value: {}, type: {}'.format(my_int, type(my_int)))" + "print(\"value: {}, type: {}\".format(my_int, type(my_int)))" ] }, { @@ -36,13 +34,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "scrolled": true - }, + "metadata": {}, "outputs": [], "source": [ "my_float = float(my_int)\n", - "print('value: {}, type: {}'.format(my_float, type(my_float)))" + "print(\"value: {}, type: {}\".format(my_float, type(my_float)))" ] }, { @@ -72,9 +68,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "scrolled": true - }, + "metadata": {}, "outputs": [], "source": [ "val = 0.1 + 0.1 + 0.1\n", @@ -113,7 +107,7 @@ "metadata": {}, "outputs": [], "source": [ - "2 ** 3" + "2**3" ] }, { @@ -127,9 +121,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "scrolled": true - }, + "metadata": {}, "outputs": [], "source": [ "from decimal import Decimal" @@ -138,27 +130,23 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "scrolled": true - }, + "metadata": {}, "outputs": [], "source": [ "from_float = Decimal(0.1)\n", - "from_str = Decimal('0.1')\n", - "print('from float: {}\\nfrom string: {}'.format(from_float, from_str))" + "from_str = Decimal(\"0.1\")\n", + "print(\"from float: {}\\nfrom string: {}\".format(from_float, from_str))" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "scrolled": true - }, + "metadata": {}, "outputs": [], "source": [ - "my_decimal = Decimal('0.1')\n", + "my_decimal = Decimal(\"0.1\")\n", "sum_of_decimals = my_decimal + my_decimal + my_decimal\n", - "print(sum_of_decimals == Decimal('0.3'))" + "print(sum_of_decimals == Decimal(\"0.3\"))" ] }, { @@ -175,7 +163,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(1 + 2**2 * 3 / 6) # 1 + 4 * 3 / 6 == 1 + 12 / 6 == 1 + 2\n", + "print(1 + 2**2 * 3 / 6) # 1 + 4 * 3 / 6 == 1 + 12 / 6 == 1 + 2\n", "print((1 + 2**2) * 3 / 6)" ] } diff --git a/notebooks/beginner/notebooks/conditionals.ipynb b/notebooks/beginner/notebooks/03_conditionals.ipynb similarity index 58% rename from notebooks/beginner/notebooks/conditionals.ipynb rename to notebooks/beginner/notebooks/03_conditionals.ipynb index 3850f20..9600954 100644 --- a/notebooks/beginner/notebooks/conditionals.ipynb +++ b/notebooks/beginner/notebooks/03_conditionals.ipynb @@ -1,5 +1,30 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import HTML\n", + "\n", + "HTML(\n", + " \"\"\"\n", + "
    \"\"\"\n", + ")" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -27,7 +52,7 @@ "metadata": {}, "outputs": [], "source": [ - "print('type of True and False: {}'.format(type(True)))" + "print(\"type of True and False: {}\".format(type(True)))" ] }, { @@ -36,9 +61,9 @@ "metadata": {}, "outputs": [], "source": [ - "print('0: {}, 1: {}'.format(bool(0), bool(1)))\n", - "print('empty list: {}, list with values: {}'.format(bool([]), bool(['woop'])))\n", - "print('empty dict: {}, dict with values: {}'.format(bool({}), bool({'Python': 'cool'})))" + "print(\"0: {}, 1: {}\".format(bool(0), bool(1)))\n", + "print(\"empty list: {}, list with values: {}\".format(bool([]), bool([\"woop\"])))\n", + "print(\"empty dict: {}, dict with values: {}\".format(bool({}), bool({\"Python\": \"cool\"})))" ] }, { @@ -54,16 +79,16 @@ "metadata": {}, "outputs": [], "source": [ - "print('1 == 0: {}'.format(1 == 0))\n", - "print('1 != 0: {}'.format(1 != 0))\n", - "print('1 > 0: {}'.format(1 > 0))\n", - "print('1 > 1: {}'.format(1 > 1))\n", - "print('1 < 0: {}'.format(1 < 0))\n", - "print('1 < 1: {}'.format(1 < 1))\n", - "print('1 >= 0: {}'.format(1 >= 0))\n", - "print('1 >= 1: {}'.format(1 >= 1))\n", - "print('1 <= 0: {}'.format(1 <= 0))\n", - "print('1 <= 1: {}'.format(1 <= 1))" + "print(\"1 == 0: {}\".format(1 == 0))\n", + "print(\"1 != 0: {}\".format(1 != 0))\n", + "print(\"1 > 0: {}\".format(1 > 0))\n", + "print(\"1 > 1: {}\".format(1 > 1))\n", + "print(\"1 < 0: {}\".format(1 < 0))\n", + "print(\"1 < 1: {}\".format(1 < 1))\n", + "print(\"1 >= 0: {}\".format(1 >= 0))\n", + "print(\"1 >= 1: {}\".format(1 >= 1))\n", + "print(\"1 <= 0: {}\".format(1 <= 0))\n", + "print(\"1 <= 1: {}\".format(1 <= 1))" ] }, { @@ -79,7 +104,7 @@ "metadata": {}, "outputs": [], "source": [ - "print('1 <= 2 <= 3: {}'.format(1 <= 2 <= 3))" + "print(\"1 <= 2 <= 3: {}\".format(1 <= 2 <= 3))" ] }, { @@ -107,8 +132,8 @@ "metadata": {}, "outputs": [], "source": [ - "print('Python and java are both cool: {}'.format(python_is_cool and java_is_cool))\n", - "print('secret_value and python_is_cool: {}'.format(secret_value and python_is_cool))" + "print(\"Python and java are both cool: {}\".format(python_is_cool and java_is_cool))\n", + "print(\"secret_value and python_is_cool: {}\".format(secret_value and python_is_cool))" ] }, { @@ -117,8 +142,8 @@ "metadata": {}, "outputs": [], "source": [ - "print('Python or java is cool: {}'.format(python_is_cool or java_is_cool))\n", - "print('1 >= 1.1 or 2 < float(\"1.4\"): {}'.format(1 >= 1.1 or 2 < float('1.4')))" + "print(\"Python or java is cool: {}\".format(python_is_cool or java_is_cool))\n", + "print('1 >= 1.1 or 2 < float(\"1.4\"): {}'.format(1 >= 1.1 or 2 < float(\"1.4\")))" ] }, { @@ -127,7 +152,7 @@ "metadata": {}, "outputs": [], "source": [ - "print('Java is not cool: {}'.format(not java_is_cool))" + "print(\"Java is not cool: {}\".format(not java_is_cool))" ] }, { @@ -143,8 +168,8 @@ "metadata": {}, "outputs": [], "source": [ - "print(bool(not java_is_cool or secret_value and python_is_cool or empty_list))\n", - "print(bool(not (java_is_cool or secret_value and python_is_cool or empty_list)))" + "print(bool(not java_is_cool or secret_value and python_is_cool or empty_list))\n", + "print(bool(not (java_is_cool or secret_value and python_is_cool or empty_list)))" ] }, { @@ -162,10 +187,10 @@ "source": [ "statement = True\n", "if statement:\n", - " print('statement is True')\n", - " \n", + " print(\"statement is True\")\n", + "\n", "if not statement:\n", - " print('statement is not True')" + " print(\"statement is not True\")" ] }, { @@ -177,7 +202,7 @@ "empty_list = []\n", "# With if and elif, conversion to `bool` is implicit\n", "if empty_list:\n", - " print('empty list will not evaluate to True') # this won't be executed" + " print(\"empty list will not evaluate to True\") # this won't be executed" ] }, { @@ -188,7 +213,7 @@ "source": [ "val = 3\n", "if 0 <= val < 1 or val == 3:\n", - " print('Value is positive and less than one or value is three')" + " print(\"Value is positive and less than one or value is three\")" ] }, { @@ -206,9 +231,9 @@ "source": [ "my_dict = {}\n", "if my_dict:\n", - " print('there is something in my dict')\n", + " print(\"there is something in my dict\")\n", "else:\n", - " print('my dict is empty :(')" + " print(\"my dict is empty :(\")" ] }, { @@ -226,11 +251,11 @@ "source": [ "val = 88\n", "if val >= 100:\n", - " print('value is equal or greater than 100')\n", + " print(\"value is equal or greater than 100\")\n", "elif val > 10:\n", - " print('value is greater than 10 but less than 100')\n", + " print(\"value is greater than 10 but less than 100\")\n", "else:\n", - " print('value is equal or less than 10')" + " print(\"value is equal or less than 10\")" ] }, { @@ -246,18 +271,18 @@ "metadata": {}, "outputs": [], "source": [ - "greeting = 'Hello fellow Pythonista!'\n", - "language = 'Italian'\n", + "greeting = \"Hello fellow Pythonista!\"\n", + "language = \"Italian\"\n", + "\n", + "if language == \"Swedish\":\n", + " greeting = \"Hejsan!\"\n", + "elif language == \"Finnish\":\n", + " greeting = \"Latua perkele!\"\n", + "elif language == \"Spanish\":\n", + " greeting = \"Hola!\"\n", + "elif language == \"German\":\n", + " greeting = \"Guten Tag!\"\n", "\n", - "if language == 'Swedish':\n", - " greeting = 'Hejsan!'\n", - "elif language == 'Finnish':\n", - " greeting = 'Latua perkele!'\n", - "elif language == 'Spanish':\n", - " greeting = 'Hola!'\n", - "elif language == 'German':\n", - " greeting = 'Guten Tag!'\n", - " \n", "print(greeting)" ] }, @@ -271,7 +296,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -285,7 +310,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.10.3" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/lists.ipynb b/notebooks/beginner/notebooks/04_lists.ipynb similarity index 75% rename from notebooks/beginner/notebooks/lists.ipynb rename to notebooks/beginner/notebooks/04_lists.ipynb index 0a08876..2820efd 100644 --- a/notebooks/beginner/notebooks/lists.ipynb +++ b/notebooks/beginner/notebooks/04_lists.ipynb @@ -14,7 +14,7 @@ "outputs": [], "source": [ "my_empty_list = []\n", - "print('empty list: {}, type: {}'.format(my_empty_list, type(my_empty_list)))" + "print(\"empty list: {}, type: {}\".format(my_empty_list, type(my_empty_list)))" ] }, { @@ -24,8 +24,8 @@ "outputs": [], "source": [ "list_of_ints = [1, 2, 6, 7]\n", - "list_of_misc = [0.2, 5, 'Python', 'is', 'still fun', '!']\n", - "print('lengths: {} and {}'.format(len(list_of_ints), len(list_of_misc)))" + "list_of_misc = [0.2, 5, \"Python\", \"is\", \"still fun\", \"!\"]\n", + "print(\"lengths: {} and {}\".format(len(list_of_ints), len(list_of_misc)))" ] }, { @@ -41,7 +41,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_list = ['Python', 'is', 'still', 'cool']\n", + "my_list = [\"Python\", \"is\", \"still\", \"cool\"]\n", "print(my_list[0])\n", "print(my_list[3])" ] @@ -53,8 +53,8 @@ "outputs": [], "source": [ "coordinates = [[12.0, 13.3], [0.6, 18.0], [88.0, 1.1]] # two dimensional\n", - "print('first coordinate: {}'.format(coordinates[0]))\n", - "print('second element of first coordinate: {}'.format(coordinates[0][1]))" + "print(\"first coordinate: {}\".format(coordinates[0]))\n", + "print(\"second element of first coordinate: {}\".format(coordinates[0][1]))" ] }, { @@ -92,9 +92,9 @@ "metadata": {}, "outputs": [], "source": [ - "languages = ['Java', 'C++', 'Go', 'Python', 'JavaScript']\n", - "if 'Python' in languages:\n", - " print('Python is there!')" + "languages = [\"Java\", \"C++\", \"Go\", \"Python\", \"JavaScript\"]\n", + "if \"Python\" in languages:\n", + " print(\"Python is there!\")" ] }, { @@ -104,7 +104,7 @@ "outputs": [], "source": [ "if 6 not in [1, 2, 3, 7]:\n", - " print('number 6 is not present')" + " print(\"number 6 is not present\")" ] }, { @@ -123,7 +123,7 @@ "original = [1, 2, 3]\n", "modified = original\n", "modified[0] = 99\n", - "print('original: {}, modified: {}'.format(original, modified))" + "print(\"original: {}, modified: {}\".format(original, modified))" ] }, { @@ -140,11 +140,11 @@ "outputs": [], "source": [ "original = [1, 2, 3]\n", - "modified = list(original) # Note list() \n", + "modified = list(original) # Note list()\n", "# Alternatively, you can use copy method\n", "# modified = original.copy()\n", "modified[0] = 99\n", - "print('original: {}, modified: {}'.format(original, modified))" + "print(\"original: {}, modified: {}\".format(original, modified))" ] }, { @@ -161,7 +161,7 @@ "outputs": [], "source": [ "my_list = [1]\n", - "my_list.append('ham')\n", + "my_list.append(\"ham\")\n", "print(my_list)" ] }, @@ -178,15 +178,15 @@ "metadata": {}, "outputs": [], "source": [ - "my_list = ['Python', 'is', 'sometimes', 'fun']\n", - "my_list.remove('sometimes')\n", + "my_list = [\"Python\", \"is\", \"sometimes\", \"fun\"]\n", + "my_list.remove(\"sometimes\")\n", "print(my_list)\n", "\n", "# If you are not sure that the value is in list, better to check first:\n", - "if 'Java' in my_list:\n", - " my_list.remove('Java')\n", + "if \"Java\" in my_list:\n", + " my_list.remove(\"Java\")\n", "else:\n", - " print('Java is not part of this story.')" + " print(\"Java is not part of this story.\")" ] }, { @@ -204,14 +204,14 @@ "source": [ "numbers = [8, 1, 6, 5, 10]\n", "numbers.sort()\n", - "print('numbers: {}'.format(numbers))\n", + "print(\"numbers: {}\".format(numbers))\n", "\n", "numbers.sort(reverse=True)\n", - "print('numbers reversed: {}'.format(numbers))\n", + "print(\"numbers reversed: {}\".format(numbers))\n", "\n", - "words = ['this', 'is', 'a', 'list', 'of', 'words']\n", + "words = [\"this\", \"is\", \"a\", \"list\", \"of\", \"words\"]\n", "words.sort()\n", - "print('words: {}'.format(words))" + "print(\"words: {}\".format(words))" ] }, { @@ -230,7 +230,7 @@ "source": [ "numbers = [8, 1, 6, 5, 10]\n", "sorted_numbers = sorted(numbers)\n", - "print('numbers: {}, sorted: {}'.format(numbers, sorted_numbers))" + "print(\"numbers: {}, sorted: {}\".format(numbers, sorted_numbers))" ] }, { @@ -246,10 +246,10 @@ "metadata": {}, "outputs": [], "source": [ - "first_list = ['beef', 'ham']\n", - "second_list = ['potatoes',1 ,3]\n", + "first_list = [\"beef\", \"ham\"]\n", + "second_list = [\"potatoes\", 1, 3]\n", "first_list.extend(second_list)\n", - "print('first: {}, second: {}'.format(first_list, second_list))" + "print(\"first: {}, second: {}\".format(first_list, second_list))" ] }, { @@ -268,11 +268,11 @@ "first = [1, 2, 3]\n", "second = [4, 5]\n", "first += second # same as: first = first + second\n", - "print('first: {}'.format(first))\n", + "print(\"first: {}\".format(first))\n", "\n", "# If you need a new list\n", "summed = first + second\n", - "print('summed: {}'.format(summed))" + "print(\"summed: {}\".format(summed))" ] }, { @@ -288,7 +288,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_list = ['a', 'b', 'ham']\n", + "my_list = [\"a\", \"b\", \"ham\"]\n", "my_list.reverse()\n", "print(my_list)" ] diff --git a/notebooks/beginner/notebooks/dictionaries.ipynb b/notebooks/beginner/notebooks/05_dictionaries.ipynb similarity index 66% rename from notebooks/beginner/notebooks/dictionaries.ipynb rename to notebooks/beginner/notebooks/05_dictionaries.ipynb index f1b4f39..97aa70c 100644 --- a/notebooks/beginner/notebooks/dictionaries.ipynb +++ b/notebooks/beginner/notebooks/05_dictionaries.ipynb @@ -15,7 +15,7 @@ "outputs": [], "source": [ "my_empty_dict = {} # alternative: my_empty_dict = dict()\n", - "print('dict: {}, type: {}'.format(my_empty_dict, type(my_empty_dict)))" + "print(\"dict: {}, type: {}\".format(my_empty_dict, type(my_empty_dict)))" ] }, { @@ -31,14 +31,14 @@ "metadata": {}, "outputs": [], "source": [ - "dict1 = {'value1': 1.6, 'value2': 10, 'name': 'John Doe'}\n", - "dict2 = dict(value1=1.6, value2=10, name='John Doe')\n", + "dict1 = {\"value1\": 1.6, \"value2\": 10, \"name\": \"John Doe\"}\n", + "dict2 = dict(value1=1.6, value2=10, name=\"John Doe\")\n", "\n", "print(dict1)\n", "print(dict2)\n", "\n", - "print('equal: {}'.format(dict1 == dict2))\n", - "print('length: {}'.format(len(dict1)))" + "print(\"equal: {}\".format(dict1 == dict2))\n", + "print(\"length: {}\".format(len(dict1)))" ] }, { @@ -54,9 +54,9 @@ "metadata": {}, "outputs": [], "source": [ - "print('keys: {}'.format(dict1.keys()))\n", - "print('values: {}'.format(dict1.values()))\n", - "print('items: {}'.format(dict1.items()))" + "print(\"keys: {}\".format(dict1.keys()))\n", + "print(\"values: {}\".format(dict1.values()))\n", + "print(\"items: {}\".format(dict1.items()))" ] }, { @@ -73,11 +73,11 @@ "outputs": [], "source": [ "my_dict = {}\n", - "my_dict['key1'] = 'value1'\n", - "my_dict['key2'] = 99\n", - "my_dict['key1'] = 'new value' # overriding existing value\n", + "my_dict[\"key1\"] = \"value1\"\n", + "my_dict[\"key2\"] = 99\n", + "my_dict[\"key1\"] = \"new value\" # overriding existing value\n", "print(my_dict)\n", - "print('value of key1: {}'.format(my_dict['key1']))" + "print(\"value of key1: {}\".format(my_dict[\"key1\"]))" ] }, { @@ -109,16 +109,16 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'key1': 'value1', 'key2': 99, 'keyX': 'valueX'}\n", - "del my_dict['keyX']\n", + "my_dict = {\"key1\": \"value1\", \"key2\": 99, \"keyX\": \"valueX\"}\n", + "del my_dict[\"keyX\"]\n", "print(my_dict)\n", "\n", "# Usually better to make sure that the key exists (see also pop() and popitem())\n", - "key_to_delete = 'my_key'\n", + "key_to_delete = \"my_key\"\n", "if key_to_delete in my_dict:\n", " del my_dict[key_to_delete]\n", "else:\n", - " print('{key} is not in {dictionary}'.format(key=key_to_delete, dictionary=my_dict))" + " print(\"{key} is not in {dictionary}\".format(key=key_to_delete, dictionary=my_dict))" ] }, { @@ -134,12 +134,12 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'ham': 'good', 'carrot': 'semi good'}\n", + "my_dict = {\"ham\": \"good\", \"carrot\": \"semi good\"}\n", "my_other_dict = my_dict\n", - "my_other_dict['carrot'] = 'super tasty'\n", - "my_other_dict['sausage'] = 'best ever'\n", - "print('my_dict: {}\\nother: {}'.format(my_dict, my_other_dict))\n", - "print('equal: {}'.format(my_dict == my_other_dict))" + "my_other_dict[\"carrot\"] = \"super tasty\"\n", + "my_other_dict[\"sausage\"] = \"best ever\"\n", + "print(\"my_dict: {}\\nother: {}\".format(my_dict, my_other_dict))\n", + "print(\"equal: {}\".format(my_dict == my_other_dict))" ] }, { @@ -155,11 +155,11 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'ham': 'good', 'carrot': 'semi good'}\n", + "my_dict = {\"ham\": \"good\", \"carrot\": \"semi good\"}\n", "my_other_dict = dict(my_dict)\n", - "my_other_dict['beer'] = 'decent'\n", - "print('my_dict: {}\\nother: {}'.format(my_dict, my_other_dict))\n", - "print('equal: {}'.format(my_dict == my_other_dict))" + "my_other_dict[\"beer\"] = \"decent\"\n", + "print(\"my_dict: {}\\nother: {}\".format(my_dict, my_other_dict))\n", + "print(\"equal: {}\".format(my_dict == my_other_dict))" ] }, { @@ -177,12 +177,12 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'a': 1, 'b': 2, 'c': 3}\n", - "d = my_dict.get('d')\n", - "print('d: {}'.format(d))\n", + "my_dict = {\"a\": 1, \"b\": 2, \"c\": 3}\n", + "d = my_dict.get(\"d\")\n", + "print(\"d: {}\".format(d))\n", "\n", - "d = my_dict.get('d', 'my default value')\n", - "print('d: {}'.format(d))" + "d = my_dict.get(\"d\", \"my default value\")\n", + "print(\"d: {}\".format(d))" ] }, { @@ -198,16 +198,16 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = dict(food='ham', drink='beer', sport='football')\n", - "print('dict before pops: {}'.format(my_dict))\n", + "my_dict = dict(food=\"ham\", drink=\"beer\", sport=\"football\")\n", + "print(\"dict before pops: {}\".format(my_dict))\n", "\n", - "food = my_dict.pop('food')\n", - "print('food: {}'.format(food))\n", - "print('dict after popping food: {}'.format(my_dict))\n", + "food = my_dict.pop(\"food\")\n", + "print(\"food: {}\".format(food))\n", + "print(\"dict after popping food: {}\".format(my_dict))\n", "\n", - "food_again = my_dict.pop('food', 'default value for food')\n", - "print('food again: {}'.format(food_again))\n", - "print('dict after popping food again: {}'.format(my_dict))\n" + "food_again = my_dict.pop(\"food\", \"default value for food\")\n", + "print(\"food again: {}\".format(food_again))\n", + "print(\"dict after popping food again: {}\".format(my_dict))" ] }, { @@ -224,10 +224,10 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'a': 1, 'b': 2, 'c': 3}\n", - "a = my_dict.setdefault('a', 'my default value')\n", - "d = my_dict.setdefault('d', 'my default value')\n", - "print('a: {}\\nd: {}\\nmy_dict: {}'.format(a, d, my_dict))" + "my_dict = {\"a\": 1, \"b\": 2, \"c\": 3}\n", + "a = my_dict.setdefault(\"a\", \"my default value\")\n", + "d = my_dict.setdefault(\"d\", \"my default value\")\n", + "print(\"a: {}\\nd: {}\\nmy_dict: {}\".format(a, d, my_dict))" ] }, { @@ -244,13 +244,13 @@ "metadata": {}, "outputs": [], "source": [ - "dict1 = {'a': 1, 'b': 2}\n", - "dict2 = {'c': 3}\n", + "dict1 = {\"a\": 1, \"b\": 2}\n", + "dict2 = {\"c\": 3}\n", "dict1.update(dict2)\n", "print(dict1)\n", "\n", "# If they have same keys:\n", - "dict1.update({'c': 4})\n", + "dict1.update({\"c\": 4})\n", "print(dict1)" ] }, @@ -291,7 +291,7 @@ "metadata": {}, "outputs": [], "source": [ - "good_dict = {'my key': ['Python', 'is', 'still', 'cool']}\n", + "good_dict = {\"my key\": [\"Python\", \"is\", \"still\", \"cool\"]}\n", "print(good_dict)" ] } diff --git a/notebooks/beginner/notebooks/for_loops.ipynb b/notebooks/beginner/notebooks/06_for_loops.ipynb similarity index 91% rename from notebooks/beginner/notebooks/for_loops.ipynb rename to notebooks/beginner/notebooks/06_for_loops.ipynb index a61c1c1..eded387 100644 --- a/notebooks/beginner/notebooks/for_loops.ipynb +++ b/notebooks/beginner/notebooks/06_for_loops.ipynb @@ -20,7 +20,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_list = [1, 2, 3, 4, 'Python', 'is', 'neat']\n", + "my_list = [1, 2, 3, 4, \"Python\", \"is\", \"neat\"]\n", "for item in my_list:\n", " print(item)" ] @@ -40,7 +40,7 @@ "outputs": [], "source": [ "for item in my_list:\n", - " if item == 'Python':\n", + " if item == \"Python\":\n", " break\n", " print(item)" ] @@ -80,7 +80,7 @@ "outputs": [], "source": [ "for idx, val in enumerate(my_list):\n", - " print('idx: {}, value: {}'.format(idx, val))" + " print(\"idx: {}, value: {}\".format(idx, val))" ] }, { @@ -96,7 +96,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'hacker': True, 'age': 72, 'name': 'John Doe'}\n", + "my_dict = {\"hacker\": True, \"age\": 72, \"name\": \"John Doe\"}\n", "for val in my_dict:\n", " print(val)" ] @@ -108,7 +108,7 @@ "outputs": [], "source": [ "for key, val in my_dict.items():\n", - " print('{}={}'.format(key, val))" + " print(\"{}={}\".format(key, val))" ] }, { diff --git a/notebooks/beginner/notebooks/functions.ipynb b/notebooks/beginner/notebooks/07_functions.ipynb similarity index 86% rename from notebooks/beginner/notebooks/functions.ipynb rename to notebooks/beginner/notebooks/07_functions.ipynb index ca00f31..bd4957c 100644 --- a/notebooks/beginner/notebooks/functions.ipynb +++ b/notebooks/beginner/notebooks/07_functions.ipynb @@ -14,9 +14,10 @@ "outputs": [], "source": [ "def my_first_function():\n", - " print('Hello world!')\n", + " print(\"Hello world!\")\n", "\n", - "print('type: {}'.format(my_first_function))\n", + "\n", + "print(\"type: {}\".format(my_first_function))\n", "\n", "my_first_function() # Calling a function" ] @@ -35,9 +36,10 @@ "outputs": [], "source": [ "def greet_us(name1, name2):\n", - " print('Hello {} and {}!'.format(name1, name2))\n", + " print(\"Hello {} and {}!\".format(name1, name2))\n", + "\n", "\n", - "greet_us('John Doe', 'Superman')" + "greet_us(\"John Doe\", \"Superman\")" ] }, { @@ -51,9 +53,10 @@ " modified = original.strip().lower()\n", " return modified\n", "\n", - "uggly_string = ' MixED CaSe '\n", + "\n", + "uggly_string = \" MixED CaSe \"\n", "pretty = strip_and_lowercase(uggly_string)\n", - "print('pretty: {}'.format(pretty))" + "print(\"pretty: {}\".format(pretty))" ] }, { @@ -70,7 +73,8 @@ "outputs": [], "source": [ "def my_fancy_calculation(first, second, third):\n", - " return first + second - third \n", + " return first + second - third\n", + "\n", "\n", "print(my_fancy_calculation(3, 2, 1))\n", "\n", @@ -80,7 +84,7 @@ "print(my_fancy_calculation(third=1, first=3, second=2))\n", "\n", "# You can mix arguments and keyword arguments but you have to start with arguments\n", - "print(my_fancy_calculation(3, third=1, second=2)) " + "print(my_fancy_calculation(3, third=1, second=2))" ] }, { @@ -93,22 +97,21 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "scrolled": true - }, + "metadata": {}, "outputs": [], "source": [ "def create_person_info(name, age, job=None, salary=300):\n", - " info = {'name': name, 'age': age, 'salary': salary}\n", - " \n", + " info = {\"name\": name, \"age\": age, \"salary\": salary}\n", + "\n", " # Add 'job' key only if it's provided as parameter\n", - " if job: \n", + " if job:\n", " info.update(dict(job=job))\n", - " \n", + "\n", " return info\n", "\n", - "person1 = create_person_info('John Doe', 82) # use default values for job and salary\n", - "person2 = create_person_info('Lisa Doe', 22, 'hacker', 10000)\n", + "\n", + "person1 = create_person_info(\"John Doe\", 82) # use default values for job and salary\n", + "person2 = create_person_info(\"Lisa Doe\", 22, \"hacker\", 10000)\n", "print(person1)\n", "print(person2)" ] @@ -131,6 +134,7 @@ " magical_list.append(number)\n", " return magical_list\n", "\n", + "\n", "print(append_if_multiple_of_five(100))\n", "print(append_if_multiple_of_five(105))\n", "print(append_if_multiple_of_five(123))\n", @@ -158,6 +162,7 @@ " magical_list.append(number)\n", " return magical_list\n", "\n", + "\n", "print(append_if_multiple_of_five(100))\n", "print(append_if_multiple_of_five(105))\n", "print(append_if_multiple_of_five(123))\n", @@ -181,7 +186,8 @@ "source": [ "def print_sum(val1, val2):\n", " \"\"\"Function which prints the sum of given arguments.\"\"\"\n", - " print('sum: {}'.format(val1 + val2))\n", + " print(\"sum: {}\".format(val1 + val2))\n", + "\n", "\n", "print(help(print_sum))" ] @@ -193,7 +199,7 @@ "outputs": [], "source": [ "def calculate_sum(val1, val2):\n", - " \"\"\"This is a longer docstring defining also the args and the return value. \n", + " \"\"\"This is a longer docstring defining also the args and the return value.\n", "\n", " Args:\n", " val1: The first parameter.\n", @@ -201,10 +207,11 @@ "\n", " Returns:\n", " The sum of val1 and val2.\n", - " \n", + "\n", " \"\"\"\n", " return val1 + val2\n", "\n", + "\n", "print(help(calculate_sum))" ] }, @@ -225,6 +232,7 @@ "def my_function(some_argument):\n", " pass\n", "\n", + "\n", "def my_other_function():\n", " pass" ] diff --git a/notebooks/beginner/notebooks/testing1.ipynb b/notebooks/beginner/notebooks/08_testing1.ipynb similarity index 95% rename from notebooks/beginner/notebooks/testing1.ipynb rename to notebooks/beginner/notebooks/08_testing1.ipynb index 50a0bbb..562ab40 100644 --- a/notebooks/beginner/notebooks/testing1.ipynb +++ b/notebooks/beginner/notebooks/08_testing1.ipynb @@ -54,14 +54,14 @@ "# Let's make sure pytest and ipytest packages are installed\n", "# ipytest is required for running pytest inside Jupyter notebooks\n", "import sys\n", + "\n", "!{sys.executable} -m pip install pytest\n", "!{sys.executable} -m pip install ipytest\n", "\n", - "import ipytest.magics\n", - "import pytest\n", + "# These are needed for running pytest inside Jupyter notebooks\n", + "import ipytest\n", "\n", - "# Filename has to be set explicitly for ipytest \n", - "__file__ = 'testing1.ipynb'" + "ipytest.autoconfig()" ] }, { @@ -101,7 +101,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean]\n", + "%%ipytest\n", "# Mention this at the top of cells which contain test(s)\n", "# This is only required for running pytest in Jupyter notebooks\n", "\n", @@ -130,7 +130,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -144,7 +144,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.10.3" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/file_io.ipynb b/notebooks/beginner/notebooks/10_file_io.ipynb similarity index 76% rename from notebooks/beginner/notebooks/file_io.ipynb rename to notebooks/beginner/notebooks/10_file_io.ipynb index 76c8ee2..e9b4865 100644 --- a/notebooks/beginner/notebooks/file_io.ipynb +++ b/notebooks/beginner/notebooks/10_file_io.ipynb @@ -23,16 +23,16 @@ "source": [ "import os\n", "\n", - "current_file = os.path.realpath('file_io.ipynb') \n", - "print('current file: {}'.format(current_file))\n", + "current_file = os.path.realpath(\"file_io.ipynb\")\n", + "print(\"current file: {}\".format(current_file))\n", "# Note: in .py files you can get the path of current file by __file__\n", "\n", - "current_dir = os.path.dirname(current_file) \n", - "print('current directory: {}'.format(current_dir))\n", + "current_dir = os.path.dirname(current_file)\n", + "print(\"current directory: {}\".format(current_dir))\n", "# Note: in .py files you can get the dir of current file by os.path.dirname(__file__)\n", "\n", - "data_dir = os.path.join(os.path.dirname(current_dir), 'data')\n", - "print('data directory: {}'.format(data_dir))" + "data_dir = os.path.join(os.path.dirname(current_dir), \"data\")\n", + "print(\"data directory: {}\".format(data_dir))" ] }, { @@ -48,9 +48,9 @@ "metadata": {}, "outputs": [], "source": [ - "print('exists: {}'.format(os.path.exists(data_dir)))\n", - "print('is file: {}'.format(os.path.isfile(data_dir)))\n", - "print('is directory: {}'.format(os.path.isdir(data_dir)))" + "print(\"exists: {}\".format(os.path.exists(data_dir)))\n", + "print(\"is file: {}\".format(os.path.isfile(data_dir)))\n", + "print(\"is directory: {}\".format(os.path.isdir(data_dir)))" ] }, { @@ -66,9 +66,9 @@ "metadata": {}, "outputs": [], "source": [ - "file_path = os.path.join(data_dir, 'simple_file.txt')\n", + "file_path = os.path.join(data_dir, \"simple_file.txt\")\n", "\n", - "with open(file_path, 'r') as simple_file:\n", + "with open(file_path, \"r\") as simple_file:\n", " for line in simple_file:\n", " print(line.strip())" ] @@ -90,13 +90,13 @@ "metadata": {}, "outputs": [], "source": [ - "file_path = os.path.join(data_dir, 'simple_file.txt')\n", + "file_path = os.path.join(data_dir, \"simple_file.txt\")\n", "\n", "# THIS IS NOT THE PREFERRED WAY\n", - "simple_file = open(file_path, 'r')\n", + "simple_file = open(file_path, \"r\")\n", "for line in simple_file:\n", " print(line.strip())\n", - "simple_file.close() # This has to be called explicitly " + "simple_file.close() # This has to be called explicitly" ] }, { @@ -112,10 +112,10 @@ "metadata": {}, "outputs": [], "source": [ - "new_file_path = os.path.join(data_dir, 'new_file.txt')\n", + "new_file_path = os.path.join(data_dir, \"new_file.txt\")\n", "\n", - "with open(new_file_path, 'w') as my_file:\n", - " my_file.write('This is my first file that I wrote with Python.')" + "with open(new_file_path, \"w\") as my_file:\n", + " my_file.write(\"This is my first file that I wrote with Python.\")" ] }, { diff --git a/notebooks/beginner/notebooks/classes.ipynb b/notebooks/beginner/notebooks/11_classes.ipynb similarity index 82% rename from notebooks/beginner/notebooks/classes.ipynb rename to notebooks/beginner/notebooks/11_classes.ipynb index b39b340..0eedf2e 100644 --- a/notebooks/beginner/notebooks/classes.ipynb +++ b/notebooks/beginner/notebooks/11_classes.ipynb @@ -18,7 +18,7 @@ " self.name = name\n", "\n", " def greet(self):\n", - " print('Hello {}!'.format(self.name))" + " print(\"Hello {}!\".format(self.name))" ] }, { @@ -27,10 +27,10 @@ "metadata": {}, "outputs": [], "source": [ - "my_instance = MyFirstClass('John Doe')\n", - "print('my_instance: {}'.format(my_instance))\n", - "print('type: {}'.format(type(my_instance)))\n", - "print('my_instance.name: {}'.format(my_instance.name))" + "my_instance = MyFirstClass(\"John Doe\")\n", + "print(\"my_instance: {}\".format(my_instance))\n", + "print(\"type: {}\".format(type(my_instance)))\n", + "print(\"my_instance.name: {}\".format(my_instance.name))" ] }, { @@ -47,7 +47,7 @@ "metadata": {}, "outputs": [], "source": [ - "alice = MyFirstClass(name='Alice')\n", + "alice = MyFirstClass(name=\"Alice\")\n", "alice.greet()" ] }, @@ -67,11 +67,12 @@ "source": [ "class Example:\n", " def __init__(self):\n", - " print('Now we are inside __init__')\n", - " \n", - "print('creating instance of Example')\n", + " print(\"Now we are inside __init__\")\n", + "\n", + "\n", + "print(\"creating instance of Example\")\n", "example = Example()\n", - "print('instance created')" + "print(\"instance created\")" ] }, { @@ -91,13 +92,13 @@ " def __init__(self, var1, var2):\n", " self.first_var = var1\n", " self.second_var = var2\n", - " \n", + "\n", " def print_variables(self):\n", - " print('{} {}'.format(self.first_var, self.second_var))\n", - " \n", - "e = Example('abc', 123)\n", - "e.print_variables()\n", - " " + " print(\"{} {}\".format(self.first_var, self.second_var))\n", + "\n", + "\n", + "e = Example(\"abc\", 123)\n", + "e.print_variables()" ] }, { @@ -118,12 +119,13 @@ " def __init__(self, name, age):\n", " self.name = name\n", " self.age = age\n", - " \n", + "\n", " def __str__(self):\n", - " return 'Person: {}'.format(self.name)\n", - " \n", - "jack = Person('Jack', 82)\n", - "print('This is the string presentation of jack: {}'.format(jack))" + " return \"Person: {}\".format(self.name)\n", + "\n", + "\n", + "jack = Person(\"Jack\", 82)\n", + "print(\"This is the string presentation of jack: {}\".format(jack))" ] }, { @@ -142,28 +144,29 @@ "source": [ "class Example:\n", " # These are class variables\n", - " name = 'Example class'\n", - " description = 'Just an example of a simple class'\n", + " name = \"Example class\"\n", + " description = \"Just an example of a simple class\"\n", "\n", " def __init__(self, var1):\n", " # This is an instance variable\n", " self.instance_variable = var1\n", "\n", " def show_info(self):\n", - " info = 'instance_variable: {}, name: {}, description: {}'.format(\n", - " self.instance_variable, Example.name, Example.description)\n", + " info = \"instance_variable: {}, name: {}, description: {}\".format(\n", + " self.instance_variable, Example.name, Example.description\n", + " )\n", " print(info)\n", "\n", "\n", - "inst1 = Example('foo')\n", - "inst2 = Example('bar')\n", + "inst1 = Example(\"foo\")\n", + "inst2 = Example(\"bar\")\n", "\n", "# name and description have identical values between instances\n", "assert inst1.name == inst2.name == Example.name\n", "assert inst1.description == inst2.description == Example.description\n", "\n", "# If you change the value of a class variable, it's changed across all instances\n", - "Example.name = 'Modified name'\n", + "Example.name = \"Modified name\"\n", "inst1.show_info()\n", "inst2.show_info()" ] @@ -187,7 +190,8 @@ "class Person:\n", " def __init__(self, age):\n", " self._age = age\n", - " \n", + "\n", + "\n", "example_person = Person(age=15)\n", "# You can't do this:\n", "# print(example_person.age)\n", @@ -211,16 +215,17 @@ "class Person:\n", " def __init__(self, age):\n", " self._age = age\n", - " \n", + "\n", " @property\n", " def age(self):\n", " return self._age\n", - " \n", + "\n", + "\n", "example_person = Person(age=15)\n", "# Now you can do this:\n", "print(example_person.age)\n", "# But not this:\n", - "#example_person.age = 16" + "# example_person.age = 16" ] }, { @@ -239,15 +244,16 @@ "class Person:\n", " def __init__(self, age):\n", " self._age = age\n", - " \n", + "\n", " @property\n", " def age(self):\n", " return self._age\n", - " \n", + "\n", " def celebrate_birthday(self):\n", " self._age += 1\n", - " print('Happy bday for {} years old!'.format(self._age))\n", - " \n", + " print(\"Happy bday for {} years old!\".format(self._age))\n", + "\n", + "\n", "example_person = Person(age=15)\n", "example_person.celebrate_birthday()" ] @@ -267,22 +273,22 @@ "source": [ "class Animal:\n", " def greet(self):\n", - " print('Hello, I am an animal')\n", + " print(\"Hello, I am an animal\")\n", "\n", " @property\n", " def favorite_food(self):\n", - " return 'beef'\n", + " return \"beef\"\n", "\n", "\n", "class Dog(Animal):\n", " def greet(self):\n", - " print('wof wof')\n", + " print(\"wof wof\")\n", "\n", "\n", "class Cat(Animal):\n", " @property\n", " def favorite_food(self):\n", - " return 'fish'" + " return \"fish\"" ] }, { @@ -303,7 +309,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -317,7 +323,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.10.3" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/exceptions.ipynb b/notebooks/beginner/notebooks/12_exceptions.ipynb similarity index 82% rename from notebooks/beginner/notebooks/exceptions.ipynb rename to notebooks/beginner/notebooks/12_exceptions.ipynb index 3fe2f0b..94d7268 100644 --- a/notebooks/beginner/notebooks/exceptions.ipynb +++ b/notebooks/beginner/notebooks/12_exceptions.ipynb @@ -34,15 +34,15 @@ "outputs": [], "source": [ "# Let's try to open a file that does not exist\n", - "file_name = 'not_existing.txt'\n", + "file_name = \"not_existing.txt\"\n", "\n", "try:\n", - " with open(file_name, 'r') as my_file:\n", - " print('File is successfully open')\n", - " \n", + " with open(file_name, \"r\") as my_file:\n", + " print(\"File is successfully open\")\n", + "\n", "except FileNotFoundError as e:\n", - " print('Uups, file: {} not found'.format(file_name))\n", - " print('Exception: {} was raised'.format(e))" + " print(\"Uups, file: {} not found\".format(file_name))\n", + " print(\"Exception: {} was raised\".format(e))" ] }, { @@ -60,24 +60,25 @@ "source": [ "def calculate_division(var1, var2):\n", " result = 0\n", - " \n", + "\n", " try:\n", " result = var1 / var2\n", " except ZeroDivisionError as ex1:\n", " print(\"Can't divide by zero\")\n", " except Exception as ex2:\n", - " print('Exception: {}'.format(ex2))\n", + " print(\"Exception: {}\".format(ex2))\n", "\n", " return result\n", "\n", + "\n", "result1 = calculate_division(3, 3)\n", - "print('result1: {}'.format(result1))\n", + "print(\"result1: {}\".format(result1))\n", "\n", - "result2 = calculate_division(3, '3')\n", - "print('result2: {}'.format(result2))\n", + "result2 = calculate_division(3, \"3\")\n", + "print(\"result2: {}\".format(result2))\n", "\n", "result3 = calculate_division(3, 0)\n", - "print('result3: {}'.format(result3))" + "print(\"result3: {}\".format(result3))" ] }, { @@ -96,8 +97,9 @@ "def calculate_division(var1, var2):\n", " return var1 / var2\n", "\n", + "\n", "try:\n", - " result = calculate_division(3, '3')\n", + " result = calculate_division(3, \"3\")\n", "except Exception as e:\n", " print(e)" ] @@ -118,19 +120,23 @@ "source": [ "import math\n", "\n", + "\n", "# Define your own exception\n", "class NegativeNumbersNotSupported(Exception):\n", " pass\n", "\n", + "\n", "# Dummy example how to use your custom exception\n", "def secret_calculation(number1, number2):\n", " if number1 < 0 or number2 < 0:\n", - " msg = 'Negative number in at least one of the parameters: {}, {}'.format(\n", - " number1, number2)\n", + " msg = \"Negative number in at least one of the parameters: {}, {}\".format(\n", + " number1, number2\n", + " )\n", " raise NegativeNumbersNotSupported(msg)\n", "\n", " return math.sqrt(number1) + math.sqrt(number2)\n", "\n", + "\n", "# Uncomment to see the traceback\n", "# result = secret_calculation(-1, 1)" ] @@ -157,4 +163,4 @@ }, "nbformat": 4, "nbformat_minor": 0 -} \ No newline at end of file +} diff --git a/notebooks/beginner/notebooks/modules_and_packages.ipynb b/notebooks/beginner/notebooks/13_modules_and_packages.ipynb similarity index 100% rename from notebooks/beginner/notebooks/modules_and_packages.ipynb rename to notebooks/beginner/notebooks/13_modules_and_packages.ipynb diff --git a/notebooks/beginner/notebooks/debugging.ipynb b/notebooks/beginner/notebooks/14_debugging.ipynb similarity index 95% rename from notebooks/beginner/notebooks/debugging.ipynb rename to notebooks/beginner/notebooks/14_debugging.ipynb index af2e669..57acdc4 100644 --- a/notebooks/beginner/notebooks/debugging.ipynb +++ b/notebooks/beginner/notebooks/14_debugging.ipynb @@ -62,7 +62,7 @@ " self._greet_hawaii(person)\n", " else:\n", " self._greet_polite(person)\n", - " \n", + "\n", " def _greet_polite(self, name):\n", " greeting = \"G'day {}! How are you doing?\".format(name)\n", " print(greeting)\n", @@ -70,14 +70,14 @@ " def _greet_street_style(self, name):\n", " # import pdb; pdb.set_trace() # UNCOMMENT\n", " name = name.upper()\n", - " print('WASSUP {}!?'.format(name))\n", + " print(\"WASSUP {}!?\".format(name))\n", "\n", " def _greet_hawaii(self, name):\n", - " print('Aloha {}!'.format(name))\n", + " print(\"Aloha {}!\".format(name))\n", "\n", "\n", "def main():\n", - " people = ['John Doe', 'Donald', 'Lisa', 'alex']\n", + " people = [\"John Doe\", \"Donald\", \"Lisa\", \"alex\"]\n", " # import pdb; pdb.set_trace() # UNCOMMENT\n", " greeter = SuperGreeter(people)\n", " greeter.greet()\n", diff --git a/notebooks/beginner/notebooks/std_lib.ipynb b/notebooks/beginner/notebooks/15_std_lib.ipynb similarity index 70% rename from notebooks/beginner/notebooks/std_lib.ipynb rename to notebooks/beginner/notebooks/15_std_lib.ipynb index 3818bec..3d13f3b 100644 --- a/notebooks/beginner/notebooks/std_lib.ipynb +++ b/notebooks/beginner/notebooks/15_std_lib.ipynb @@ -24,18 +24,25 @@ "import datetime as dt\n", "\n", "local_now = dt.datetime.now()\n", - "print('local now: {}'.format(local_now))\n", + "print(\"local now: {}\".format(local_now))\n", "\n", "utc_now = dt.datetime.utcnow()\n", - "print('utc now: {}'.format(utc_now))\n", + "print(\"utc now: {}\".format(utc_now))\n", "\n", "# You can access any value separately:\n", - "print('{} {} {} {} {} {}'.format(local_now.year, local_now.month,\n", - " local_now.day, local_now.hour,\n", - " local_now.minute, local_now.second))\n", - "\n", - "print('date: {}'.format(local_now.date()))\n", - "print('time: {}'.format(local_now.time()))" + "print(\n", + " \"{} {} {} {} {} {}\".format(\n", + " local_now.year,\n", + " local_now.month,\n", + " local_now.day,\n", + " local_now.hour,\n", + " local_now.minute,\n", + " local_now.second,\n", + " )\n", + ")\n", + "\n", + "print(\"date: {}\".format(local_now.date()))\n", + "print(\"time: {}\".format(local_now.time()))" ] }, { @@ -52,10 +59,10 @@ "metadata": {}, "outputs": [], "source": [ - "formatted1 = local_now.strftime('%Y/%m/%d-%H:%M:%S')\n", + "formatted1 = local_now.strftime(\"%Y/%m/%d-%H:%M:%S\")\n", "print(formatted1)\n", "\n", - "formatted2 = local_now.strftime('date: %Y-%m-%d time:%H:%M:%S')\n", + "formatted2 = local_now.strftime(\"date: %Y-%m-%d time:%H:%M:%S\")\n", "print(formatted2)" ] }, @@ -73,8 +80,8 @@ "metadata": {}, "outputs": [], "source": [ - "my_dt = dt.datetime.strptime('2000-01-01 10:00:00', '%Y-%m-%d %H:%M:%S')\n", - "print('my_dt: {}'.format(my_dt))" + "my_dt = dt.datetime.strptime(\"2000-01-01 10:00:00\", \"%Y-%m-%d %H:%M:%S\")\n", + "print(\"my_dt: {}\".format(my_dt))" ] }, { @@ -92,12 +99,12 @@ "outputs": [], "source": [ "tomorrow = local_now + dt.timedelta(days=1)\n", - "print('tomorrow this time: {}'.format(tomorrow))\n", + "print(\"tomorrow this time: {}\".format(tomorrow))\n", "\n", "delta = tomorrow - local_now\n", - "print('tomorrow - now = {}'.format(delta))\n", - "print('days: {}, seconds: {}'.format(delta.days, delta.seconds))\n", - "print('total seconds: {}'.format(delta.total_seconds()))" + "print(\"tomorrow - now = {}\".format(delta))\n", + "print(\"days: {}, seconds: {}\".format(delta.days, delta.seconds))\n", + "print(\"total seconds: {}\".format(delta.total_seconds()))" ] }, { @@ -115,6 +122,7 @@ "outputs": [], "source": [ "import sys\n", + "\n", "!{sys.executable} -m pip install pytz" ] }, @@ -128,21 +136,21 @@ "import pytz\n", "\n", "naive_utc_now = dt.datetime.utcnow()\n", - "print('naive utc now: {}, tzinfo: {}'.format(naive_utc_now, naive_utc_now.tzinfo))\n", + "print(\"naive utc now: {}, tzinfo: {}\".format(naive_utc_now, naive_utc_now.tzinfo))\n", "\n", "# Localizing naive datetimes\n", - "UTC_TZ = pytz.timezone('UTC')\n", + "UTC_TZ = pytz.timezone(\"UTC\")\n", "utc_now = UTC_TZ.localize(naive_utc_now)\n", - "print('utc now: {}, tzinfo: {}'.format(utc_now, utc_now.tzinfo))\n", + "print(\"utc now: {}, tzinfo: {}\".format(utc_now, utc_now.tzinfo))\n", "\n", "# Converting localized datetimes to different timezone\n", - "PARIS_TZ = pytz.timezone('Europe/Paris')\n", + "PARIS_TZ = pytz.timezone(\"Europe/Paris\")\n", "paris_now = PARIS_TZ.normalize(utc_now)\n", - "print('Paris: {}, tzinfo: {}'.format(paris_now, paris_now.tzinfo))\n", + "print(\"Paris: {}, tzinfo: {}\".format(paris_now, paris_now.tzinfo))\n", "\n", - "NEW_YORK_TZ = pytz.timezone('America/New_York')\n", + "NEW_YORK_TZ = pytz.timezone(\"America/New_York\")\n", "ny_now = NEW_YORK_TZ.normalize(utc_now)\n", - "print('New York: {}, tzinfo: {}'.format(ny_now, ny_now.tzinfo))" + "print(\"New York: {}, tzinfo: {}\".format(ny_now, ny_now.tzinfo))" ] }, { @@ -171,11 +179,11 @@ "logger = logging.getLogger(__name__)\n", "logger.setLevel(logging.WARNING)\n", "\n", - "logger.debug('This is debug')\n", - "logger.info('This is info')\n", - "logger.warning('This is warning')\n", - "logger.error('This is error')\n", - "logger.critical('This is critical')" + "logger.debug(\"This is debug\")\n", + "logger.info(\"This is info\")\n", + "logger.warning(\"This is warning\")\n", + "logger.error(\"This is error\")\n", + "logger.critical(\"This is critical\")" ] }, { @@ -195,7 +203,7 @@ "try:\n", " path_calculation = 1 / 0\n", "except ZeroDivisionError:\n", - " logging.exception('All went south in my calculation')" + " logging.exception(\"All went south in my calculation\")" ] }, { @@ -215,15 +223,16 @@ "\n", "# This is only required for Jupyter notebook environment\n", "from importlib import reload\n", + "\n", "reload(logging)\n", "\n", - "my_format = '%(asctime)s | %(name)-12s | %(levelname)-10s | %(message)s'\n", + "my_format = \"%(asctime)s | %(name)-12s | %(levelname)-10s | %(message)s\"\n", "logging.basicConfig(format=my_format)\n", "\n", - "logger = logging.getLogger('MyLogger')\n", + "logger = logging.getLogger(\"MyLogger\")\n", "\n", - "logger.warning('Something bad is going to happen')\n", - "logger.error('Uups, it already happened')" + "logger.warning(\"Something bad is going to happen\")\n", + "logger.error(\"Uups, it already happened\")" ] }, { @@ -244,16 +253,19 @@ "\n", "# This is only required for Jupyter notebook environment\n", "from importlib import reload\n", + "\n", "reload(logging)\n", "\n", - "logger = logging.getLogger('MyFileLogger')\n", + "logger = logging.getLogger(\"MyFileLogger\")\n", "\n", "# Let's define a file_handler for our logger\n", - "log_path = os.path.join(os.getcwd(), 'my_log.txt')\n", + "log_path = os.path.join(os.getcwd(), \"my_log.txt\")\n", "file_handler = logging.FileHandler(log_path)\n", "\n", "# And a nice format\n", - "formatter = logging.Formatter('%(asctime)s | %(name)-12s | %(levelname)-10s | %(message)s')\n", + "formatter = logging.Formatter(\n", + " \"%(asctime)s | %(name)-12s | %(levelname)-10s | %(message)s\"\n", + ")\n", "file_handler.setFormatter(formatter)\n", "\n", "logger.addHandler(file_handler)\n", @@ -261,8 +273,8 @@ "# If you want to see it also in the console, add another handler for it\n", "# logger.addHandler(logging.StreamHandler())\n", "\n", - "logger.warning('Oops something is going to happen')\n", - "logger.error('John Doe visits our place')" + "logger.warning(\"Oops something is going to happen\")\n", + "logger.error(\"John Doe visits our place\")" ] }, { @@ -281,10 +293,10 @@ "import random\n", "\n", "rand_int = random.randint(1, 100)\n", - "print('random integer between 1-100: {}'.format(rand_int))\n", + "print(\"random integer between 1-100: {}\".format(rand_int))\n", "\n", "rand = random.random()\n", - "print('random float between 0-1: {}'.format(rand))" + "print(\"random float between 0-1: {}\".format(rand))" ] }, { @@ -331,17 +343,17 @@ "source": [ "import re\n", "\n", - "secret_code = 'qwret 8sfg12f5 fd09f_df'\n", + "secret_code = \"qwret 8sfg12f5 fd09f_df\"\n", "# \"r\" at the beginning means raw format, use it with regular expression patterns\n", - "search_pattern = r'(g12)' \n", + "search_pattern = r\"(g12)\"\n", "\n", "match = re.search(search_pattern, secret_code)\n", - "print('match: {}'.format(match))\n", - "print('match.group(): {}'.format(match.group()))\n", + "print(\"match: {}\".format(match))\n", + "print(\"match.group(): {}\".format(match.group()))\n", "\n", - "numbers_pattern = r'[0-9]'\n", + "numbers_pattern = r\"[0-9]\"\n", "numbers_match = re.findall(numbers_pattern, secret_code)\n", - "print('numbers: {}'.format(numbers_match))" + "print(\"numbers: {}\".format(numbers_match))" ] }, { @@ -359,21 +371,23 @@ "source": [ "import re\n", "\n", + "\n", "def validate_only_lower_case_letters(to_validate):\n", - " pattern = r'^[a-z]+$'\n", + " pattern = r\"^[a-z]+$\"\n", " return bool(re.match(pattern, to_validate))\n", "\n", - "print(validate_only_lower_case_letters('thisshouldbeok'))\n", - "print(validate_only_lower_case_letters('thisshould notbeok'))\n", - "print(validate_only_lower_case_letters('Thisshouldnotbeok'))\n", - "print(validate_only_lower_case_letters('thisshouldnotbeok1'))\n", - "print(validate_only_lower_case_letters(''))" + "\n", + "print(validate_only_lower_case_letters(\"thisshouldbeok\"))\n", + "print(validate_only_lower_case_letters(\"thisshould notbeok\"))\n", + "print(validate_only_lower_case_letters(\"Thisshouldnotbeok\"))\n", + "print(validate_only_lower_case_letters(\"thisshouldnotbeok1\"))\n", + "print(validate_only_lower_case_letters(\"\"))" ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -387,7 +401,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.10.3" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/testing2.ipynb b/notebooks/beginner/notebooks/16_testing2.ipynb similarity index 88% rename from notebooks/beginner/notebooks/testing2.ipynb rename to notebooks/beginner/notebooks/16_testing2.ipynb index f4c18e0..d0e72e2 100644 --- a/notebooks/beginner/notebooks/testing2.ipynb +++ b/notebooks/beginner/notebooks/16_testing2.ipynb @@ -16,12 +16,14 @@ "# Let's make sure pytest and ipytest packages are installed\n", "# ipytest is required for running pytest inside Jupyter notebooks\n", "import sys\n", + "\n", "!{sys.executable} -m pip install pytest\n", "!{sys.executable} -m pip install ipytest\n", "\n", - "import ipytest.magics\n", - "import pytest\n", - "__file__ = 'testing2.ipynb'" + "# These are needed for running pytest inside Jupyter notebooks\n", + "import ipytest\n", + "\n", + "ipytest.autoconfig()" ] }, { @@ -44,18 +46,18 @@ " self.first_name = first_name\n", " self.last_name = last_name\n", " self.age = age\n", - " \n", + "\n", " @property\n", " def full_name(self):\n", - " return '{} {}'.format(self.first_name, self.last_name)\n", - " \n", + " return \"{} {}\".format(self.first_name, self.last_name)\n", + "\n", " @property\n", " def as_dict(self):\n", - " return {'name': self.full_name, 'age': self.age}\n", - " \n", + " return {\"name\": self.full_name, \"age\": self.age}\n", + "\n", " def increase_age(self, years):\n", " if years < 0:\n", - " raise ValueError('Can not make people younger :(')\n", + " raise ValueError(\"Can not make people younger :(\")\n", " self.age += years" ] }, @@ -73,9 +75,12 @@ "outputs": [], "source": [ "# This would be in either conftest.py or test_person.py\n", + "import pytest\n", + "\n", + "\n", "@pytest.fixture()\n", "def default_person():\n", - " person = Person(first_name='John', last_name='Doe', age=82)\n", + " person = Person(first_name=\"John\", last_name=\"Doe\", age=82)\n", " return person" ] }, @@ -92,7 +97,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean]\n", + "%%ipytest\n", "\n", "# These would be in test_person.py\n", "def test_full_name(default_person): # Note: we use fixture as an argument of the test case\n", @@ -147,7 +152,7 @@ " \"\"\"Replaces names (uppercase words) of original_str by new_name\"\"\"\n", " words = original_str.split()\n", " manipulated_words = [new_name if w.istitle() else w for w in words]\n", - " return ' '.join(manipulated_words)" + " return \" \".join(manipulated_words)" ] }, { @@ -163,7 +168,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean]\n", + "%%ipytest\n", "\n", "# This would be in your test module\n", "@pytest.mark.parametrize(\"original,new_name,expected\", [\n", @@ -175,11 +180,18 @@ " result = replace_names(original, new_name)\n", " assert result == expected" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -193,7 +205,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.10.3" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/venv.ipynb b/notebooks/beginner/notebooks/17_venv.ipynb similarity index 100% rename from notebooks/beginner/notebooks/venv.ipynb rename to notebooks/beginner/notebooks/17_venv.ipynb diff --git a/notebooks/beginner/notebooks/project_structure.ipynb b/notebooks/beginner/notebooks/18_project_structure.ipynb similarity index 96% rename from notebooks/beginner/notebooks/project_structure.ipynb rename to notebooks/beginner/notebooks/18_project_structure.ipynb index f3b0878..823e966 100644 --- a/notebooks/beginner/notebooks/project_structure.ipynb +++ b/notebooks/beginner/notebooks/18_project_structure.ipynb @@ -33,7 +33,7 @@ "\n", "\n", "def magical_function():\n", - " LOGGER.warning('We are about to do some magical stuff')\n", + " LOGGER.warning(\"We are about to do some magical stuff\")\n", "\n", "\n", "def main():\n", @@ -41,7 +41,7 @@ " magical_function()\n", "\n", "\n", - "if __name__ == '__main__':\n", + "if __name__ == \"__main__\":\n", " main()" ] }, diff --git a/notebooks/intermediate/exercises/std_lib2_exercise.ipynb b/notebooks/intermediate/exercises/01_std_lib2_exercise.ipynb similarity index 82% rename from notebooks/intermediate/exercises/std_lib2_exercise.ipynb rename to notebooks/intermediate/exercises/01_std_lib2_exercise.ipynb index 163ce02..072d73a 100644 --- a/notebooks/intermediate/exercises/std_lib2_exercise.ipynb +++ b/notebooks/intermediate/exercises/01_std_lib2_exercise.ipynb @@ -20,8 +20,9 @@ "source": [ "from urllib.request import urlopen\n", "\n", + "\n", "def get_wiki_article(name):\n", - " url = 'https://en.wikipedia.org/wiki/{}'.format(name)\n", + " url = \"https://en.wikipedia.org/wiki/{}\".format(name)\n", " response = urlopen(url)\n", " content = str(response.read())\n", " return content" @@ -33,7 +34,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Your implementation here\n" + "# Your implementation here" ] }, { @@ -51,13 +52,15 @@ }, "outputs": [], "source": [ - "article = 'Python_(programming_language)'\n", + "article = \"Python_(programming_language)\"\n", "res = get_wiki_article(article)\n", - "assert 'Guido van Rossum' not in res, 'Guido is still there!'\n", - "assert res == 'Python is cool!'\n", - "urlopen.assert_called_with('https://en.wikipedia.org/wiki/Python_(programming_language)')\n", + "assert \"Guido van Rossum\" not in res, \"Guido is still there!\"\n", + "assert res == \"Python is cool!\"\n", + "urlopen.assert_called_with(\n", + " \"https://en.wikipedia.org/wiki/Python_(programming_language)\"\n", + ")\n", "\n", - "print('All good!')" + "print(\"All good!\")" ] }, { @@ -99,18 +102,18 @@ }, "outputs": [], "source": [ - "car1 = Car(25000, 2000, 'BMW')\n", + "car1 = Car(25000, 2000, \"BMW\")\n", "assert car1.price == 25000\n", "assert car1.mileage == 2000\n", - "assert car1.brand == 'BMW'\n", + "assert car1.brand == \"BMW\"\n", "assert isinstance(car1, tuple)\n", "\n", "# Note that indexing works also!\n", "# This means that if you change a tuple into a namedtuple,\n", "# the change will be backwards compatible.\n", - "assert car1[2] == 'BMW'\n", + "assert car1[2] == \"BMW\"\n", "\n", - "print('All good!')" + "print(\"All good!\")" ] }, { @@ -149,7 +152,7 @@ }, "outputs": [], "source": [ - "VOWELS = ('a', 'e', 'i', 'o', 'u')" + "VOWELS = (\"a\", \"e\", \"i\", \"o\", \"u\")" ] }, { @@ -177,35 +180,22 @@ }, "outputs": [], "source": [ - "names = ('Alice', 'John', 'Lisa', 'John', 'Eric', 'Waldo', 'annie', 'Alice', 'John')\n", + "names = (\"Alice\", \"John\", \"Lisa\", \"John\", \"Eric\", \"Waldo\", \"annie\", \"Alice\", \"John\")\n", "expected = {\n", - " 'consonant': {\n", - " 'John': 3,\n", - " 'Waldo': 1,\n", - " 'Lisa': 1\n", - " },\n", - " 'vowel': {\n", - " 'Alice': 2,\n", - " 'annie': 1,\n", - " 'Eric': 1\n", - " }\n", + " \"consonant\": {\"John\": 3, \"Waldo\": 1, \"Lisa\": 1},\n", + " \"vowel\": {\"Alice\": 2, \"annie\": 1, \"Eric\": 1},\n", "}\n", "assert name_mapping(names) == expected\n", - "print('First ok!')\n", + "print(\"First ok!\")\n", "\n", - "only_consonants = ('John', 'Doe', 'Doe')\n", - "expected2 = {\n", - " 'consonant': {\n", - " 'John': 1,\n", - " 'Doe': 2\n", - " }\n", - "}\n", + "only_consonants = (\"John\", \"Doe\", \"Doe\")\n", + "expected2 = {\"consonant\": {\"John\": 1, \"Doe\": 2}}\n", "assert name_mapping(only_consonants) == expected2\n", - "print('Second ok!')\n", + "print(\"Second ok!\")\n", "\n", "assert name_mapping([]) == {}\n", "\n", - "print('All ok!')" + "print(\"All ok!\")" ] } ], diff --git a/notebooks/intermediate/exercises/idiomatic_python_exercise.ipynb b/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb similarity index 87% rename from notebooks/intermediate/exercises/idiomatic_python_exercise.ipynb rename to notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb index a17da86..e1776c3 100644 --- a/notebooks/intermediate/exercises/idiomatic_python_exercise.ipynb +++ b/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb @@ -84,7 +84,7 @@ " 2. numeric values (list of floats)\n", " 3. non-numeric values (list of strings)\n", " \"\"\"\n", - " data_file = open(path, 'r')\n", + " data_file = open(path, \"r\")\n", " lines = data_file.readlines()\n", " line_count = len(lines)\n", " idx = 0\n", @@ -94,7 +94,7 @@ " while idx < line_count:\n", " line = lines[idx]\n", " line = line.strip()\n", - " if line == '':\n", + " if line == \"\":\n", " empty_lines = empty_lines + 1\n", " else:\n", " is_number = False\n", @@ -129,20 +129,28 @@ " most_common_words = most_common_info[0]\n", " most_common_count = most_common_info[1]\n", "\n", - " most_common_str = ''\n", + " most_common_str = \"\"\n", " for idx in range(len(most_common_words)):\n", - " most_common_str += most_common_words[idx] + ', '\n", + " most_common_str += most_common_words[idx] + \", \"\n", " # remove the last comma and space\n", - " most_common_str = most_common_str[0:len(most_common_str) - 2]\n", - "\n", - " report = ('missing values: {}\\n'\n", - " 'highest number: {}\\n'\n", - " 'most common words: {}\\n'\n", - " 'occurrences of most common: {}\\n'\n", - " '#####\\n'\n", - " 'numbers: {}\\n'\n", - " 'words: {}').format(missing_values, max_value, most_common_str,\n", - " most_common_count, numbers, lower_case_words)\n", + " most_common_str = most_common_str[0 : len(most_common_str) - 2]\n", + "\n", + " report = (\n", + " \"missing values: {}\\n\"\n", + " \"highest number: {}\\n\"\n", + " \"most common words: {}\\n\"\n", + " \"occurrences of most common: {}\\n\"\n", + " \"#####\\n\"\n", + " \"numbers: {}\\n\"\n", + " \"words: {}\"\n", + " ).format(\n", + " missing_values,\n", + " max_value,\n", + " most_common_str,\n", + " most_common_count,\n", + " numbers,\n", + " lower_case_words,\n", + " )\n", "\n", " return report\n", "\n", @@ -234,9 +242,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Your beautiful refactored, idiomatic, pythonic solution here\n", - "\n", - "\n" + "# Your beautiful refactored, idiomatic, pythonic solution here" ] }, { @@ -257,44 +263,44 @@ "import os\n", "\n", "CURRENT_DIR = os.getcwd()\n", - "DATA_DIR = os.path.join(os.path.dirname(CURRENT_DIR), 'data')\n", + "DATA_DIR = os.path.join(os.path.dirname(CURRENT_DIR), \"data\")\n", "\n", - "DATA_FILE1 = os.path.join(DATA_DIR, 'misc_data1.txt')\n", - "DATA_FILE2 = os.path.join(DATA_DIR, 'misc_data2.txt')\n", - "DATA_FILE3 = os.path.join(DATA_DIR, 'empty.txt')\n", + "DATA_FILE1 = os.path.join(DATA_DIR, \"misc_data1.txt\")\n", + "DATA_FILE2 = os.path.join(DATA_DIR, \"misc_data2.txt\")\n", + "DATA_FILE3 = os.path.join(DATA_DIR, \"empty.txt\")\n", "\n", - "expected1 = '''missing values: 2\n", + "expected1 = \"\"\"missing values: 2\n", "highest number: 99.0\n", "most common words: john\n", "occurrences of most common: 4\n", "#####\n", "numbers: [1.0, 2.0, 99.0, 6.72, 2.0, 2.0, 2.0]\n", - "words: ['john', 'doe', 'john', 'john', 'was', 'here', 'this', 'is', 'totally', 'random', 'john']'''\n", + "words: ['john', 'doe', 'john', 'john', 'was', 'here', 'this', 'is', 'totally', 'random', 'john']\"\"\"\n", "\n", - "expected2 = '''missing values: 3\n", + "expected2 = \"\"\"missing values: 3\n", "highest number: 101.0\n", "most common words: doe, john\n", "occurrences of most common: 4\n", "#####\n", "numbers: [1.0, 2.0, 101.0, 6.72, 2.0, 2.0, 67.0, 2.0]\n", - "words: ['john', 'doe', 'john', 'john', 'doe', 'was', 'doe', 'here', 'this', 'is', 'totally', 'random', 'john', 'doe']'''\n", + "words: ['john', 'doe', 'john', 'john', 'doe', 'was', 'doe', 'here', 'this', 'is', 'totally', 'random', 'john', 'doe']\"\"\"\n", "\n", - "expected3 = '''missing values: 0\n", + "expected3 = \"\"\"missing values: 0\n", "highest number: None\n", "most common words: \n", "occurrences of most common: 0\n", "#####\n", "numbers: []\n", - "words: []'''\n", + "words: []\"\"\"\n", "\n", "assert get_report(DATA_FILE1) == expected1\n", - "print('First one OK!')\n", + "print(\"First one OK!\")\n", "\n", "assert get_report(DATA_FILE2) == expected2\n", - "print('Second one OK!')\n", + "print(\"Second one OK!\")\n", "\n", "assert get_report(DATA_FILE3) == expected3\n", - "print('All OK, woop woop!')" + "print(\"All OK, woop woop!\")" ] }, { diff --git a/notebooks/intermediate/html/01_best_practices.html b/notebooks/intermediate/html/01_best_practices.html new file mode 100644 index 0000000..9c4f31f --- /dev/null +++ b/notebooks/intermediate/html/01_best_practices.html @@ -0,0 +1,15945 @@ + + + + + +01_best_practices + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/intermediate/html/01_idiomatic_loops.html b/notebooks/intermediate/html/01_idiomatic_loops.html new file mode 100644 index 0000000..88d9f9d --- /dev/null +++ b/notebooks/intermediate/html/01_idiomatic_loops.html @@ -0,0 +1,16013 @@ + + + + + +01_idiomatic_loops + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/intermediate/html/01_pytest_fixtures.html b/notebooks/intermediate/html/01_pytest_fixtures.html new file mode 100644 index 0000000..49503dc --- /dev/null +++ b/notebooks/intermediate/html/01_pytest_fixtures.html @@ -0,0 +1,15902 @@ + + + + + +01_pytest_fixtures + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/intermediate/html/01_std_lib2.html b/notebooks/intermediate/html/01_std_lib2.html new file mode 100644 index 0000000..62d537a --- /dev/null +++ b/notebooks/intermediate/html/01_std_lib2.html @@ -0,0 +1,15788 @@ + + + + + +01_std_lib2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/intermediate/html/02_idiomatic_dicts.html b/notebooks/intermediate/html/02_idiomatic_dicts.html new file mode 100644 index 0000000..8491e8f --- /dev/null +++ b/notebooks/intermediate/html/02_idiomatic_dicts.html @@ -0,0 +1,15879 @@ + + + + + +02_idiomatic_dicts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/intermediate/html/03_idiomatic_misc1.html b/notebooks/intermediate/html/03_idiomatic_misc1.html new file mode 100644 index 0000000..1027480 --- /dev/null +++ b/notebooks/intermediate/html/03_idiomatic_misc1.html @@ -0,0 +1,16410 @@ + + + + + +03_idiomatic_misc1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/intermediate/html/04_idiomatic_misc2.html b/notebooks/intermediate/html/04_idiomatic_misc2.html new file mode 100644 index 0000000..17f35c6 --- /dev/null +++ b/notebooks/intermediate/html/04_idiomatic_misc2.html @@ -0,0 +1,16268 @@ + + + + + +04_idiomatic_misc2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/notebooks/intermediate/html/best_practices.html b/notebooks/intermediate/html/best_practices.html deleted file mode 100644 index 2803cb6..0000000 --- a/notebooks/intermediate/html/best_practices.html +++ /dev/null @@ -1,12473 +0,0 @@ - - - -tmp_best_practices - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Best practices in development

    -
    -
    -
    -
    -
    -
    -
    -

    One virtual environment per project

    - -
    -
    -
    -
    -
    -
    -
    -

    Why

      -
    • Isolation
    • -
    • Different projects have different dependency versions
    • -
    • You don't want to mess up the system Python
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling

    pipenv is currently the recommended tool for dependency management but "consider other tools such as pip when pipenv does not meet your use case". If pipenv doesn't fit your use case, I recommend using virtualenvwrapper for managing virtual environments and pip for package management. On the other hand, if you're working on only a couple of projects, built-in venv will do just fine.

    -

    pipenv

    - -
    -
    -
    -
    -
    -
    -
    -

    virtualenvwrapper

      -
    • If you are using Windows command prompt: virtualenvwrapper-win
    • -
    • Like the name suggests, a wrapper around virtualenv
    • -
    • Eases the workflow for creating, deleting, and (de)activating your virtual environments
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    pyenv

      -
    • Easily change global / per project Python version
    • -
    • Also a tool for installing different Python versions (also different runtimes available, e.g. PyPy)
    • -
    • Useful if you'll need to work with different Python versions
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Test your code

    - -
    -
    -
    -
    -
    -
    -
    -

    Why

      -
    • No surprises (especially in production)
    • -
    • Make sure that everything works as expected
    • -
    • Make sure that old stuff works as expected after introducing new features (regression)
    • -
    • Tests give you confidence while refactoring
    • -
    • Good tests demonstrate the use cases of application, i.e. they also document the implementation
    • -
    • ...
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling

    pytest

    There's unittest module in Python Standard Library but the go-to test runner nowadays is definitely pytest.

    -

    Some reasons to use pytest:

    - - -
    -
    -
    -
    -
    -
    -
    -

    tox

    tox makes it simple to test your code against different Python interpreter/runtime and dependency versions. This is important when you're writing software which should support different Python versions, which is usually the case with library-like packages. On the other hand, if you're developing, say, a web application which will be deployed to a known target platform, testing against multiple different versions is usually not necessary. However, tox makes it also possible to configure, for example, linting as part of tox run. Thus, tox may simplify the development workflow significantly by wrapping multiple different operations under a single command.

    - -
    -
    -
    -
    -
    -
    -
    -

    Write high quality code

    - -
    -
    -
    -
    -
    -
    -
    -

    Why

      -
    • Easy to read
    • -
    • Better maintainability
    • -
    • Better quality == less bugs
    • -
    - -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    import this
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    The Zen of Python, by Tim Peters
    -
    -Beautiful is better than ugly.
    -Explicit is better than implicit.
    -Simple is better than complex.
    -Complex is better than complicated.
    -Flat is better than nested.
    -Sparse is better than dense.
    -Readability counts.
    -Special cases aren't special enough to break the rules.
    -Although practicality beats purity.
    -Errors should never pass silently.
    -Unless explicitly silenced.
    -In the face of ambiguity, refuse the temptation to guess.
    -There should be one-- and preferably only one --obvious way to do it.
    -Although that way may not be obvious at first unless you're Dutch.
    -Now is better than never.
    -Although never is often better than *right* now.
    -If the implementation is hard to explain, it's a bad idea.
    -If the implementation is easy to explain, it may be a good idea.
    -Namespaces are one honking great idea -- let's do more of those!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Tooling - code formatters

    PEP8 (see also "for humans version") describes the style guidelines for Python code, you should follow them. Luckily, there are awesome tools that handle this for you while you focus on writing code, not formatting it.

    - -
    -
    -
    -
    -
    -
    -
    -

    yapf

    - -
    -
    -
    -
    -
    -
    -
    -

    black

      -
    • Note requires Python 3.6+
    • -
    • Note "This is a beta product" while writing this
    • -
    • Uncompromising - not as many configuration options as in yapf
    • -
    • Good integration with editors
    • -
    • Try it in the playground
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling - linters

    Automatic code formatting is great but in addition to that, you should use static analyzer (linter) to detect potential pitfalls in your code.

    - -
    -
    -
    -
    -
    -
    -
    -

    flake8

    - -
    -
    -
    -
    -
    -
    -
    -

    pylint

      -
    • More verbose compared to flake8
    • -
    • Criticized about the default configuration but is easily configurable
    • -
    • Gives an overall score
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    bandit

      -
    • Checks for security vulnerabilities
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling - pre-commit

    pre-commit

    Ideally, all project contributors should follow the best practices of the project, let it be e.g. respecting PEP8 or making sure there's no linting errors or security vulnerabilities in their change sets. However, as code formatters and linters are (mainly) local tools, this can not be guaranteed. pre-commit let's you configure (.pre-commit-config.yaml file) a set of hooks that will be run as pre actions to a commit/push. After a developer has called once pre-commit install, these hooks will be then automatically ran prior each commit/push.

    -
      -
    • Run formatting before commit
    • -
    • Fail the commit in case linting errors
    • -
    • Even exercise the test suite before the code ends up to remote (might be time consuming in most scenarios though)
    • -
    • Easy to configure your own hooks
    • -
    • And use the existing ones
    • -
    • There's also pre-push option
    • -
    • Written in Python but supports also other languages, such as Ruby, Go, and Rust
    • -
    • Less failed CI builds!
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Structure your code and projects

    - -
    -
    -
    -
    -
    -
    -
    -

    Why

      -
    • Package and module structure gives an overview about the project
    • -
    • Modular design == better reusability
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    How

    Some general guidelines:

    -
      -
    • Don't put too much stuff into one module
    • -
    • Split project into packages
    • -
    • Be consistent with your naming conventions
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    A few words about structuring your projects. If you're developing, say, a relative big business application, it makes sense to separate some of the non-core business logic packages into a separate project and publish that as separate package. This way the "main" repository doesn't get bloated and it's more approachable for newcomers. Additionally, there's a change that you (or someone else) can easily reuse this "separated" package in the future, which is often the case e.g. for different kinds of utility functionalities.

    -

    Let's take a practical example. If your team has two different applications which interact with the same third party, it's beneficial to implement a separate client library for communication with it. This way a change is needed only in one place (in the client library) if the third party decides to make a backwards incompatible change in their API.

    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling

    cookiecutter

    - -
    -
    -
    -
    -
    -
    -
    -

    Cookiecutter is a tool which let's you create projects from predefined templates.

    -
      -
    • Rapid set-up of new projects, no need to copy paste from existing ones
    • -
    • Consistent development practices across all projects (project structure as well as e.g. pre-commit, tox, and CI configuration)
    • -
    • You can create one yourself or use some of the existing ones
    • -
    • Written in Python but is applicable for non-Python projects as well, even non-programming related directory and file structures
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Use continuous integration and deployment

    - -
    -
    -
    -
    -
    -
    -
    -

    CI & CD belong to the best practices of software development without controversy, no matter what is the technology stack used for development. From Python point of view, CI is the place where we want to make sure that the other best practices described above are followed. For example, in bigger projects, it may not be even practical/possible to run the full test suite on developer's machine.

    - -
    -
    -
    -
    -
    -
    -
    -

    Why

      -
    • Make sure the tests pass
    • -
    • CI is the place where it's possible to run also some time consuming tests which the impatient developers prefer to skip on their local machines
    • -
    • Make sure there's no linting errors
    • -
    • Ideally, the place to test against all target versions and platforms
    • -
    • Overall, CI is the last resort for automatically ensuring the quality
    • -
    • Manual deployments are time consuming and error-prone, CD is automated and deterministic
    • -
    • You want to automate as much as possible, human time is expensive
    • -
    • Minimize the time required for code reviews - what could be detected with automatic tools, should be detected by using those tools. Human time is expensive.
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling

    Tooling depends on which git repository manager option you've chosen and what kind of requirements you have. For example:

    - - -
    -
    -
    -
    -
    -
    -
    -

    Utilize the capabitilies of your editor

    -
    -
    -
    -
    -
    -
    -
    -

    Why

      -
    • Efficient and fluent development
    • -
    • There's plenty of tools to make your daily programming easier, why would you not use them
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling

    As there's a number of different editors and IDEs available, not to mention that everyone has their own preferences, I'll just focus on highlighting some of the features of my favorite IDE, PyCharm, which I highly recommend for Python development.

    -

    PyCharm

      -
    • Good integration with pytest, e.g. run single tests / test classes / test modules
    • -
    • Git integration (in case you don't like command line)
    • -
    • Easy to configure to use automatic formatting, e.g black
    • -
    • Intuitive searching capabilities
    • -
    • Refactoring features
    • -
    • Debugger
    • -
    • Jupyter Notebook integration
    • -
    • Free community edition already contains all you need
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Use existing solutions

    - -
    -
    -
    -
    -
    -
    -
    -

    Why

      -
    • Python Standard Library is extensive - and stable!
    • -
    • There are over 150k packages in PyPI
    • -
    • Someone has most likely solved the problem you're trying to solve
    • -
    • Spend 5 minutes doing a google research before starting to solve a new problem, e.g. stackoverflow is a magical place.
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Learn how to debug efficiently

    - -
    -
    -
    -
    -
    -
    -
    -

    Why

      -
    • You won't write completely stable code anyway - impossible looking conditions will occur.
    • -
    • When something is not working as expected, there are plenty of tools out there to help you figure out what's going on.
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling - debuggers

    pdb

      -
    • Part of the Standard Library
    • -
    • Sufficient for most use cases
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    ipdb

      -
    • Feature rich pdb with similar API
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    pdb++

      -
    • Drop-in replacement for pdb with additional features
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling - profilers

    -
    -
    -
    -
    -
    -
    -
    -

    gprof2dot

      -
    • Find the performance bottlenecks of your application via illustrative graphs
    • -
    • If you're using pytest (like you should), see also pytest-profiling which is powered by gprof2dot
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    py-spy

      -
    • Profile running Python program without the need for modifying the source code or restarting the target process
    • -
    • Potential tool for identifying problems of e.g. a web application in production
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    objgraph

      -
    • Graphs which are useful while hunting memory leaks
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling - runtime error tracking

    These are especially useful with web applications as you'll get reports - and notifications - of runtime exceptions with full tracebacks and variable values. This information is often enough for identifying the root cause of the problem, which is a huge benefit considering the time required for implementing and deploying the fix.

    - -
    -
    -
    -
    -
    -
    -
    -

    Sentry

      -
    • Complete stack traces with relevant variable (locals()) values
    • -
    • Browser and OS information of the client
    • -
    • Support for other languages as well
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    rollbar

      -
    • Very similar to sentry
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    While writing this, both sentry and rollbar are free for hobbyist use.

    - -
    -
    -
    -
    -
    -
    -
    -

    Tooling - misc

    -
    -
    -
    -
    -
    -
    -
    -

    Use logging instead of prints

    - -
    -
    -
    -
    -
    -
    -
    -
      -
    • logging is part of the Standard Library
    • -
    • With logging you can redirect the output to a file
    • -
    • Logs are usually the first place to look at after an end user reports an issue
    • -
    • You can specify the runtime level - no need to remove the debug prints
    • -
    - -
    -
    -
    -
    -
    -
    -
    -

    General guidelines

      -
    • Use Python 3, legacy Python (aka 2.7) will retire soon
    • -
    • Develop in branches. Even if you're the only person in the project, branching makes it possible to easily switch between different features / bug fixes.
    • -
    • If you're not developing alone, practice code reviews. It's one of the best ways to learn for both parties.
    • -
    • Document your master pieces
    • -
    - -
    -
    -
    -
    -
    - - - - - - diff --git a/notebooks/intermediate/html/idiomatic_dicts.html b/notebooks/intermediate/html/idiomatic_dicts.html deleted file mode 100644 index e9b6335..0000000 --- a/notebooks/intermediate/html/idiomatic_dicts.html +++ /dev/null @@ -1,12431 +0,0 @@ - - - -tmp_idiomatic_dicts - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Idiomatic dictionaries

    -
    -
    -
    -
    -
    -
    -
    -

    get - default value of a non existing key while accessing

    Especially handy if you're unsure about the presence of a key.

    - -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    my_dict = {'a': 1, 'b': 2, 'c': 3}
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    if 'g' in my_dict:
    -    value = my_dict['g']
    -else:
    -    value = 'some default value'
    -print(value)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    some default value
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Or like this.

    - -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    try:
    -    value = my_dict['g']
    -except KeyError:
    -    value = 'some default value'
    -print(value)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    some default value
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    value = my_dict.get('g', 'some default value')
    -print(value)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    some default value
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Note that if you don't provide the default value for get, the return value will be None if the key is not present in the dictionary

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    value = my_dict.get('g')
    -print(value is None)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    setdefault - same as get but also sets the value if not present

    -
    -
    -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    my_dict = {'a': 1, 'b': 2, 'c': 3}
    -
    -key = 'g'
    -if key in my_dict:
    -    value = my_dict[key]
    -else:
    -    value = 'some default value'
    -    my_dict[key] = value
    -    
    -print(value)
    -print(my_dict)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    some default value
    -{'g': 'some default value', 'c': 3, 'b': 2, 'a': 1}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Let's do it like this!

    -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    my_dict = {'a': 1, 'b': 2, 'c': 3}
    -
    -key = 'g'
    -value = my_dict.setdefault(key, 'some default value')
    -
    -print(value)
    -print(my_dict)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    some default value
    -{'g': 'some default value', 'c': 3, 'b': 2, 'a': 1}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Comprehensions

    Let's say we have a collection of numbers and we want to store those as a dictionary where the number is key and it's square is the value.

    - -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    numbers = (1, 5, 10)
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    squares = {}
    -for num in numbers:
    -    squares[num] = num**2
    -print(squares)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {1: 1, 10: 100, 5: 25}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    squares = {num: num**2 for num in numbers}
    -print(squares)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {1: 1, 10: 100, 5: 25}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Another example

    -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    keys = ('a', 'b', 'c')
    -values = [True, 100, 'John Doe']
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [12]:
    -
    -
    -
    my_dict = {}
    -for idx, key in enumerate(keys):
    -    my_dict[key] = values[idx]
    -print(my_dict)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'c': 'John Doe', 'b': 100, 'a': True}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [13]:
    -
    -
    -
    my_dict = {k: v for k, v in zip(keys, values)}
    -print(my_dict)
    -
    -# Or even like this:
    -my_dict2 = dict(zip(keys, values))
    -
    -assert my_dict2 == my_dict
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'c': 'John Doe', 'b': 100, 'a': True}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Looping

    -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    my_dict = {'age': 83, 'is gangster': True, 'name': 'John Doe'}
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [15]:
    -
    -
    -
    for key in my_dict:
    -    val = my_dict[key]
    -    print('key: {:15s} value: {}'.format(key, val))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    key: is gangster     value: True
    -key: age             value: 83
    -key: name            value: John Doe
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [16]:
    -
    -
    -
    for key, val in my_dict.items():
    -    print('key: {:15s} value: {}'.format(key, val))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    key: is gangster     value: True
    -key: age             value: 83
    -key: name            value: John Doe
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/intermediate/html/idiomatic_loops.html b/notebooks/intermediate/html/idiomatic_loops.html deleted file mode 100644 index 9e704b3..0000000 --- a/notebooks/intermediate/html/idiomatic_loops.html +++ /dev/null @@ -1,12544 +0,0 @@ - - - -tmp_idiomatic_loops - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Idiomatic loops

    -
    -
    -
    -
    -
    -
    -
    -

    Looping in general

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    data = ['John', 'Doe', 'was', 'here']
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this. While loops are actually really rarely needed.

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    idx = 0
    -while idx < len(data):
    -    print(data[idx])
    -    idx += 1
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John
    -Doe
    -was
    -here
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Don't do like this either.

    - -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    for idx in range(len(data)):
    -    print(data[idx])
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John
    -Doe
    -was
    -here
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    for item in data:
    -    print(item)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John
    -Doe
    -was
    -here
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    If you need the index as well, you can use enumerate.

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    for idx, val in enumerate(data):
    -    print('{}: {}'.format(idx, val))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0: John
    -1: Doe
    -2: was
    -3: here
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Looping over a range of numbers

    -
    -
    -
    -
    -
    -
    -
    -

    Don't do this.

    - -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    i = 0
    -while i < 6:
    -    print(i)
    -    i += 1
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0
    -1
    -2
    -3
    -4
    -5
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Don't do this either.

    - -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    for val in [0, 1, 2, 3, 4, 5]:
    -    print(val)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0
    -1
    -2
    -3
    -4
    -5
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    for val in range(6):
    -    print(val)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0
    -1
    -2
    -3
    -4
    -5
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Reversed looping

    -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    data = ['first', 'to', 'last', 'from'] 
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    This is no good.

    - -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    i = len(data) - 1
    -while i >= 0:
    -    print(data[i])
    -    i -= 1
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    from
    -last
    -to
    -first
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    for item in reversed(data):
    -    print(item)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    from
    -last
    -to
    -first
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Looping over n collections simultaneously

    -
    -
    -
    -
    -
    -
    In [12]:
    -
    -
    -
    collection1 = ['a', 'b', 'c']
    -collection2 = (10, 20, 30, 40, 50)
    -collection3 = ['John', 'Doe', True]
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Oh boy, not like this.

    - -
    -
    -
    -
    -
    -
    In [13]:
    -
    -
    -
    shortest = len(collection1)
    -if len(collection2) < shortest:
    -    shortest = len(collection2)
    -if len(collection3) < shortest:
    -    shortest = len(collection3)
    -    
    -i = 0
    -while i < shortest:
    -    print(collection1[i], collection2[i], collection3[i])
    -    i += 1
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    a 10 John
    -b 20 Doe
    -c 30 True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    This is getting better but there's even a better way!

    - -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    shortest = min(len(collection1), len(collection2), len(collection3))
    -for i in range(shortest):
    -    print(collection1[i], collection2[i], collection3[i])
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    a 10 John
    -b 20 Doe
    -c 30 True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [15]:
    -
    -
    -
    for first, second, third in zip(collection1, collection2, collection3):
    -    print(first, second, third)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    a 10 John
    -b 20 Doe
    -c 30 True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    You can also create a dict out of two collections!

    - -
    -
    -
    -
    -
    -
    In [16]:
    -
    -
    -
    my_dict = dict(zip(collection1, collection2))
    -print(my_dict)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'a': 10, 'b': 20, 'c': 30}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    for - else - Checking for a match in a collection

    Let's say we want to verify a certain condition is met by at least one element in a collection. Let's consider the following relatively naive example where we want to verify that at least one item is "python" (case insensitive) in data. If not, we'll raise a ValueError.

    - -
    -
    -
    -
    -
    -
    In [17]:
    -
    -
    -
    data = [1, 2, 3, 'This', 'is', 'just', 'a', 'random', 'Python', 'list']
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this

    - -
    -
    -
    -
    -
    -
    In [18]:
    -
    -
    -
    found = False
    -for val in data:
    -    if str(val).lower() == 'python':
    -        found = True
    -        break
    -if not found:
    -    raise ValueError("Nope, couldn't find.")
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [19]:
    -
    -
    -
    for val in data:
    -    if str(val).lower() == 'python':
    -        break
    -else:
    -    raise ValueError("Nope, couldn't find.")
    -
    - -
    -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/intermediate/html/idiomatic_misc1.html b/notebooks/intermediate/html/idiomatic_misc1.html deleted file mode 100644 index b537c29..0000000 --- a/notebooks/intermediate/html/idiomatic_misc1.html +++ /dev/null @@ -1,12875 +0,0 @@ - - - -tmp_idiomatic_misc1 - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Idiomatic Python - miscellaneous part 1

    -
    -
    -
    -
    -
    -
    -
    -

    Comprehensions

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    original_data = (1, 2, 3, 4)
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do this.

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    # list
    -square_roots_list = []
    -for val in original_data:
    -    square_root = val**(1/2) 
    -    square_roots_list.append(square_root)
    -print(square_roots_list)
    -
    -# set
    -square_roots_set = set()
    -for val in original_data:
    -    square_root = val**(1/2) 
    -    square_roots_set.add(square_root)
    -print(square_roots_set)
    -
    -# dict
    -square_roots_dict = {}
    -for val in original_data:
    -    square_root = val**(1/2) 
    -    square_roots_dict[val] = square_root
    -print(square_roots_dict) 
    -
    -# dict with a condition
    -integer_square_roots_dict = {}
    -for val in original_data:
    -    square_root = val**(1/2)
    -    if square_root.is_integer():
    -        integer_square_roots_dict[val] = square_root
    -print(integer_square_roots_dict) 
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    [1.0, 1.4142135623730951, 1.7320508075688772, 2.0]
    -{1.0, 2.0, 1.7320508075688772, 1.4142135623730951}
    -{1: 1.0, 2: 1.4142135623730951, 3: 1.7320508075688772, 4: 2.0}
    -{1: 1.0, 4: 2.0}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    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.

    - -
    -
    -
    -
    -
    -
    -
    -

    Use comprehensions!

    -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    square_roots_list = [val**(1/2) for val in original_data]
    -print(square_roots_list)
    -
    -square_roots_set = {val**(1/2) for val in original_data}
    -print(square_roots_set)
    -
    -square_roots_dict = {val: val**(1/2) for val in original_data}
    -print(square_roots_dict)
    -
    -integer_square_roots_dict = {
    -    val: val**(1/2)
    -    for val in original_data if (val**(1/2)).is_integer()
    -}
    -print(integer_square_roots_dict)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    [1.0, 1.4142135623730951, 1.7320508075688772, 2.0]
    -{1.0, 2.0, 1.7320508075688772, 1.4142135623730951}
    -{1: 1.0, 2: 1.4142135623730951, 3: 1.7320508075688772, 4: 2.0}
    -{1: 1.0, 4: 2.0}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Using in for checking presence of an element in a collection

    -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    name = 'John Doe'
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    if name == 'John' or name == 'Doe' or name == 'John Doe':
    -    print('This seems to be our guy')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    This seems to be our guy
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    if name in ('John', 'Doe', 'John Doe'):
    -    print('This seems to be our guy')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    This seems to be our guy
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Chained comparisons

    -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    a, b, c, d = 1, 2, 3, 4
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    if b > a and c > b and d > c:
    -    print('from lowest to highest: a, b, c, d')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    from lowest to highest: a, b, c, d
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    if a < b < c < d:
    -    print('from lowest to highest: a, b, c, d')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    from lowest to highest: a, b, c, d
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Falsy/truthy values

    -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    # These are falsy
    -my_list = []
    -my_dict = {}
    -my_set = set()
    -my_tuple = tuple()
    -zero = 0
    -false = False
    -none = None
    -my_str = ''
    -
    -# Basically the rest are truthy
    -# for example:
    -my_second_list = ['foo']
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    if len(my_list) == 0:
    -    print('Empty list is so empty')
    -    
    -if not len(my_dict):
    -    print('Empty dict is also very empty')
    -    
    -if not len(my_set) and not len(my_tuple):
    -    print('Same goes for sets and tuples')
    -    
    -if not bool(zero) and not bool(false) and not bool(none) and len(my_str) == 0:
    -    print('These are also falsy')
    -    
    -if len(my_second_list) > 0:
    -    print('This should be true')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Empty list is so empty
    -Empty dict is also very empty
    -Same goes for sets and tuples
    -These are also falsy
    -This should be true
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    This is much better!

    -
    -
    -
    -
    -
    -
    In [12]:
    -
    -
    -
    if not my_list:
    -    print('Empty list is so empty')
    -    
    -if not my_dict:
    -    print('Empty dict is also very empty')
    -    
    -if not my_set and not my_tuple:
    -    print('Same goes for sets and tuples')
    -    
    -if not zero and not false and not none and not my_str:
    -    print('These are also falsy')
    -    
    -if my_second_list:
    -    print('This should be true')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Empty list is so empty
    -Empty dict is also very empty
    -Same goes for sets and tuples
    -These are also falsy
    -This should be true
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    any & all

    -
    -
    -
    -
    -
    -
    In [13]:
    -
    -
    -
    example_collection = ['a', True, 'Python is cool', 123, 0]
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    any_value_truthy = True
    -for val in example_collection:
    -    if val:
    -        any_value_truthy = True
    -        break
    -
    -all_values_truthy = True
    -for val in example_collection:
    -    if not val:
    -        all_values_truthy = False
    -        break
    -        
    -print('any truthy: {}, all truthy: {}'.format(any_value_truthy, all_values_truthy))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    any truthy: True, all truthy: False
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [15]:
    -
    -
    -
    any_value_truthy = any(example_collection)
    -all_values_truthy = all(example_collection)
    -print('any truthy: {}, all truthy: {}'.format(any_value_truthy, all_values_truthy))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    any truthy: True, all truthy: False
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Pythonic substitute for ternary operator

    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:

    - -
    variable = some_condition ? some_value : some_other_value
    - -
    -
    -
    -
    -
    -
    -
    -

    Instead of doing this.

    - -
    -
    -
    -
    -
    -
    In [16]:
    -
    -
    -
    some_condition = True  # just a dummy condition
    -
    -if some_condition:
    -    variable = 'John'
    -else:
    -    variable = 'Doe'
    -print(variable)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    You can do it like this!

    -
    -
    -
    -
    -
    -
    In [17]:
    -
    -
    -
    variable = 'John' if some_condition else 'Doe'
    -print(variable)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Function keywords arguments

    For better readability and maintainability.

    - -
    -
    -
    -
    -
    -
    In [18]:
    -
    -
    -
    def show_person_details(name, is_gangster, is_hacker, age):
    -    print('name: {}, gangster: {}, hacker: {}, age: {}'.format(
    -        name, is_gangster, is_hacker, age))
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    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.

    - -
    -
    -
    -
    -
    -
    In [19]:
    -
    -
    -
    show_person_details('John Doe', True, False, 83)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    name: John Doe, gangster: True, hacker: False, age: 83
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    This is much better!

    -
    -
    -
    -
    -
    -
    In [20]:
    -
    -
    -
    show_person_details('John Doe', is_gangster=True, is_hacker=False, age=83)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    name: John Doe, gangster: True, hacker: False, age: 83
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Extra: keyword only arguments after `*`

    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 *.

    - -
    -
    -
    -
    -
    -
    In [21]:
    -
    -
    -
    def func_with_loads_of_args(arg1, *, arg2=None, arg3=None, arg4=None, arg5='boom'):
    -    pass
    -
    -# This won't work because only keyword arguments allowed after *
    -#func_with_loads_of_args('John Doe', 1, 2)
    -
    -# This is ok
    -func_with_loads_of_args('John Doe', arg4='foo', arg5='bar', arg2='foo bar')
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Multiple assigment

    Let's say we want to swap the values of two variables.

    - -
    -
    -
    -
    -
    -
    -
    -

    Don't do it like this.

    - -
    -
    -
    -
    -
    -
    In [22]:
    -
    -
    -
    # original values
    -a = 1
    -b = 2
    -
    -# swap
    -tmp = a
    -a = b
    -b = tmp
    -print(a, b)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    2 1
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this!

    -
    -
    -
    -
    -
    -
    In [23]:
    -
    -
    -
    # original values
    -a = 1
    -b = 2
    -
    -# swap
    -a, b = b, a
    -print(a, b)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    2 1
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    (Un)packing

    -
    -
    -
    -
    -
    -
    In [24]:
    -
    -
    -
    my_list = [1, 2, 3, 4, 5, 6]
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do something like this.

    - -
    -
    -
    -
    -
    -
    In [25]:
    -
    -
    -
    first = my_list[0]
    -last = my_list[-1]
    -middle = my_list[1:-1]
    -print(first, middle, last)
    -
    -packed = [first] + middle + [last]
    -assert packed == my_list
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    1 [2, 3, 4, 5] 6
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    This is the Pythonic way!

    -
    -
    -
    -
    -
    -
    In [26]:
    -
    -
    -
    # unpacking
    -first, *middle, last = my_list
    -print(first, middle, last)
    -
    -# packing
    -packed = [first, *middle, last]
    -assert packed == my_list
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    1 [2, 3, 4, 5] 6
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/intermediate/html/idiomatic_misc2.html b/notebooks/intermediate/html/idiomatic_misc2.html deleted file mode 100644 index ac6087b..0000000 --- a/notebooks/intermediate/html/idiomatic_misc2.html +++ /dev/null @@ -1,12761 +0,0 @@ - - - -tmp_idiomatic_misc2 - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Idiomatic Python - miscellaneous part 2

    -
    -
    -
    -
    -
    -
    -
    -

    String concatenation

    -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    names = ('John', 'Lisa', 'Terminator', 'Python')
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Don't do this.

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    semicolon_separated = names[0]
    -for name in names[1:]:
    -    semicolon_separated += ';' + name
    -print(semicolon_separated)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John;Lisa;Terminator;Python
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Use `join` instead!

    -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    semicolon_separated = ';'.join(names)
    -print(semicolon_separated)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John;Lisa;Terminator;Python
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    or in assignments

    The return value of a or b:

    -
      -
    • a if a is truthy
    • -
    • b otherwise
    • -
    -

    You can take advantage of this e.g. while writing variable assignments.

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    a = 0
    -b = None
    -c = 'John Doe'
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Instead of doing something like this:

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    my_variable = 'default value'
    -if a:
    -    my_variable = a
    -elif b:
    -    my_variable = b
    -elif c:
    -    my_variable = c
    -print(my_variable)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John Doe
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Prefer doing this:

    -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    my_variable = a or b or c or 'default value'
    -print(my_variable)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John Doe
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    try - except - else

    -
    -
    -
    -
    -
    -
    -
    -

    Don't use the following technique for checking if there was exceptions during execution of some block of code.

    - -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    exception_occured = False
    -try:
    -    # here would be the logic of your master piece
    -    
    -    bad_calculation = 1 / 0
    -    
    -except ValueError as e:
    -    print('Oh boi, some value error: {}'.format(e))
    -    exception_occured = True
    -except Exception as e:
    -    print('Oh boi, something bad happened: {}'.format(e))
    -    exception_occured = True
    -    
    -if not exception_occured:
    -    print('All went well!')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Oh boi, something bad happened: division by zero
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Use this instead!

    -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    try:
    -    # here would be the logic of your master piece
    -    
    -    bad_calculation = 1 / 0
    -    
    -except ValueError as e:
    -    print('Oh boi, some keyerror: {}'.format(e))
    -except Exception as e:
    -    print('Oh boi, something bad happened: {}'.format(e))
    -else:
    -    print('All went well!')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Oh boi, something bad happened: division by zero
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    try - finally

    For scenarios where you want to do something always, even when there are exceptions.

    - -
    -
    -
    -
    -
    -
    -
    -

    Don't do it like this

    - -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    def magical_calculation():
    -    try:
    -        # here would be the logic of your master piece
    -        result = 1 / 0
    -    except ZeroDivisionError:
    -        print('This could be something important that should be done every time')
    -        return 0
    -    except Exception:
    -        print('This could be something important that should be done every time')
    -        return None
    -
    -    print('This could be something important that should be done every time')
    -    return result
    -
    -print('return value: {}'.format(magical_calculation()))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    This could be something important that should be done every time
    -return value: 0
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    This is better fit for the purpose!

    -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    def magical_calculation():
    -    try:
    -        # here would be the logic of your master piece
    -        result = 1 / 0
    -    except ZeroDivisionError:
    -        return 0
    -    except Exception:
    -        return None
    -    finally:
    -        print('This could be something important that should be done every time')
    -    return result
    -
    -print('return value: {}'.format(magical_calculation()))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    This could be something important that should be done every time
    -return value: 0
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Note: You can also have try-except-else-finally structure. In cases where exception is not raised inside try, else will be executed before finally. If there is an expection, else block is not executed.

    - -
    -
    -
    -
    -
    -
    -
    -

    Use context managers when possible

    One use case example is file I/O.

    - -
    -
    -
    -
    -
    -
    -
    -

    Don't play with files like this.

    - -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    try:
    -    some_file = open('tmp.txt', 'w')
    -    print('the file is now open: {}'.format(not some_file.closed))
    -    
    -    # here would be some logic
    - 
    -finally:
    -    some_file.close()
    -    print("now it's closed: {}".format(some_file.closed))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    the file is now open: True
    -now it's closed: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Use context manager instead!

    -
    -
    -
    -
    -
    -
    In [12]:
    -
    -
    -
    with open('tmp.txt', 'w') as some_file:
    -    print('the file is now open: {}'.format(not some_file.closed))
    -    
    -    # here would be some logic
    -
    -print("now it's closed: {}".format(some_file.closed))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    the file is now open: True
    -now it's closed: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    It's also easy to implement one yourself.

    -
    -
    -
    -
    -
    -
    In [13]:
    -
    -
    -
    from contextlib import contextmanager
    -
    -@contextmanager
    -def my_context():
    -    print('Entering to my context')
    -    yield
    -    print('Exiting my context')
    -    
    -def do_stuff():
    -    with my_context():
    -        print('Doing stuff')
    -        
    -    print('Doing some stuff outside my context')
    -        
    -do_stuff()  
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Entering to my context
    -Doing stuff
    -Exiting my context
    -Doing some stuff outside my context
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    min() & max()

    -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    secret_data = (1, 2, 5, 99, 8, -9)
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    No need to bake it yourself.

    - -
    -
    -
    -
    -
    -
    In [15]:
    -
    -
    -
    max_value = 0
    -for val in secret_data:
    -    if val > max_value:
    -        max_value = val
    -print(max_value)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    99
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Use builtin functionality instead!

    -
    -
    -
    -
    -
    -
    In [16]:
    -
    -
    -
    max_value = max(secret_data)
    -print(max_value)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    99
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    contextlib.suppress - ignoring exceptions

    -
    -
    -
    -
    -
    -
    -
    -

    If there's a potential exception that is ok, don't handle it like this.

    - -
    -
    -
    -
    -
    -
    In [17]:
    -
    -
    -
    value = 0
    -try:
    -    value = 1 / 0  # just for demonstrating purposes 
    -except ZeroDivisionError:
    -    pass
    -
    -print(value)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Do it like this instead!

    -
    -
    -
    -
    -
    -
    In [18]:
    -
    -
    -
    from contextlib import suppress
    -
    -value = 0
    -with suppress(ZeroDivisionError):
    -    value = 1 / 0  # just for demonstrating purposes
    -    
    -print(value)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    0
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Properties instead of getter/setter methods

    -
    -
    -
    -
    -
    -
    -
    -

    Instead of doing something like this.

    - -
    -
    -
    -
    -
    -
    In [19]:
    -
    -
    -
    class Person:
    -    def __init__(self, first_name, last_name):
    -        self.first_name = first_name
    -        self.last_name = last_name
    -        
    -    def get_full_name(self):
    -        return '{} {}'.format(self.first_name, self.last_name)
    -    
    -    def set_full_name(self, full_name):
    -        parts = full_name.split()
    -        if len(parts) != 2:
    -            raise ValueError('Sorry, too difficult name')
    -            
    -        self.first_name, self.last_name = parts 
    -        
    -      
    -p = Person('John', 'Doe')
    -print(p.get_full_name())
    -p.set_full_name('Lisa Doe')
    -print(p.get_full_name())
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John Doe
    -Lisa Doe
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Prefer properties!

    -
    -
    -
    -
    -
    -
    In [20]:
    -
    -
    -
    class Person:
    -    def __init__(self, first_name, last_name):
    -        self.first_name = first_name
    -        self.last_name = last_name
    -        
    -    @property
    -    def full_name(self):
    -        return '{} {}'.format(self.first_name, self.last_name)
    -    
    -    @full_name.setter
    -    def full_name(self, name):
    -        parts = name.split()
    -        if len(parts) != 2:
    -            raise ValueError('Sorry, too difficult name')
    -            
    -        self.first_name, self.last_name = parts
    -
    -    
    -p = Person('John', 'Doe')
    -print(p.full_name)
    -p.full_name = 'Lisa Doe'
    -print(p.full_name)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    John Doe
    -Lisa Doe
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/intermediate/html/pytest_fixtures.html b/notebooks/intermediate/html/pytest_fixtures.html deleted file mode 100644 index 665ffc7..0000000 --- a/notebooks/intermediate/html/pytest_fixtures.html +++ /dev/null @@ -1,12542 +0,0 @@ - - - -tmp_pytest_fixtures - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Efficient use of pytest fixtures

    -
    -
    -
    -
    -
    -
    -
    -

    Required boilerplate for using pytest inside notebooks.

    - -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    # Let's make sure pytest and ipytest packages are installed
    -# ipytest is required for running pytest inside Jupyter notebooks
    -import sys
    -!{sys.executable} -m pip install pytest 'ipytest>=0.3.0'
    -
    -import pytest
    -from ipytest import magics, clean_tests
    -__file__ = 'pytest_fixtures.ipynb'
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Requirement already satisfied: pytest in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (3.5.0)
    -Requirement already satisfied: ipytest>=0.3.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (0.3.0)
    -Requirement already satisfied: attrs>=17.4.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (17.4.0)
    -Requirement already satisfied: pluggy<0.7,>=0.5 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (0.6.0)
    -Requirement already satisfied: setuptools in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (39.0.1)
    -Requirement already satisfied: py>=1.5.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.5.3)
    -Requirement already satisfied: more-itertools>=4.0.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (4.1.0)
    -Requirement already satisfied: six>=1.10.0 in /Users/jerry/.virtualenvs/learn-python3/lib/python3.5/site-packages (from pytest) (1.11.0)
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Parametrizing fixtures

    Similarly as you can parametrize test functions with pytest.mark.parametrize, you can parametrize fixtures:

    - -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    PATHS = ['/foo/bar.txt', '/bar/baz.txt']
    -
    -@pytest.fixture(params=PATHS)
    -def executable(request):
    -    return request.param
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [3]:
    -
    -
    -
    %%run_pytest[clean] '-s'
    -
    -def test_something_with_executable(executable):
    -    print(executable)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================ test session starts =================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 2 items
    -
    -pytest_fixtures.py /foo/bar.txt
    -./bar/baz.txt
    -.
    -
    -============================================================================== 2 passed in 0.02 seconds ==============================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    pytest.mark.usefixtures

    pytest.mark.usefixtures is useful especially when you want to use some fixture in a set of tests but you don't need the return value of the fixture.

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    @pytest.fixture
    -def my_fixture():
    -    print('\nmy_fixture is used')
    -
    -@pytest.fixture
    -def other_fixture():
    -    return 'FOO'
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [5]:
    -
    -
    -
    %%run_pytest[clean] '-s'
    -
    -@pytest.mark.usefixtures('my_fixture')
    -class TestMyStuff:
    -    def test_somestuff(self):
    -        pass
    -    
    -    def test_some_other_stuff(self, other_fixture):
    -        print('here we use also other_fixture which returns: {}'.format(other_fixture))
    -        pass
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================ test session starts =================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 2 items
    -
    -pytest_fixtures.py 
    -my_fixture is used
    -.
    -my_fixture is used
    -here we use also other_fixture which returns: FOO
    -.
    -
    -================================================================================== warnings summary ==================================================================================
    -None
    -  Module already imported so cannot be rewritten: nbval
    -
    --- Docs: http://doc.pytest.org/en/latest/warnings.html
    -======================================================================== 2 passed, 1 warnings in 0.02 seconds ========================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    In [6]:
    -
    -
    -
    # Needed to clean up test classes (Test*) in ipytest
    -clean_tests('Test*')
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    pytest built-in fixtures

    Here are a couple of examples of the useful built-in fixtures, you can view all available fixtures by running pytest --fixtures.

    - -
    -
    -
    -
    -
    -
    -
    -

    monkeypatch

    Built-in monkeypatch fixture lets you e.g. set environment variables and set/delete attributes of objects. The use cases are similar as with patching/mocking with unittest.mock.patch/unittest.mock.MagicMock which are part of the Python Standard Library.

    -

    Monkeypatching environment variables:

    - -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    import os
    -
    -def get_env_var_or_none(var_name):
    -    return os.environ.get(var_name, None)
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [8]:
    -
    -
    -
    %%run_pytest[clean] '-s'
    -
    -def test_get_env_var_or_none_with_valid_env_var(monkeypatch):
    -    monkeypatch.setenv('MY_ENV_VAR', 'secret')
    -    res = get_env_var_or_none('MY_ENV_VAR')
    -    assert res == 'secret'
    -    
    -def test_get_env_var_or_none_with_missing_env_var():
    -    res = get_env_var_or_none('NOT_EXISTING')
    -    assert res is None
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================ test session starts =================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 2 items
    -
    -pytest_fixtures.py ..
    -
    -================================================================================== warnings summary ==================================================================================
    -None
    -  Module already imported so cannot be rewritten: nbval
    -
    --- Docs: http://doc.pytest.org/en/latest/warnings.html
    -======================================================================== 2 passed, 1 warnings in 0.02 seconds ========================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Monkeypatching attributes:

    - -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    class SomeClass:
    -    some_value = 'some value'
    -    
    -    @staticmethod
    -    def tell_the_truth():
    -        print('This is the original truth')
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [10]:
    -
    -
    -
    def fake_truth():
    -    print('This is modified truth')
    -
    -@pytest.fixture
    -def fake_some_class(monkeypatch): 
    -    monkeypatch.setattr('__main__.SomeClass.some_value', 'fake value')
    -    monkeypatch.setattr('__main__.SomeClass.tell_the_truth', fake_truth)
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [11]:
    -
    -
    -
    %%run_pytest[clean] '-s'
    -
    -def test_some_class(fake_some_class):
    -    print(SomeClass.some_value)
    -    SomeClass.tell_the_truth()
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================ test session starts =================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 1 item
    -
    -pytest_fixtures.py fake value
    -This is modified truth
    -.
    -
    -================================================================================== warnings summary ==================================================================================
    -None
    -  Module already imported so cannot be rewritten: nbval
    -
    --- Docs: http://doc.pytest.org/en/latest/warnings.html
    -======================================================================== 1 passed, 1 warnings in 0.02 seconds ========================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    tmpdir

    tmpdir fixture provides functionality for creating temporary files and directories.

    - -
    -
    -
    -
    -
    -
    In [12]:
    -
    -
    -
    def word_count_of_txt_file(file_path):
    -    with open(file_path, 'r') as f:
    -        content = f.read()
    -        return len(content.split())
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [13]:
    -
    -
    -
    %%run_pytest[clean] '-s'
    -
    -def test_word_count(tmpdir):
    -    test_file = tmpdir.join('test.txt')
    -    test_file.write('This is example content of seven words')
    -    res = word_count_of_txt_file(str(test_file)) # str returns the path
    -    assert res == 7
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================ test session starts =================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 1 item
    -
    -pytest_fixtures.py .
    -
    -================================================================================== warnings summary ==================================================================================
    -None
    -  Module already imported so cannot be rewritten: nbval
    -
    --- Docs: http://doc.pytest.org/en/latest/warnings.html
    -======================================================================== 1 passed, 1 warnings in 0.02 seconds ========================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Fixture scope

    -
    -
    -
    -
    -
    -
    In [14]:
    -
    -
    -
    # scope is function also by default
    -@pytest.fixture(scope='function')
    -def func_fixture():
    -    print('\nfunc')
    -    
    -@pytest.fixture(scope='module')
    -def module_fixture():
    -    print('\nmodule')
    -    
    -@pytest.fixture(scope='session')
    -def session_fixture():
    -    print('\nsession')  
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [15]:
    -
    -
    -
    %%run_pytest[clean] '-s'
    -
    -def test_something(func_fixture, module_fixture, session_fixture):
    -    pass
    -
    -def test_something_else(func_fixture, module_fixture, session_fixture):
    -    pass
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================ test session starts =================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 2 items
    -
    -pytest_fixtures.py 
    -session
    -
    -module
    -
    -func
    -.
    -func
    -.
    -
    -================================================================================== warnings summary ==================================================================================
    -None
    -  Module already imported so cannot be rewritten: nbval
    -
    --- Docs: http://doc.pytest.org/en/latest/warnings.html
    -======================================================================== 2 passed, 1 warnings in 0.02 seconds ========================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Setup-teardown behaviour

    -
    -
    -
    -
    -
    -
    In [16]:
    -
    -
    -
    @pytest.fixture
    -def some_fixture():
    -    print('some_fixture is run now')
    -    yield 'some magical value'
    -    print('\nthis will be run after test execution, you can do e.g. some clean up here')
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [17]:
    -
    -
    -
    %%run_pytest[clean] '-s'
    -
    -def test_something(some_fixture):
    -    print('running test_something')
    -    assert some_fixture == 'some magical value'
    -    print('test ends here')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================ test session starts =================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 1 item
    -
    -pytest_fixtures.py some_fixture is run now
    -running test_something
    -test ends here
    -.
    -this will be run after test execution, you can do e.g. some clean up here
    -
    -
    -================================================================================== warnings summary ==================================================================================
    -None
    -  Module already imported so cannot be rewritten: nbval
    -
    --- Docs: http://doc.pytest.org/en/latest/warnings.html
    -======================================================================== 1 passed, 1 warnings in 0.02 seconds ========================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Using fixtures automatically

    -
    -
    -
    -
    -
    -
    In [18]:
    -
    -
    -
    @pytest.fixture(autouse=True)
    -def my_fixture():
    -    print('\nusing my_fixture')
    -
    - -
    -
    -
    - -
    -
    -
    -
    In [19]:
    -
    -
    -
    %%run_pytest[clean] '-s'
    -
    -def test_1():
    -    pass
    -    
    -def test_2():
    -    pass
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    ================================================================================ test session starts =================================================================================
    -platform darwin -- Python 3.5.4, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
    -rootdir: /Users/jerry/github/jerry-git/learn-python3, inifile: pytest.ini
    -plugins: nbval-0.9.0
    -collected 2 items
    -
    -pytest_fixtures.py 
    -using my_fixture
    -.
    -using my_fixture
    -.
    -
    -================================================================================== warnings summary ==================================================================================
    -None
    -  Module already imported so cannot be rewritten: nbval
    -
    --- Docs: http://doc.pytest.org/en/latest/warnings.html
    -======================================================================== 2 passed, 1 warnings in 0.02 seconds ========================================================================
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/intermediate/html/std_lib2.html b/notebooks/intermediate/html/std_lib2.html deleted file mode 100644 index a0a8d32..0000000 --- a/notebooks/intermediate/html/std_lib2.html +++ /dev/null @@ -1,12366 +0,0 @@ - - - -tmp_std_lib2 - - - - - - - - - - - - - - - - - - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    -

    Goodies of the Python Standard Library

    -
    -
    -
    -
    -
    -
    -
    -

    json for encoding and decoding JSON

    Because the web is filled with JSON nowadays and the good days of xml are gone.

    - -
    -
    -
    -
    -
    -
    In [1]:
    -
    -
    -
    data = {'b': True, 'a': 1, 'nested': {'foo': 'bar'}, 'c': None, 'some_list': [1, 2, 3]}
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    Encoding

    -
    -
    -
    -
    -
    -
    In [2]:
    -
    -
    -
    import json
    -json_data = json.dumps(data)
    -print('type: {} data: {}'.format(type(json_data), json_data))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    type: <class 'str'> data: {"c": null, "b": true, "some_list": [1, 2, 3], "a": 1, "nested": {"foo": "bar"}}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Decoding

    -
    -
    -
    -
    -
    -
    In [3]:
    -
    -
    -
    decoded = json.loads(json_data)
    -print('type: {} data: {}'.format(type(decoded), decoded))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    type: <class 'dict'> data: {'c': None, 'nested': {'foo': 'bar'}, 'b': True, 'some_list': [1, 2, 3], 'a': 1}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    unittest.mock

    Although pytest is the preferred testing framework, unittest.mock module offers some goodies that are helpful also in pytest test cases. Mocking and patching are generally useful for "faking" some parts of the logic/state of the software under test. Common use cases are, for example, patching parts of code that interact with 3rd parties (e.g. some web services).

    - -
    -
    -
    -
    -
    -
    -
    -

    MagicMock

    In general, Mocks are simulated objects that replace the functionality/state of a real world object in a controlled way. Thus, they are especially useful in tests for mimicing some behavior of a specific part of the implementation under test.

    -

    There is also a Mock class in the Python Standard Library but you usually want to use MagicMock which is a subclass of Mock. MagicMock provides default implementation for the most of the magic methods (e.g. __setitem__() and __getitem__())

    -

    A potential use case could be something like this:

    - -
    -
    -
    -
    -
    -
    In [4]:
    -
    -
    -
    import random
    -
    -class Client:
    -    def __init__(self, url, username, password):
    -        self.url = url
    -        self.creds = (username, password)
    -        
    -    def fetch_some_data(self):
    -        print('Here we could for example fetch data from 3rd party API and return the data.')
    -        print('Now we will just return some random number between 1-100.')
    -        return random.randint(1, 100)
    -
    -
    -class MyApplication:
    -    def __init__(self):
    -        self.client = Client(url='https://somewhere/api', username='John Doe', password='secret123?')
    -        
    -    def do_something_fancy(self):
    -        data = self.client.fetch_some_data()
    -        return data**(1/2) # let's return a square root just for example
    -    
    -    
    -####################
    -# In the test module:
    -
    -from unittest.mock import MagicMock
    -
    -# Inside a test case:
    -app = MyApplication()
    -app.client = MagicMock() # Mock the client
    -app.client.fetch_some_data.return_value = 4  # Set controlled behaviour
    -result = app.do_something_fancy()
    -assert result == 2
    -print('All good, woop woop!')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    All good, woop woop!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    patch

    The use cases of patch are pretty similar to MacigMock. The biggest difference is that patch is used as a context manager or a decorator. Object to be patched is given as an argument for patch. In addition, you can provide additional object as a second argument (new) which will replace the original one. In case the new is omitted, MagicMock will be used by default.

    -

    Let's see how the example above would look like with patch.

    - -
    -
    -
    -
    -
    -
    In [5]:
    -
    -
    -
    # In the test module:
    -
    -from unittest.mock import patch
    -
    -# Inside a test case:
    -app = MyApplication()
    -with patch('__main__.app.client') as patched_client:  # Patch the client 
    -    patched_client.fetch_some_data.return_value = 4 # Set controlled behaviour
    -    result = app.do_something_fancy()
    -    assert result == 2
    -    print('All good, woop woop!')
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    All good, woop woop!
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    The same but with a function decorator instead of a context manager. Note that here we are patching the whole Client class, not just the client instance variable of app.

    - -
    -
    -
    -
    -
    -
    In [6]:
    -
    -
    -
    from unittest.mock import patch
    -
    -@patch('__main__.Client') # Patch the Client
    -def test_do_something_fancy(client_cls):
    -    client_cls().fetch_some_data.return_value = 4 # Set controlled behaviour
    -    app = MyApplication()
    -    result = app.do_something_fancy()
    -    assert result == 2
    -    print('All good, woop woop!')
    -    
    -    
    -test_do_something_fancy()  # This is just for the sake of example
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    All good, woop woop!
    -
    -
    -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -

    namedtuple

    A great helper for creating more readable and self documenting code.

    -

    namedtuple is a function that returns a tuple whose fields have names and also the tuple itself has a name (just like classes and their instance variables). Potential use cases include storing data which should be immutable. If you can use Python 3.7 or newer, you may want to take a look at dataclasses as well.

    - -
    -
    -
    -
    -
    -
    In [7]:
    -
    -
    -
    from collections import namedtuple
    -
    -Person = namedtuple('Person', ['name', 'age', 'is_gangster'])
    -
    -# instance creation is similar to classes
    -john = Person('John Doe', 83, True)
    -lisa = Person('Lis Doe', age=77, is_gangster=False)
    -
    -print(john, lisa)
    -print('Is John a gangster: {}'.format(john.is_gangster))
    -
    -# tuples are immutable, thus you can't do this
    -#john.is_gangster = False
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    Person(name='John Doe', age=83, is_gangster=True) Person(name='Lis Doe', age=77, is_gangster=False)
    -Is John a gangster: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    Counter

    For counting the occurences of elements in a collection.

    - -
    -
    -
    -
    -
    -
    In [8]:
    -
    -
    -
    from collections import Counter
    -
    -data = [1, 2, 3, 1, 2, 4, 5, 6, 2]
    -
    -counter = Counter(data)
    -print('type: {}, counter: {}'.format(type(counter), counter))
    -
    -print('count of twos: {}'.format(counter[2]))
    -print('count of tens: {}'.format(counter[10])) # zero for non existing
    -
    -print('counter is a dict: {}'.format(isinstance(counter, dict)))
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    type: <class 'collections.Counter'>, counter: Counter({2: 3, 1: 2, 3: 1, 4: 1, 5: 1, 6: 1})
    -count of twos: 3
    -count of tens: 0
    -counter is a dict: True
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    defaultdict

    For cleaner code for populating dictionaries.

    -

    Let's first see how you could use a normal dict.

    - -
    -
    -
    -
    -
    -
    In [9]:
    -
    -
    -
    data = (1, 2, 3, 4, 3, 2, 5, 6, 7)
    -
    -my_dict = {}
    -for val in data:
    -    if val % 2:
    -        if not 'odd' in my_dict:
    -            my_dict['odd'] = []
    -        my_dict['odd'].append(val)
    -    else:
    -        if not 'even' in my_dict:
    -            my_dict['even'] = []
    -        my_dict['even'].append(val)
    -        
    -print(my_dict)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    {'even': [2, 4, 2, 6], 'odd': [1, 3, 3, 5, 7]}
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    With defaultdict:

    - -
    -
    -
    -
    -
    -
    In [10]:
    -
    -
    -
    from collections import defaultdict
    -
    -my_dict = defaultdict(list)
    -for val in data:
    -    if val % 2:
    -        my_dict['odd'].append(val)
    -    else:
    -        my_dict['even'].append(val)
    -print(my_dict)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    defaultdict(<class 'list'>, {'even': [2, 4, 2, 6], 'odd': [1, 3, 3, 5, 7]})
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -

    In the above example, defaultdict makes sure that a fresh list is automatically initialized as a value when a new key is added.

    -

    Here's another example with int as a default.

    - -
    -
    -
    -
    -
    -
    In [11]:
    -
    -
    -
    my_dict = defaultdict(int)
    -for val in data:
    -    if val % 2:
    -        my_dict['odd_count'] += 1
    -    else:
    -        my_dict['even_count'] += 1
    -print(my_dict)
    -
    - -
    -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    defaultdict(<class 'int'>, {'even_count': 4, 'odd_count': 5})
    -
    -
    -
    - -
    -
    - -
    -
    -
    - - - - - - diff --git a/notebooks/intermediate/notebooks/best_practices.ipynb b/notebooks/intermediate/notebooks/01_best_practices.ipynb similarity index 100% rename from notebooks/intermediate/notebooks/best_practices.ipynb rename to notebooks/intermediate/notebooks/01_best_practices.ipynb diff --git a/notebooks/intermediate/notebooks/idiomatic_loops.ipynb b/notebooks/intermediate/notebooks/01_idiomatic_loops.ipynb similarity index 94% rename from notebooks/intermediate/notebooks/idiomatic_loops.ipynb rename to notebooks/intermediate/notebooks/01_idiomatic_loops.ipynb index bc52b64..4b3f446 100644 --- a/notebooks/intermediate/notebooks/idiomatic_loops.ipynb +++ b/notebooks/intermediate/notebooks/01_idiomatic_loops.ipynb @@ -20,7 +20,7 @@ "metadata": {}, "outputs": [], "source": [ - "data = ['John', 'Doe', 'was', 'here']" + "data = [\"John\", \"Doe\", \"was\", \"here\"]" ] }, { @@ -90,7 +90,7 @@ "outputs": [], "source": [ "for idx, val in enumerate(data):\n", - " print('{}: {}'.format(idx, val))" + " print(\"{}: {}\".format(idx, val))" ] }, { @@ -166,7 +166,7 @@ "metadata": {}, "outputs": [], "source": [ - "data = ['first', 'to', 'last', 'from'] " + "data = [\"first\", \"to\", \"last\", \"from\"]" ] }, { @@ -218,9 +218,9 @@ "metadata": {}, "outputs": [], "source": [ - "collection1 = ['a', 'b', 'c']\n", + "collection1 = [\"a\", \"b\", \"c\"]\n", "collection2 = (10, 20, 30, 40, 50)\n", - "collection3 = ['John', 'Doe', True]" + "collection3 = [\"John\", \"Doe\", True]" ] }, { @@ -241,11 +241,11 @@ " shortest = len(collection2)\n", "if len(collection3) < shortest:\n", " shortest = len(collection3)\n", - " \n", + "\n", "i = 0\n", "while i < shortest:\n", " print(collection1[i], collection2[i], collection3[i])\n", - " i += 1\n" + " i += 1" ] }, { @@ -314,7 +314,7 @@ "metadata": {}, "outputs": [], "source": [ - "data = [1, 2, 3, 'This', 'is', 'just', 'a', 'random', 'Python', 'list']" + "data = [1, 2, 3, \"This\", \"is\", \"just\", \"a\", \"random\", \"Python\", \"list\"]" ] }, { @@ -332,7 +332,7 @@ "source": [ "found = False\n", "for val in data:\n", - " if str(val).lower() == 'python':\n", + " if str(val).lower() == \"python\":\n", " found = True\n", " break\n", "if not found:\n", @@ -353,7 +353,7 @@ "outputs": [], "source": [ "for val in data:\n", - " if str(val).lower() == 'python':\n", + " if str(val).lower() == \"python\":\n", " break\n", "else:\n", " raise ValueError(\"Nope, couldn't find.\")" diff --git a/notebooks/intermediate/notebooks/pytest_fixtures.ipynb b/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb similarity index 82% rename from notebooks/intermediate/notebooks/pytest_fixtures.ipynb rename to notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb index 1182c37..09f5ca0 100644 --- a/notebooks/intermediate/notebooks/pytest_fixtures.ipynb +++ b/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb @@ -23,11 +23,16 @@ "# Let's make sure pytest and ipytest packages are installed\n", "# ipytest is required for running pytest inside Jupyter notebooks\n", "import sys\n", - "!{sys.executable} -m pip install pytest 'ipytest>=0.3.0'\n", "\n", - "import pytest\n", - "from ipytest import magics, clean_tests\n", - "__file__ = 'pytest_fixtures.ipynb'" + "!{sys.executable} -m pip install pytest\n", + "!{sys.executable} -m pip install ipytest\n", + "\n", + "# These are needed for running pytest inside Jupyter notebooks\n", + "import ipytest\n", + "\n", + "ipytest.autoconfig()\n", + "\n", + "import pytest" ] }, { @@ -44,7 +49,8 @@ "metadata": {}, "outputs": [], "source": [ - "PATHS = ['/foo/bar.txt', '/bar/baz.txt']\n", + "PATHS = [\"/foo/bar.txt\", \"/bar/baz.txt\"]\n", + "\n", "\n", "@pytest.fixture(params=PATHS)\n", "def executable(request):\n", @@ -57,7 +63,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean] '-s'\n", + "%%ipytest -s\n", "\n", "def test_something_with_executable(executable):\n", " print(executable)" @@ -79,11 +85,12 @@ "source": [ "@pytest.fixture\n", "def my_fixture():\n", - " print('\\nmy_fixture is used')\n", + " print(\"\\nmy_fixture is used\")\n", + "\n", "\n", "@pytest.fixture\n", "def other_fixture():\n", - " return 'FOO'" + " return \"FOO\"" ] }, { @@ -92,7 +99,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean] '-s'\n", + "%%ipytest -s\n", "\n", "@pytest.mark.usefixtures('my_fixture')\n", "class TestMyStuff:\n", @@ -104,16 +111,6 @@ " pass" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Needed to clean up test classes (Test*) in ipytest\n", - "clean_tests('Test*')" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -140,6 +137,7 @@ "source": [ "import os\n", "\n", + "\n", "def get_env_var_or_none(var_name):\n", " return os.environ.get(var_name, None)" ] @@ -150,7 +148,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean] '-s'\n", + "%%ipytest -s\n", "\n", "def test_get_env_var_or_none_with_valid_env_var(monkeypatch):\n", " monkeypatch.setenv('MY_ENV_VAR', 'secret')\n", @@ -176,11 +174,11 @@ "outputs": [], "source": [ "class SomeClass:\n", - " some_value = 'some value'\n", - " \n", + " some_value = \"some value\"\n", + "\n", " @staticmethod\n", " def tell_the_truth():\n", - " print('This is the original truth')" + " print(\"This is the original truth\")" ] }, { @@ -190,12 +188,13 @@ "outputs": [], "source": [ "def fake_truth():\n", - " print('This is modified truth')\n", + " print(\"This is modified truth\")\n", + "\n", "\n", "@pytest.fixture\n", - "def fake_some_class(monkeypatch): \n", - " monkeypatch.setattr('__main__.SomeClass.some_value', 'fake value')\n", - " monkeypatch.setattr('__main__.SomeClass.tell_the_truth', fake_truth)" + "def fake_some_class(monkeypatch):\n", + " monkeypatch.setattr(\"__main__.SomeClass.some_value\", \"fake value\")\n", + " monkeypatch.setattr(\"__main__.SomeClass.tell_the_truth\", fake_truth)" ] }, { @@ -204,7 +203,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean] '-s'\n", + "%%ipytest -s\n", "\n", "def test_some_class(fake_some_class):\n", " print(SomeClass.some_value)\n", @@ -226,7 +225,7 @@ "outputs": [], "source": [ "def word_count_of_txt_file(file_path):\n", - " with open(file_path, 'r') as f:\n", + " with open(file_path, \"r\") as f:\n", " content = f.read()\n", " return len(content.split())" ] @@ -237,7 +236,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean] '-s'\n", + "%%ipytest -s\n", "\n", "def test_word_count(tmpdir):\n", " test_file = tmpdir.join('test.txt')\n", @@ -260,17 +259,19 @@ "outputs": [], "source": [ "# scope is function also by default\n", - "@pytest.fixture(scope='function')\n", + "@pytest.fixture(scope=\"function\")\n", "def func_fixture():\n", - " print('\\nfunc')\n", - " \n", - "@pytest.fixture(scope='module')\n", + " print(\"\\nfunc\")\n", + "\n", + "\n", + "@pytest.fixture(scope=\"module\")\n", "def module_fixture():\n", - " print('\\nmodule')\n", - " \n", - "@pytest.fixture(scope='session')\n", + " print(\"\\nmodule\")\n", + "\n", + "\n", + "@pytest.fixture(scope=\"session\")\n", "def session_fixture():\n", - " print('\\nsession') " + " print(\"\\nsession\")" ] }, { @@ -279,7 +280,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean] '-s'\n", + "%%ipytest -s\n", "\n", "def test_something(func_fixture, module_fixture, session_fixture):\n", " pass\n", @@ -303,9 +304,9 @@ "source": [ "@pytest.fixture\n", "def some_fixture():\n", - " print('some_fixture is run now')\n", - " yield 'some magical value'\n", - " print('\\nthis will be run after test execution, you can do e.g. some clean up here')" + " print(\"some_fixture is run now\")\n", + " yield \"some magical value\"\n", + " print(\"\\nthis will be run after test execution, you can do e.g. some clean up here\")" ] }, { @@ -314,7 +315,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean] '-s'\n", + "%%ipytest -s\n", "\n", "def test_something(some_fixture):\n", " print('running test_something')\n", @@ -337,7 +338,7 @@ "source": [ "@pytest.fixture(autouse=True)\n", "def my_fixture():\n", - " print('\\nusing my_fixture')" + " print(\"\\nusing my_fixture\")" ] }, { @@ -346,7 +347,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean] '-s'\n", + "%%ipytest -s\n", "\n", "def test_1():\n", " pass\n", @@ -358,7 +359,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -372,7 +373,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.10.3" } }, "nbformat": 4, diff --git a/notebooks/intermediate/notebooks/std_lib2.ipynb b/notebooks/intermediate/notebooks/01_std_lib2.ipynb similarity index 79% rename from notebooks/intermediate/notebooks/std_lib2.ipynb rename to notebooks/intermediate/notebooks/01_std_lib2.ipynb index aac47c7..b567924 100644 --- a/notebooks/intermediate/notebooks/std_lib2.ipynb +++ b/notebooks/intermediate/notebooks/01_std_lib2.ipynb @@ -21,7 +21,7 @@ "metadata": {}, "outputs": [], "source": [ - "data = {'b': True, 'a': 1, 'nested': {'foo': 'bar'}, 'c': None, 'some_list': [1, 2, 3]}" + "data = {\"b\": True, \"a\": 1, \"nested\": {\"foo\": \"bar\"}, \"c\": None, \"some_list\": [1, 2, 3]}" ] }, { @@ -38,8 +38,9 @@ "outputs": [], "source": [ "import json\n", + "\n", "json_data = json.dumps(data)\n", - "print('type: {} data: {}'.format(type(json_data), json_data))" + "print(\"type: {} data: {}\".format(type(json_data), json_data))" ] }, { @@ -56,7 +57,7 @@ "outputs": [], "source": [ "decoded = json.loads(json_data)\n", - "print('type: {} data: {}'.format(type(decoded), decoded))" + "print(\"type: {} data: {}\".format(type(decoded), decoded))" ] }, { @@ -88,26 +89,31 @@ "source": [ "import random\n", "\n", + "\n", "class Client:\n", " def __init__(self, url, username, password):\n", " self.url = url\n", " self.creds = (username, password)\n", - " \n", + "\n", " def fetch_some_data(self):\n", - " print('Here we could for example fetch data from 3rd party API and return the data.')\n", - " print('Now we will just return some random number between 1-100.')\n", + " print(\n", + " \"Here we could for example fetch data from 3rd party API and return the data.\"\n", + " )\n", + " print(\"Now we will just return some random number between 1-100.\")\n", " return random.randint(1, 100)\n", "\n", "\n", "class MyApplication:\n", " def __init__(self):\n", - " self.client = Client(url='https://somewhere/api', username='John Doe', password='secret123?')\n", - " \n", + " self.client = Client(\n", + " url=\"https://somewhere/api\", username=\"John Doe\", password=\"secret123?\"\n", + " )\n", + "\n", " def do_something_fancy(self):\n", " data = self.client.fetch_some_data()\n", - " return data**(1/2) # let's return a square root just for example\n", - " \n", - " \n", + " return data ** (1 / 2) # let's return a square root just for example\n", + "\n", + "\n", "####################\n", "# In the test module:\n", "\n", @@ -115,11 +121,11 @@ "\n", "# Inside a test case:\n", "app = MyApplication()\n", - "app.client = MagicMock() # Mock the client\n", + "app.client = MagicMock() # Mock the client\n", "app.client.fetch_some_data.return_value = 4 # Set controlled behaviour\n", "result = app.do_something_fancy()\n", "assert result == 2\n", - "print('All good, woop woop!')" + "print(\"All good, woop woop!\")" ] }, { @@ -144,11 +150,11 @@ "\n", "# Inside a test case:\n", "app = MyApplication()\n", - "with patch('__main__.app.client') as patched_client: # Patch the client \n", - " patched_client.fetch_some_data.return_value = 4 # Set controlled behaviour\n", + "with patch(\"__main__.app.client\") as patched_client: # Patch the client\n", + " patched_client.fetch_some_data.return_value = 4 # Set controlled behaviour\n", " result = app.do_something_fancy()\n", " assert result == 2\n", - " print('All good, woop woop!')" + " print(\"All good, woop woop!\")" ] }, { @@ -166,15 +172,16 @@ "source": [ "from unittest.mock import patch\n", "\n", - "@patch('__main__.Client') # Patch the Client\n", + "\n", + "@patch(\"__main__.Client\") # Patch the Client\n", "def test_do_something_fancy(client_cls):\n", - " client_cls().fetch_some_data.return_value = 4 # Set controlled behaviour\n", + " client_cls().fetch_some_data.return_value = 4 # Set controlled behaviour\n", " app = MyApplication()\n", " result = app.do_something_fancy()\n", " assert result == 2\n", - " print('All good, woop woop!')\n", - " \n", - " \n", + " print(\"All good, woop woop!\")\n", + "\n", + "\n", "test_do_something_fancy() # This is just for the sake of example" ] }, @@ -203,17 +210,17 @@ "source": [ "from collections import namedtuple\n", "\n", - "Person = namedtuple('Person', ['name', 'age', 'is_gangster'])\n", + "Person = namedtuple(\"Person\", [\"name\", \"age\", \"is_gangster\"])\n", "\n", "# instance creation is similar to classes\n", - "john = Person('John Doe', 83, True)\n", - "lisa = Person('Lis Doe', age=77, is_gangster=False)\n", + "john = Person(\"John Doe\", 83, True)\n", + "lisa = Person(\"Lis Doe\", age=77, is_gangster=False)\n", "\n", "print(john, lisa)\n", - "print('Is John a gangster: {}'.format(john.is_gangster))\n", + "print(\"Is John a gangster: {}\".format(john.is_gangster))\n", "\n", "# tuples are immutable, thus you can't do this\n", - "#john.is_gangster = False" + "# john.is_gangster = False" ] }, { @@ -235,12 +242,12 @@ "data = [1, 2, 3, 1, 2, 4, 5, 6, 2]\n", "\n", "counter = Counter(data)\n", - "print('type: {}, counter: {}'.format(type(counter), counter))\n", + "print(\"type: {}, counter: {}\".format(type(counter), counter))\n", "\n", - "print('count of twos: {}'.format(counter[2]))\n", - "print('count of tens: {}'.format(counter[10])) # zero for non existing\n", + "print(\"count of twos: {}\".format(counter[2]))\n", + "print(\"count of tens: {}\".format(counter[10])) # zero for non existing\n", "\n", - "print('counter is a dict: {}'.format(isinstance(counter, dict)))" + "print(\"counter is a dict: {}\".format(isinstance(counter, dict)))" ] }, { @@ -264,14 +271,14 @@ "my_dict = {}\n", "for val in data:\n", " if val % 2:\n", - " if not 'odd' in my_dict:\n", - " my_dict['odd'] = []\n", - " my_dict['odd'].append(val)\n", + " if not \"odd\" in my_dict:\n", + " my_dict[\"odd\"] = []\n", + " my_dict[\"odd\"].append(val)\n", " else:\n", - " if not 'even' in my_dict:\n", - " my_dict['even'] = []\n", - " my_dict['even'].append(val)\n", - " \n", + " if not \"even\" in my_dict:\n", + " my_dict[\"even\"] = []\n", + " my_dict[\"even\"].append(val)\n", + "\n", "print(my_dict)" ] }, @@ -293,9 +300,9 @@ "my_dict = defaultdict(list)\n", "for val in data:\n", " if val % 2:\n", - " my_dict['odd'].append(val)\n", + " my_dict[\"odd\"].append(val)\n", " else:\n", - " my_dict['even'].append(val)\n", + " my_dict[\"even\"].append(val)\n", "print(my_dict)" ] }, @@ -317,9 +324,9 @@ "my_dict = defaultdict(int)\n", "for val in data:\n", " if val % 2:\n", - " my_dict['odd_count'] += 1\n", + " my_dict[\"odd_count\"] += 1\n", " else:\n", - " my_dict['even_count'] += 1\n", + " my_dict[\"even_count\"] += 1\n", "print(my_dict)" ] } diff --git a/notebooks/intermediate/notebooks/idiomatic_dicts.ipynb b/notebooks/intermediate/notebooks/02_idiomatic_dicts.ipynb similarity index 87% rename from notebooks/intermediate/notebooks/idiomatic_dicts.ipynb rename to notebooks/intermediate/notebooks/02_idiomatic_dicts.ipynb index e8470b1..0cccc10 100644 --- a/notebooks/intermediate/notebooks/idiomatic_dicts.ipynb +++ b/notebooks/intermediate/notebooks/02_idiomatic_dicts.ipynb @@ -21,7 +21,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'a': 1, 'b': 2, 'c': 3}" + "my_dict = {\"a\": 1, \"b\": 2, \"c\": 3}" ] }, { @@ -37,10 +37,10 @@ "metadata": {}, "outputs": [], "source": [ - "if 'g' in my_dict:\n", - " value = my_dict['g']\n", + "if \"g\" in my_dict:\n", + " value = my_dict[\"g\"]\n", "else:\n", - " value = 'some default value'\n", + " value = \"some default value\"\n", "print(value)" ] }, @@ -58,9 +58,9 @@ "outputs": [], "source": [ "try:\n", - " value = my_dict['g']\n", + " value = my_dict[\"g\"]\n", "except KeyError:\n", - " value = 'some default value'\n", + " value = \"some default value\"\n", "print(value)" ] }, @@ -77,7 +77,7 @@ "metadata": {}, "outputs": [], "source": [ - "value = my_dict.get('g', 'some default value')\n", + "value = my_dict.get(\"g\", \"some default value\")\n", "print(value)" ] }, @@ -94,7 +94,7 @@ "metadata": {}, "outputs": [], "source": [ - "value = my_dict.get('g')\n", + "value = my_dict.get(\"g\")\n", "print(value is None)" ] }, @@ -118,15 +118,15 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'a': 1, 'b': 2, 'c': 3}\n", + "my_dict = {\"a\": 1, \"b\": 2, \"c\": 3}\n", "\n", - "key = 'g'\n", + "key = \"g\"\n", "if key in my_dict:\n", " value = my_dict[key]\n", "else:\n", - " value = 'some default value'\n", + " value = \"some default value\"\n", " my_dict[key] = value\n", - " \n", + "\n", "print(value)\n", "print(my_dict)" ] @@ -144,10 +144,10 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'a': 1, 'b': 2, 'c': 3}\n", + "my_dict = {\"a\": 1, \"b\": 2, \"c\": 3}\n", "\n", - "key = 'g'\n", - "value = my_dict.setdefault(key, 'some default value')\n", + "key = \"g\"\n", + "value = my_dict.setdefault(key, \"some default value\")\n", "\n", "print(value)\n", "print(my_dict)" @@ -219,8 +219,8 @@ "metadata": {}, "outputs": [], "source": [ - "keys = ('a', 'b', 'c')\n", - "values = [True, 100, 'John Doe']" + "keys = (\"a\", \"b\", \"c\")\n", + "values = [True, 100, \"John Doe\"]" ] }, { @@ -277,7 +277,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_dict = {'age': 83, 'is gangster': True, 'name': 'John Doe'}" + "my_dict = {\"age\": 83, \"is gangster\": True, \"name\": \"John Doe\"}" ] }, { @@ -295,7 +295,7 @@ "source": [ "for key in my_dict:\n", " val = my_dict[key]\n", - " print('key: {:15s} value: {}'.format(key, val))" + " print(\"key: {:15s} value: {}\".format(key, val))" ] }, { @@ -312,7 +312,7 @@ "outputs": [], "source": [ "for key, val in my_dict.items():\n", - " print('key: {:15s} value: {}'.format(key, val))" + " print(\"key: {:15s} value: {}\".format(key, val))" ] } ], diff --git a/notebooks/intermediate/notebooks/idiomatic_misc1.ipynb b/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb similarity index 82% rename from notebooks/intermediate/notebooks/idiomatic_misc1.ipynb rename to notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb index 89531a0..8b9c642 100644 --- a/notebooks/intermediate/notebooks/idiomatic_misc1.ipynb +++ b/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb @@ -39,31 +39,31 @@ "# list\n", "square_roots_list = []\n", "for val in original_data:\n", - " square_root = val**(1/2) \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_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_root = val ** (1 / 2)\n", " square_roots_dict[val] = square_root\n", - "print(square_roots_dict) \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", + " 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) " + "print(integer_square_roots_dict)" ] }, { @@ -86,18 +86,17 @@ "metadata": {}, "outputs": [], "source": [ - "square_roots_list = [val**(1/2) for val in original_data]\n", + "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", + "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", + "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)\n", - " for val in original_data if (val**(1/2)).is_integer()\n", + " val: val ** (1 / 2) for val in original_data if (val ** (1 / 2)).is_integer()\n", "}\n", "print(integer_square_roots_dict)" ] @@ -115,7 +114,7 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'John Doe'" + "name = \"John Doe\"" ] }, { @@ -131,8 +130,8 @@ "metadata": {}, "outputs": [], "source": [ - "if name == 'John' or name == 'Doe' or name == 'John Doe':\n", - " print('This seems to be our guy')" + "if name == \"John\" or name == \"Doe\" or name == \"John Doe\":\n", + " print(\"This seems to be our guy\")" ] }, { @@ -148,8 +147,8 @@ "metadata": {}, "outputs": [], "source": [ - "if name in ('John', 'Doe', 'John Doe'):\n", - " print('This seems to be our guy')" + "if name in (\"John\", \"Doe\", \"John Doe\"):\n", + " print(\"This seems to be our guy\")" ] }, { @@ -182,7 +181,7 @@ "outputs": [], "source": [ "if b > a and c > b and d > c:\n", - " print('from lowest to highest: a, b, c, d')" + " print(\"from lowest to highest: a, b, c, d\")" ] }, { @@ -199,7 +198,7 @@ "outputs": [], "source": [ "if a < b < c < d:\n", - " print('from lowest to highest: a, b, c, d')" + " print(\"from lowest to highest: a, b, c, d\")" ] }, { @@ -223,11 +222,11 @@ "zero = 0\n", "false = False\n", "none = None\n", - "my_str = ''\n", + "my_str = \"\"\n", "\n", "# Basically the rest are truthy\n", "# for example:\n", - "my_second_list = ['foo']" + "my_second_list = [\"foo\"]" ] }, { @@ -244,19 +243,19 @@ "outputs": [], "source": [ "if len(my_list) == 0:\n", - " print('Empty list is so empty')\n", - " \n", + " print(\"Empty list is so empty\")\n", + "\n", "if not len(my_dict):\n", - " print('Empty dict is also very empty')\n", - " \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", + " 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", + " print(\"These are also falsy\")\n", + "\n", "if len(my_second_list) > 0:\n", - " print('This should be true')" + " print(\"This should be true\")" ] }, { @@ -273,19 +272,19 @@ "outputs": [], "source": [ "if not my_list:\n", - " print('Empty list is so empty')\n", - " \n", + " print(\"Empty list is so empty\")\n", + "\n", "if not my_dict:\n", - " print('Empty dict is also very empty')\n", - " \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", + " 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", + " print(\"These are also falsy\")\n", + "\n", "if my_second_list:\n", - " print('This should be true')" + " print(\"This should be true\")" ] }, { @@ -301,7 +300,7 @@ "metadata": {}, "outputs": [], "source": [ - "example_collection = ['a', True, 'Python is cool', 123, 0]" + "example_collection = [\"a\", True, \"Python is cool\", 123, 0]" ] }, { @@ -328,8 +327,8 @@ " if not val:\n", " all_values_truthy = False\n", " break\n", - " \n", - "print('any truthy: {}, all truthy: {}'.format(any_value_truthy, all_values_truthy))" + "\n", + "print(\"any truthy: {}, all truthy: {}\".format(any_value_truthy, all_values_truthy))" ] }, { @@ -347,7 +346,7 @@ "source": [ "any_value_truthy = any(example_collection)\n", "all_values_truthy = all(example_collection)\n", - "print('any truthy: {}, all truthy: {}'.format(any_value_truthy, all_values_truthy))" + "print(\"any truthy: {}, all truthy: {}\".format(any_value_truthy, all_values_truthy))" ] }, { @@ -377,9 +376,9 @@ "some_condition = True # just a dummy condition\n", "\n", "if some_condition:\n", - " variable = 'John'\n", + " variable = \"John\"\n", "else:\n", - " variable = 'Doe'\n", + " variable = \"Doe\"\n", "print(variable)" ] }, @@ -396,7 +395,7 @@ "metadata": {}, "outputs": [], "source": [ - "variable = 'John' if some_condition else 'Doe'\n", + "variable = \"John\" if some_condition else \"Doe\"\n", "print(variable)" ] }, @@ -415,8 +414,11 @@ "outputs": [], "source": [ "def show_person_details(name, is_gangster, is_hacker, age):\n", - " print('name: {}, gangster: {}, hacker: {}, age: {}'.format(\n", - " name, is_gangster, is_hacker, age))" + " print(\n", + " \"name: {}, gangster: {}, hacker: {}, age: {}\".format(\n", + " name, is_gangster, is_hacker, age\n", + " )\n", + " )" ] }, { @@ -432,7 +434,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_person_details('John Doe', True, False, 83)" + "show_person_details(\"John Doe\", True, False, 83)" ] }, { @@ -448,7 +450,7 @@ "metadata": {}, "outputs": [], "source": [ - "show_person_details('John Doe', is_gangster=True, is_hacker=False, age=83)" + "show_person_details(\"John Doe\", is_gangster=True, is_hacker=False, age=83)" ] }, { @@ -465,14 +467,15 @@ "metadata": {}, "outputs": [], "source": [ - "def func_with_loads_of_args(arg1, *, arg2=None, arg3=None, arg4=None, arg5='boom'):\n", + "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", + "# 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')" + "func_with_loads_of_args(\"John Doe\", arg4=\"foo\", arg5=\"bar\", arg2=\"foo bar\")" ] }, { diff --git a/notebooks/intermediate/notebooks/idiomatic_misc2.ipynb b/notebooks/intermediate/notebooks/04_idiomatic_misc2.ipynb similarity index 81% rename from notebooks/intermediate/notebooks/idiomatic_misc2.ipynb rename to notebooks/intermediate/notebooks/04_idiomatic_misc2.ipynb index 08a48d5..7500f1b 100644 --- a/notebooks/intermediate/notebooks/idiomatic_misc2.ipynb +++ b/notebooks/intermediate/notebooks/04_idiomatic_misc2.ipynb @@ -20,7 +20,7 @@ "metadata": {}, "outputs": [], "source": [ - "names = ('John', 'Lisa', 'Terminator', 'Python')" + "names = (\"John\", \"Lisa\", \"Terminator\", \"Python\")" ] }, { @@ -38,7 +38,7 @@ "source": [ "semicolon_separated = names[0]\n", "for name in names[1:]:\n", - " semicolon_separated += ';' + name\n", + " semicolon_separated += \";\" + name\n", "print(semicolon_separated)" ] }, @@ -55,7 +55,7 @@ "metadata": {}, "outputs": [], "source": [ - "semicolon_separated = ';'.join(names)\n", + "semicolon_separated = \";\".join(names)\n", "print(semicolon_separated)" ] }, @@ -79,7 +79,7 @@ "source": [ "a = 0\n", "b = None\n", - "c = 'John Doe'" + "c = \"John Doe\"" ] }, { @@ -95,7 +95,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_variable = 'default value'\n", + "my_variable = \"default value\"\n", "if a:\n", " my_variable = a\n", "elif b:\n", @@ -118,7 +118,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_variable = a or b or c or 'default value'\n", + "my_variable = a or b or c or \"default value\"\n", "print(my_variable)" ] }, @@ -145,18 +145,18 @@ "exception_occured = False\n", "try:\n", " # here would be the logic of your master piece\n", - " \n", + "\n", " bad_calculation = 1 / 0\n", - " \n", + "\n", "except ValueError as e:\n", - " print('Oh boi, some value error: {}'.format(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", + " print(\"Oh boi, something bad happened: {}\".format(e))\n", " exception_occured = True\n", - " \n", + "\n", "if not exception_occured:\n", - " print('All went well!')" + " print(\"All went well!\")" ] }, { @@ -174,15 +174,15 @@ "source": [ "try:\n", " # here would be the logic of your master piece\n", - " \n", + "\n", " bad_calculation = 1 / 0\n", - " \n", + "\n", "except ValueError as e:\n", - " print('Oh boi, some keyerror: {}'.format(e))\n", + " print(\"Oh boi, some keyerror: {}\".format(e))\n", "except Exception as e:\n", - " print('Oh boi, something bad happened: {}'.format(e))\n", + " print(\"Oh boi, something bad happened: {}\".format(e))\n", "else:\n", - " print('All went well!')" + " print(\"All went well!\")" ] }, { @@ -211,16 +211,17 @@ " # 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", + " 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", + " 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", + " print(\"This could be something important that should be done every time\")\n", " return result\n", "\n", - "print('return value: {}'.format(magical_calculation()))" + "\n", + "print(\"return value: {}\".format(magical_calculation()))" ] }, { @@ -245,10 +246,11 @@ " except Exception:\n", " return None\n", " finally:\n", - " print('This could be something important that should be done every time')\n", + " print(\"This could be something important that should be done every time\")\n", " return result\n", "\n", - "print('return value: {}'.format(magical_calculation()))" + "\n", + "print(\"return value: {}\".format(magical_calculation()))" ] }, { @@ -280,11 +282,11 @@ "outputs": [], "source": [ "try:\n", - " some_file = open('tmp.txt', 'w')\n", - " print('the file is now open: {}'.format(not some_file.closed))\n", - " \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", + "\n", "finally:\n", " some_file.close()\n", " print(\"now it's closed: {}\".format(some_file.closed))" @@ -303,9 +305,9 @@ "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", + "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))" @@ -326,19 +328,22 @@ "source": [ "from contextlib import contextmanager\n", "\n", + "\n", "@contextmanager\n", "def my_context():\n", - " print('Entering to my context')\n", + " print(\"Entering to my context\")\n", " yield\n", - " print('Exiting my context')\n", - " \n", + " print(\"Exiting my context\")\n", + "\n", + "\n", "def do_stuff():\n", " with my_context():\n", - " print('Doing stuff')\n", - " \n", - " print('Doing some stuff outside my context')\n", - " \n", - "do_stuff() " + " print(\"Doing stuff\")\n", + "\n", + " print(\"Doing some stuff outside my context\")\n", + "\n", + "\n", + "do_stuff()" ] }, { @@ -416,7 +421,7 @@ "source": [ "value = 0\n", "try:\n", - " value = 1 / 0 # just for demonstrating purposes \n", + " value = 1 / 0 # just for demonstrating purposes\n", "except ZeroDivisionError:\n", " pass\n", "\n", @@ -441,7 +446,7 @@ "value = 0\n", "with suppress(ZeroDivisionError):\n", " value = 1 / 0 # just for demonstrating purposes\n", - " \n", + "\n", "print(value)" ] }, @@ -469,21 +474,21 @@ " def __init__(self, first_name, last_name):\n", " self.first_name = first_name\n", " self.last_name = last_name\n", - " \n", + "\n", " def get_full_name(self):\n", - " return '{} {}'.format(self.first_name, self.last_name)\n", - " \n", + " return \"{} {}\".format(self.first_name, self.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", - " \n", - "p = Person('John', 'Doe')\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.get_full_name())\n", - "p.set_full_name('Lisa Doe')\n", + "p.set_full_name(\"Lisa Doe\")\n", "print(p.get_full_name())" ] }, @@ -504,23 +509,23 @@ " def __init__(self, first_name, last_name):\n", " self.first_name = first_name\n", " self.last_name = last_name\n", - " \n", + "\n", " @property\n", " def full_name(self):\n", - " return '{} {}'.format(self.first_name, self.last_name)\n", - " \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", + " raise ValueError(\"Sorry, too difficult name\")\n", + "\n", " self.first_name, self.last_name = parts\n", "\n", - " \n", - "p = Person('John', 'Doe')\n", + "\n", + "p = Person(\"John\", \"Doe\")\n", "print(p.full_name)\n", - "p.full_name = 'Lisa Doe'\n", + "p.full_name = \"Lisa Doe\"\n", "print(p.full_name)" ] } From 0d6f95ab5cebde0b58640550395561dead1be28a Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Wed, 19 Apr 2023 10:23:22 +0300 Subject: [PATCH 39/60] Update links and remove old stuff --- README.md | 71 +++++++++++++++---------------------------------------- 1 file changed, 19 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 1c9b174..8c8ecd3 100644 --- a/README.md +++ b/README.md @@ -27,25 +27,25 @@ See [contributing](https://github.com/jerry-git/learn-python3/blob/master/CONTRI ## Beginner -1. [Strings](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/strings.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/strings.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/strings_exercise.ipynb) -1. [Numbers](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/numbers.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/numbers.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/numbers_exercise.ipynb) -1. [Conditionals](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/conditionals.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/conditionals.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/conditionals_exercise.ipynb) -1. [Lists](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/lists.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/lists.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/lists_exercise.ipynb) -1. [Dictionaries](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/dictionaries.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/dictionaries.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/dictionaries_exercise.ipynb) -1. [For loops](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/for_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/for_loops.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/for_loops_exercise.ipynb) -1. [Functions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/functions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/functions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/functions_exercise.ipynb) -1. [Testing with pytest - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/testing1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/testing1.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing1_exercise.ipynb) -1. Recap exercise 1 [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/recap1_exercise.ipynb) -1. [File I\O](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/file_io.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/file_io.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/file_io_exercise.ipynb) -1. [Classes](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/classes.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/classes.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/classes_exercise.ipynb) -1. [Exceptions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/exceptions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/exceptions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/exceptions_exercise.ipynb) -1. [Modules and packages](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/modules_and_packages.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/modules_and_packages.ipynb) -1. [Debugging](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/debugging.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/debugging.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/debugging_exercise.ipynb) -1. [Goodies of the Standard Library - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/std_lib.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/std_lib.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/std_lib1_exercise.ipynb) -1. [Testing with pytest - part 2](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/testing2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/testing2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/testing2_exercise.ipynb) -1. [Virtual environment](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/venv.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/venv.ipynb) -1. [Project structure](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/project_structure.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/project_structure.ipynb) -1. Recap exercise 2 [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/recap2_exercise.ipynb) +1. [Strings](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/01_strings.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/01_strings.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/01_strings_exercise.ipynb) +2. [Numbers](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/02_numbers.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/02_numbers.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/02_numbers_exercise.ipynb) +3. [Conditionals](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/03_conditionals.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/03_conditionals.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/03_conditionals_exercise.ipynb) +4. [Lists](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/04_lists.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/04_lists.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/04_lists_exercise.ipynb) +5. [Dictionaries](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/05_dictionaries.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/05_dictionaries.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/05_dictionaries_exercise.ipynb) +6. [For loops](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/06_for_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/06_for_loops.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/06_for_loops_exercise.ipynb) +7. [Functions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/07_functions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/07_functions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/07_functions_exercise.ipynb) +8. [Testing with pytest - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/08_testing1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/08_testing1.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/08_testing1_exercise.ipynb) +9. Recap exercise 1 [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/09_recap1_exercise.ipynb) +10. [File I\O](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/10_file_io.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/10_file_io.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/10_file_io_exercise.ipynb) +11. [Classes](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/11_classes.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/11_classes.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/11_classes_exercise.ipynb) +12. [Exceptions](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/12_exceptions.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/12_exceptions.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/12_exceptions_exercise.ipynb) +13. [Modules and packages](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/13_modules_and_packages.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/13_modules_and_packages.ipynb) +14. [Debugging](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/14_debugging.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/14_debugging.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/14_debugging_exercise.ipynb) +15. [Goodies of the Standard Library - part 1](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/15_std_lib.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/15_std_lib.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/15_std_lib1_exercise.ipynb) +16. [Testing with pytest - part 2](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/16_testing2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/16_testing2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/16_testing2_exercise.ipynb) +17. [Virtual environment](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/17_venv.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/17_venv.ipynb) +18. [Project structure](https://jerry-git.github.io/learn-python3/notebooks/beginner/html/18_project_structure.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/notebooks/18_project_structure.ipynb) +19. Recap exercise 2 [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/beginner/exercises/19_recap2_exercise.ipynb) ## Intermediate @@ -61,7 +61,6 @@ Python is a powerful language which contains many features not presented in most #### Step up your `pytest` game 1. [Efficient use of fixtures](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/pytest_fixtures.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/pytest_fixtures.ipynb) -1. Other tips and tricks #### Best practices A list of best development practices for Python projects. Most of the practices listed here are also applicable for other languages, however the presented tooling focuses mainly on Python. @@ -70,38 +69,6 @@ A list of best development practices for Python projects. Most of the practices #### General topics 1. [Goodies of the Standard Library - part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/std_lib2_exercise.ipynb) -#### Backlog -* Sets -* Generators -* Decorators -* Context managers -* Playing with attributes -* *, *args, **kwargs -* Command line arguments with click -* OOP - inheritance -* OOP - Abstract Base Classes -* OOP - attrs -* Testing with mocks -* Structuring your tests - - -## Use cases - -#### Playing with the web -* requests -* testing requests with responses -* beautifulsoup4 -* selenium - -#### Communicating with databases -* SQLAlchemy - -#### Working with documents -* excel - * openpyxl -* pdf - * pdfrw / PyPDF2 - ## Credits * Logo: Abdur-Rahmaan Janhangeer, [@Abdur-rahmaanJ](https://github.com/Abdur-rahmaanJ) From 45d6173f1469e99ca9b403c4f94efcc8e41925d0 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Wed, 19 Apr 2023 10:27:48 +0300 Subject: [PATCH 40/60] Update contribution guidelines --- CONTRIBUTING.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 108f2a3..d93926c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,15 +5,23 @@ If you spot a typo or the content does not make sense in some way, feel free to I am open for enhancement ideas and feature requests. If there's some topic you'd like to see a notebook about, feel free to open an issue and request it there. ## Development +Install development dependencies +``` +pip install -r dev-requirements.txt +``` -#### post_save_hook -* Copy the content of utils/post_save_hook.py to your jupyter_notebook_config.py before making changes to notebooks -* This will setup a post_save_hook which will generate a html version of the notebook automatically when the notebook is saved -* htmls are not generated for exercises +#### Generating html +``` +python scripts/notebook_to_html.py +``` #### Testing -* Travis CI will make sure that the code cells in the notebooks can be executed -* You test the same locally by: - * install tox by: `pip install tox` - * run tox: `tox` -* Tests are not run for exercises (because the code in the exercise cells is usually intentionally incomplete) \ No newline at end of file +``` +pytest --nbval notebooks +``` + +#### pre-commit +``` +pre-commit install +``` +and it'll automatically run all the pre-commit hooks for each commit. From 33150e098d4c401c53f9b927d7a858f5e170af73 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Wed, 19 Apr 2023 10:33:55 +0300 Subject: [PATCH 41/60] Add CI workflow --- .github/workflows/ci.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a2afda0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,23 @@ +name: CI + +on: + pull_request: + push: + branches: + - "**" + +jobs: + checks: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: [ "3.10", "3.11" ] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - run: pip install -r dev-requirements.txt + - run: pre-commit run -a + - run: pytest --nbval notebooks From 5befce8e92c0c0dc0353b18af3bd48d712a562f4 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Thu, 20 Apr 2023 10:13:38 +0300 Subject: [PATCH 42/60] Workaround to get ipytest play nicely with 3.11 See https://github.com/chmp/ipytest/issues/93 --- .../beginner/notebooks/08_testing1.ipynb | 7 +------ .../beginner/notebooks/16_testing2.ipynb | 16 +++------------ .../notebooks/01_pytest_fixtures.ipynb | 20 +++++++------------ 3 files changed, 11 insertions(+), 32 deletions(-) diff --git a/notebooks/beginner/notebooks/08_testing1.ipynb b/notebooks/beginner/notebooks/08_testing1.ipynb index 562ab40..0e921ad 100644 --- a/notebooks/beginner/notebooks/08_testing1.ipynb +++ b/notebooks/beginner/notebooks/08_testing1.ipynb @@ -78,7 +78,6 @@ "metadata": {}, "outputs": [], "source": [ - "# This would be in your e.g. implementation.py\n", "def sum_of_three_numbers(num1, num2, num3):\n", " return num1 + num2 + num3" ] @@ -102,11 +101,7 @@ "outputs": [], "source": [ "%%ipytest\n", - "# Mention this at the top of cells which contain test(s)\n", - "# This is only required for running pytest in Jupyter notebooks\n", "\n", - "\n", - "# This would be in your test_implementation.py\n", "def test_sum_of_three_numbers():\n", " # 1. Setup the variables used in the test\n", " num1 = 2\n", @@ -144,7 +139,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.3" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/16_testing2.ipynb b/notebooks/beginner/notebooks/16_testing2.ipynb index d0e72e2..06b013f 100644 --- a/notebooks/beginner/notebooks/16_testing2.ipynb +++ b/notebooks/beginner/notebooks/16_testing2.ipynb @@ -40,7 +40,6 @@ "metadata": {}, "outputs": [], "source": [ - "# This would be e.g. in person.py\n", "class Person:\n", " def __init__(self, first_name, last_name, age):\n", " self.first_name = first_name\n", @@ -74,7 +73,6 @@ "metadata": {}, "outputs": [], "source": [ - "# This would be in either conftest.py or test_person.py\n", "import pytest\n", "\n", "\n", @@ -99,7 +97,7 @@ "source": [ "%%ipytest\n", "\n", - "# These would be in test_person.py\n", + "\n", "def test_full_name(default_person): # Note: we use fixture as an argument of the test case\n", " result = default_person.full_name\n", " assert result == 'John Doe'\n", @@ -147,7 +145,6 @@ "metadata": {}, "outputs": [], "source": [ - "# This would be e.g. in string_manipulate.py\n", "def replace_names(original_str, new_name):\n", " \"\"\"Replaces names (uppercase words) of original_str by new_name\"\"\"\n", " words = original_str.split()\n", @@ -170,7 +167,7 @@ "source": [ "%%ipytest\n", "\n", - "# This would be in your test module\n", + "\n", "@pytest.mark.parametrize(\"original,new_name,expected\", [\n", " ('this is Lisa', 'John Doe', 'this is John Doe'),\n", " ('how about Frank and Amy', 'John', 'how about John and John'),\n", @@ -180,13 +177,6 @@ " result = replace_names(original, new_name)\n", " assert result == expected" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -205,7 +195,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.3" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb b/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb index 09f5ca0..fcc27e6 100644 --- a/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb +++ b/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb @@ -83,23 +83,18 @@ "metadata": {}, "outputs": [], "source": [ + "%%ipytest -s\n", + "\n", + "\n", "@pytest.fixture\n", "def my_fixture():\n", " print(\"\\nmy_fixture is used\")\n", - "\n", + " \n", "\n", "@pytest.fixture\n", "def other_fixture():\n", - " return \"FOO\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%%ipytest -s\n", + " return \"FOO\"\n", + "\n", "\n", "@pytest.mark.usefixtures('my_fixture')\n", "class TestMyStuff:\n", @@ -258,7 +253,6 @@ "metadata": {}, "outputs": [], "source": [ - "# scope is function also by default\n", "@pytest.fixture(scope=\"function\")\n", "def func_fixture():\n", " print(\"\\nfunc\")\n", @@ -373,7 +367,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.3" + "version": "3.11.0" } }, "nbformat": 4, From 407dc6d28c99fb44c66897b4353de99b7da20849 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Thu, 20 Apr 2023 10:20:55 +0300 Subject: [PATCH 43/60] Update ipytest things --- .../exercises/08_testing1_exercise.ipynb | 15 ++++++++------- .../exercises/16_testing2_exercise.ipynb | 16 +++++++++------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/notebooks/beginner/exercises/08_testing1_exercise.ipynb b/notebooks/beginner/exercises/08_testing1_exercise.ipynb index ea7219c..98512b2 100644 --- a/notebooks/beginner/exercises/08_testing1_exercise.ipynb +++ b/notebooks/beginner/exercises/08_testing1_exercise.ipynb @@ -6,16 +6,17 @@ "metadata": {}, "outputs": [], "source": [ - "# Required boilerplate\n", + "# Let's make sure pytest and ipytest packages are installed\n", + "# ipytest is required for running pytest inside Jupyter notebooks\n", "import sys\n", "\n", "!{sys.executable} -m pip install pytest\n", "!{sys.executable} -m pip install ipytest\n", "\n", - "import ipytest.magics\n", - "import pytest\n", + "# These are needed for running pytest inside Jupyter notebooks\n", + "import ipytest\n", "\n", - "__file__ = \"testing1_exercise.ipynb\"" + "ipytest.autoconfig()" ] }, { @@ -50,7 +51,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean]\n", + "%%ipytest\n", "\n", "def test_get_divisible_by_five():\n", " # Your implementation here\n" @@ -59,7 +60,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -73,7 +74,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/exercises/16_testing2_exercise.ipynb b/notebooks/beginner/exercises/16_testing2_exercise.ipynb index d3862db..a7a2b3b 100644 --- a/notebooks/beginner/exercises/16_testing2_exercise.ipynb +++ b/notebooks/beginner/exercises/16_testing2_exercise.ipynb @@ -6,16 +6,18 @@ "metadata": {}, "outputs": [], "source": [ - "# Required boilerplate\n", + "# Let's make sure pytest and ipytest packages are installed\n", + "# ipytest is required for running pytest inside Jupyter notebooks\n", "import sys\n", "\n", "!{sys.executable} -m pip install pytest\n", "!{sys.executable} -m pip install ipytest\n", "\n", - "import ipytest.magics\n", + "# These are needed for running pytest inside Jupyter notebooks\n", + "import ipytest\n", "import pytest\n", "\n", - "__file__ = \"testing2_exercise.ipynb\"" + "ipytest.autoconfig()" ] }, { @@ -83,7 +85,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean]\n", + "%%ipytest\n", "\n", "\n", "@pytest.____\n", @@ -171,7 +173,7 @@ "metadata": {}, "outputs": [], "source": [ - "%%run_pytest[clean]\n", + "%%ipytest\n", "\n", "# Your implementation here\n" ] @@ -179,7 +181,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -193,7 +195,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, From 252d70bdaee4239b4857e636961a8ce2f77b6354 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Fri, 21 Apr 2023 13:41:52 +0300 Subject: [PATCH 44/60] Add nbqa to dev deps --- dev-requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-requirements.txt b/dev-requirements.txt index e3f4c05..9e30ba2 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,5 +1,6 @@ black[jupyter] jupyter +nbqa[toolchain] nbval pre-commit pytest From 5a0793db03bd80e894aa9ac19fadb6c1ae00e546 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Fri, 21 Apr 2023 13:42:01 +0300 Subject: [PATCH 45/60] Add hook for pyupgrade --- .pre-commit-config.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a2296f5..7c09ca9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,3 +11,8 @@ repos: entry: black language: system files: \.(py|ipynb)$ + - id: pyupgrade + name: pyupgrade + entry: nbqa pyupgrade --py310-plus + language: system + files: \.(py|ipynb)$ From 52ca70b866df59b1aa21c50784b828cfbc069cd5 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Fri, 21 Apr 2023 13:45:36 +0300 Subject: [PATCH 46/60] Pyupgrade 3.10+ --- .../exercises/01_strings_exercise.ipynb | 4 +- .../exercises/03_conditionals_exercise.ipynb | 10 +-- .../exercises/16_testing2_exercise.ipynb | 4 +- notebooks/beginner/notebooks/01_strings.ipynb | 33 +++++---- notebooks/beginner/notebooks/02_numbers.ipynb | 10 +-- .../beginner/notebooks/03_conditionals.ipynb | 67 ++++++------------- notebooks/beginner/notebooks/04_lists.ipynb | 32 ++++----- .../beginner/notebooks/05_dictionaries.ipynb | 46 ++++++------- .../beginner/notebooks/06_for_loops.ipynb | 4 +- .../beginner/notebooks/07_functions.ipynb | 8 +-- notebooks/beginner/notebooks/10_file_io.ipynb | 16 ++--- notebooks/beginner/notebooks/11_classes.ipynb | 20 +++--- .../beginner/notebooks/12_exceptions.ipynb | 14 ++-- .../beginner/notebooks/14_debugging.ipynb | 6 +- notebooks/beginner/notebooks/15_std_lib.ipynb | 36 +++++----- .../beginner/notebooks/16_testing2.ipynb | 2 +- .../exercises/01_std_lib2_exercise.ipynb | 2 +- .../05_idiomatic_python_exercise.ipynb | 2 +- .../notebooks/01_idiomatic_loops.ipynb | 2 +- .../notebooks/01_pytest_fixtures.ipynb | 2 +- .../intermediate/notebooks/01_std_lib2.ipynb | 14 ++-- .../notebooks/02_idiomatic_dicts.ipynb | 4 +- .../notebooks/03_idiomatic_misc1.ipynb | 4 +- .../notebooks/04_idiomatic_misc2.ipynb | 24 +++---- 24 files changed, 167 insertions(+), 199 deletions(-) diff --git a/notebooks/beginner/exercises/01_strings_exercise.ipynb b/notebooks/beginner/exercises/01_strings_exercise.ipynb index 66a97be..cf94527 100644 --- a/notebooks/beginner/exercises/01_strings_exercise.ipynb +++ b/notebooks/beginner/exercises/01_strings_exercise.ipynb @@ -84,7 +84,7 @@ }, "outputs": [], "source": [ - "print(\"pretty: {}\".format(pretty))\n", + "print(f\"pretty: {pretty}\")\n", "assert pretty == \"Title Of My New Book\"" ] }, @@ -127,7 +127,7 @@ }, "outputs": [], "source": [ - "print(\"sentence: {}\".format(sentence))\n", + "print(f\"sentence: {sentence}\")\n", "assert sentence == \"Learning Python is fun!\"" ] } diff --git a/notebooks/beginner/exercises/03_conditionals_exercise.ipynb b/notebooks/beginner/exercises/03_conditionals_exercise.ipynb index 061c2c1..9052e70 100644 --- a/notebooks/beginner/exercises/03_conditionals_exercise.ipynb +++ b/notebooks/beginner/exercises/03_conditionals_exercise.ipynb @@ -26,19 +26,19 @@ "outputs": [], "source": [ "if ____:\n", - " print('Name \"{}\" is more than 20 chars long'.format(name))\n", + " print(f'Name \"{name}\" is more than 20 chars long')\n", " length_description = \"long\"\n", "elif ____:\n", - " print('Name \"{}\" is more than 15 chars long'.format(name))\n", + " print(f'Name \"{name}\" is more than 15 chars long')\n", " length_description = \"semi long\"\n", "elif ____:\n", - " print('Name \"{}\" is more than 10 chars long'.format(name))\n", + " print(f'Name \"{name}\" is more than 10 chars long')\n", " length_description = \"semi long\"\n", "elif ____:\n", - " print('Name \"{}\" is 8, 9 or 10 chars long'.format(name))\n", + " print(f'Name \"{name}\" is 8, 9 or 10 chars long')\n", " length_description = \"semi short\"\n", "else:\n", - " print('Name \"{}\" is a short name'.format(name))\n", + " print(f'Name \"{name}\" is a short name')\n", " length_description = \"short\"" ] }, diff --git a/notebooks/beginner/exercises/16_testing2_exercise.ipynb b/notebooks/beginner/exercises/16_testing2_exercise.ipynb index a7a2b3b..c1e426f 100644 --- a/notebooks/beginner/exercises/16_testing2_exercise.ipynb +++ b/notebooks/beginner/exercises/16_testing2_exercise.ipynb @@ -60,14 +60,14 @@ "\n", " def complete(self, number):\n", " if number not in self._todo:\n", - " raise TodoNotFound(\"{} not in todos\".format(number))\n", + " raise TodoNotFound(f\"{number} not in todos\")\n", "\n", " task = self._todo.pop(number)\n", " self._done[number] = task\n", "\n", " def remove(self, number):\n", " if number not in self._todo:\n", - " raise TodoNotFound(\"{} not in todos\".format(number))\n", + " raise TodoNotFound(f\"{number} not in todos\")\n", "\n", " del self._todo[number]" ] diff --git a/notebooks/beginner/notebooks/01_strings.ipynb b/notebooks/beginner/notebooks/01_strings.ipynb index fdbb05a..d2841f8 100644 --- a/notebooks/beginner/notebooks/01_strings.ipynb +++ b/notebooks/beginner/notebooks/01_strings.ipynb @@ -126,7 +126,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## `str.format()`" + "## f-strings" ] }, { @@ -135,8 +135,11 @@ "metadata": {}, "outputs": [], "source": [ - "secret = \"{} is cool\".format(\"Python\")\n", - "print(secret)" + "first_name = \"John\"\n", + "last_name = \"Doe\"\n", + "age = 88\n", + "print(f\"My name is {first_name} {last_name}, you can call me {first_name}.\")\n", + "print(f\"I'm {age} years old.\")" ] }, { @@ -145,13 +148,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"My name is {} {}, you can call me {}.\".format(\"John\", \"Doe\", \"John\"))\n", - "# is the same as:\n", - "print(\n", - " \"My name is {first} {family}, you can call me {first}.\".format(\n", - " first=\"John\", family=\"Doe\"\n", - " )\n", - ")" + "print(f\"Use '=' to also print the variable name like this: {age=}\")" ] }, { @@ -179,14 +176,14 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"Some cool python libraries: {}\".format(cool_python_libs))" + "print(f\"Some cool python libraries: {cool_python_libs}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Alternatives (not as [Pythonic](http://docs.python-guide.org/en/latest/writing/style/#idioms) and [slower](https://waymoot.org/home/python_string/)):" + "Alternative (not as [Pythonic](http://docs.python-guide.org/en/latest/writing/style/#idioms) and [slower](https://waymoot.org/home/python_string/)):" ] }, { @@ -196,12 +193,12 @@ "outputs": [], "source": [ "cool_python_libs = pandas + \", \" + numpy + \", \" + requests\n", - "print(\"Some cool python libraries: {}\".format(cool_python_libs))\n", + "print(f\"Some cool python libraries: {cool_python_libs}\")\n", "\n", "cool_python_libs = pandas\n", "cool_python_libs += \", \" + numpy\n", "cool_python_libs += \", \" + requests\n", - "print(\"Some cool python libraries: {}\".format(cool_python_libs))" + "print(f\"Some cool python libraries: {cool_python_libs}\")" ] }, { @@ -263,8 +260,8 @@ "ugly_formatted = \" \\n \\t Some story to tell \"\n", "stripped = ugly_formatted.strip()\n", "\n", - "print(\"ugly: {}\".format(ugly_formatted))\n", - "print(\"stripped: {}\".format(ugly_formatted.strip()))" + "print(f\"ugly: {ugly_formatted}\")\n", + "print(f\"stripped: {stripped}\")" ] }, { @@ -370,7 +367,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -384,7 +381,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/02_numbers.ipynb b/notebooks/beginner/notebooks/02_numbers.ipynb index 45af1a7..4fd6678 100644 --- a/notebooks/beginner/notebooks/02_numbers.ipynb +++ b/notebooks/beginner/notebooks/02_numbers.ipynb @@ -21,7 +21,7 @@ "outputs": [], "source": [ "my_int = 6\n", - "print(\"value: {}, type: {}\".format(my_int, type(my_int)))" + "print(f\"value: {my_int}, type: {type(my_int)}\")" ] }, { @@ -38,7 +38,7 @@ "outputs": [], "source": [ "my_float = float(my_int)\n", - "print(\"value: {}, type: {}\".format(my_float, type(my_float)))" + "print(f\"value: {my_float}, type: {type(my_float)}\")" ] }, { @@ -135,7 +135,7 @@ "source": [ "from_float = Decimal(0.1)\n", "from_str = Decimal(\"0.1\")\n", - "print(\"from float: {}\\nfrom string: {}\".format(from_float, from_str))" + "print(f\"from float: {from_float}\\nfrom string: {from_str}\")" ] }, { @@ -170,7 +170,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -184,7 +184,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/03_conditionals.ipynb b/notebooks/beginner/notebooks/03_conditionals.ipynb index 9600954..4958b96 100644 --- a/notebooks/beginner/notebooks/03_conditionals.ipynb +++ b/notebooks/beginner/notebooks/03_conditionals.ipynb @@ -1,30 +1,5 @@ { "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from IPython.display import HTML\n", - "\n", - "HTML(\n", - " \"\"\"\n", - "
    \"\"\"\n", - ")" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -52,7 +27,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"type of True and False: {}\".format(type(True)))" + "print(f\"type of True and False: {type(True)}\")" ] }, { @@ -61,9 +36,9 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"0: {}, 1: {}\".format(bool(0), bool(1)))\n", - "print(\"empty list: {}, list with values: {}\".format(bool([]), bool([\"woop\"])))\n", - "print(\"empty dict: {}, dict with values: {}\".format(bool({}), bool({\"Python\": \"cool\"})))" + "print(f\"0: {bool(0)}, 1: {bool(1)}\")\n", + "print(f\"empty list: {bool([])}, list with values: {bool(['woop'])}\")\n", + "print(f\"empty dict: {bool({})}, dict with values: {bool({'Python': 'cool'})}\")" ] }, { @@ -79,16 +54,16 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"1 == 0: {}\".format(1 == 0))\n", - "print(\"1 != 0: {}\".format(1 != 0))\n", - "print(\"1 > 0: {}\".format(1 > 0))\n", - "print(\"1 > 1: {}\".format(1 > 1))\n", - "print(\"1 < 0: {}\".format(1 < 0))\n", - "print(\"1 < 1: {}\".format(1 < 1))\n", - "print(\"1 >= 0: {}\".format(1 >= 0))\n", - "print(\"1 >= 1: {}\".format(1 >= 1))\n", - "print(\"1 <= 0: {}\".format(1 <= 0))\n", - "print(\"1 <= 1: {}\".format(1 <= 1))" + "print(f\"{1 == 0}\")\n", + "print(f\"{1 != 0}\")\n", + "print(f\"{1 > 0}\")\n", + "print(f\"{1 > 1}\")\n", + "print(f\"{1 < 0}\")\n", + "print(f\"{1 < 1}\")\n", + "print(f\"{1 >= 0}\")\n", + "print(f\"{1 >= 1}\")\n", + "print(f\"{1 <= 0}\")\n", + "print(f\"{1 <= 1}\")" ] }, { @@ -104,7 +79,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"1 <= 2 <= 3: {}\".format(1 <= 2 <= 3))" + "print(f\"{1 <= 2 <= 3}\")" ] }, { @@ -132,8 +107,8 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"Python and java are both cool: {}\".format(python_is_cool and java_is_cool))\n", - "print(\"secret_value and python_is_cool: {}\".format(secret_value and python_is_cool))" + "print(f\"Python and java are both cool: {python_is_cool and java_is_cool}\")\n", + "print(f\"secret_value and python_is_cool: {secret_value and python_is_cool}\")" ] }, { @@ -142,8 +117,8 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"Python or java is cool: {}\".format(python_is_cool or java_is_cool))\n", - "print('1 >= 1.1 or 2 < float(\"1.4\"): {}'.format(1 >= 1.1 or 2 < float(\"1.4\")))" + "print(f\"Python or java is cool: {python_is_cool or java_is_cool}\")\n", + "print(f\"{1 >= 1.1 or 2 < 1.4}\")" ] }, { @@ -152,7 +127,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"Java is not cool: {}\".format(not java_is_cool))" + "print(f\"Java is not cool: {not java_is_cool}\")" ] }, { @@ -310,7 +285,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.3" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/04_lists.ipynb b/notebooks/beginner/notebooks/04_lists.ipynb index 2820efd..6949ef2 100644 --- a/notebooks/beginner/notebooks/04_lists.ipynb +++ b/notebooks/beginner/notebooks/04_lists.ipynb @@ -14,7 +14,7 @@ "outputs": [], "source": [ "my_empty_list = []\n", - "print(\"empty list: {}, type: {}\".format(my_empty_list, type(my_empty_list)))" + "print(f\"empty list: {my_empty_list}, type: {type(my_empty_list)}\")" ] }, { @@ -25,7 +25,7 @@ "source": [ "list_of_ints = [1, 2, 6, 7]\n", "list_of_misc = [0.2, 5, \"Python\", \"is\", \"still fun\", \"!\"]\n", - "print(\"lengths: {} and {}\".format(len(list_of_ints), len(list_of_misc)))" + "print(f\"lengths: {len(list_of_ints)} and {len(list_of_misc)}\")" ] }, { @@ -53,8 +53,8 @@ "outputs": [], "source": [ "coordinates = [[12.0, 13.3], [0.6, 18.0], [88.0, 1.1]] # two dimensional\n", - "print(\"first coordinate: {}\".format(coordinates[0]))\n", - "print(\"second element of first coordinate: {}\".format(coordinates[0][1]))" + "print(f\"first coordinate: {coordinates[0]}\")\n", + "print(f\"second element of first coordinate: {coordinates[0][1]}\")" ] }, { @@ -123,7 +123,7 @@ "original = [1, 2, 3]\n", "modified = original\n", "modified[0] = 99\n", - "print(\"original: {}, modified: {}\".format(original, modified))" + "print(f\"original: {original}, modified: {modified}\")" ] }, { @@ -144,7 +144,7 @@ "# Alternatively, you can use copy method\n", "# modified = original.copy()\n", "modified[0] = 99\n", - "print(\"original: {}, modified: {}\".format(original, modified))" + "print(f\"original: {original}, modified: {modified}\")" ] }, { @@ -204,14 +204,14 @@ "source": [ "numbers = [8, 1, 6, 5, 10]\n", "numbers.sort()\n", - "print(\"numbers: {}\".format(numbers))\n", + "print(f\"numbers: {numbers}\")\n", "\n", "numbers.sort(reverse=True)\n", - "print(\"numbers reversed: {}\".format(numbers))\n", + "print(f\"numbers reversed: {numbers}\")\n", "\n", "words = [\"this\", \"is\", \"a\", \"list\", \"of\", \"words\"]\n", "words.sort()\n", - "print(\"words: {}\".format(words))" + "print(f\"words: {words}\")" ] }, { @@ -230,7 +230,7 @@ "source": [ "numbers = [8, 1, 6, 5, 10]\n", "sorted_numbers = sorted(numbers)\n", - "print(\"numbers: {}, sorted: {}\".format(numbers, sorted_numbers))" + "print(f\"{numbers=}, {sorted_numbers=}\")" ] }, { @@ -249,7 +249,7 @@ "first_list = [\"beef\", \"ham\"]\n", "second_list = [\"potatoes\", 1, 3]\n", "first_list.extend(second_list)\n", - "print(\"first: {}, second: {}\".format(first_list, second_list))" + "print(f\"{first_list=}, {second_list=}\")" ] }, { @@ -268,11 +268,7 @@ "first = [1, 2, 3]\n", "second = [4, 5]\n", "first += second # same as: first = first + second\n", - "print(\"first: {}\".format(first))\n", - "\n", - "# If you need a new list\n", - "summed = first + second\n", - "print(\"summed: {}\".format(summed))" + "print(f\"{first=}\")" ] }, { @@ -296,7 +292,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -310,7 +306,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/05_dictionaries.ipynb b/notebooks/beginner/notebooks/05_dictionaries.ipynb index 97aa70c..e880cb6 100644 --- a/notebooks/beginner/notebooks/05_dictionaries.ipynb +++ b/notebooks/beginner/notebooks/05_dictionaries.ipynb @@ -15,7 +15,7 @@ "outputs": [], "source": [ "my_empty_dict = {} # alternative: my_empty_dict = dict()\n", - "print(\"dict: {}, type: {}\".format(my_empty_dict, type(my_empty_dict)))" + "print(f\"dict: {my_empty_dict}, type: {type(my_empty_dict)}\")" ] }, { @@ -37,8 +37,8 @@ "print(dict1)\n", "print(dict2)\n", "\n", - "print(\"equal: {}\".format(dict1 == dict2))\n", - "print(\"length: {}\".format(len(dict1)))" + "print(f\"equals: {dict1 == dict2}\")\n", + "print(f\"length: {len(dict1)}\")" ] }, { @@ -54,9 +54,9 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"keys: {}\".format(dict1.keys()))\n", - "print(\"values: {}\".format(dict1.values()))\n", - "print(\"items: {}\".format(dict1.items()))" + "print(f\"keys: {dict1.keys()}\")\n", + "print(f\"values: {dict1.values()}\")\n", + "print(f\"items: {dict1.items()}\")" ] }, { @@ -77,7 +77,7 @@ "my_dict[\"key2\"] = 99\n", "my_dict[\"key1\"] = \"new value\" # overriding existing value\n", "print(my_dict)\n", - "print(\"value of key1: {}\".format(my_dict[\"key1\"]))" + "print(f\"value of key1: {my_dict['key1']}\")" ] }, { @@ -118,7 +118,7 @@ "if key_to_delete in my_dict:\n", " del my_dict[key_to_delete]\n", "else:\n", - " print(\"{key} is not in {dictionary}\".format(key=key_to_delete, dictionary=my_dict))" + " print(f\"{key_to_delete} is not in {my_dict}\")" ] }, { @@ -138,8 +138,8 @@ "my_other_dict = my_dict\n", "my_other_dict[\"carrot\"] = \"super tasty\"\n", "my_other_dict[\"sausage\"] = \"best ever\"\n", - "print(\"my_dict: {}\\nother: {}\".format(my_dict, my_other_dict))\n", - "print(\"equal: {}\".format(my_dict == my_other_dict))" + "print(f\"{my_dict=}\\nother: {my_other_dict}\")\n", + "print(f\"equals: {my_dict == my_other_dict}\")" ] }, { @@ -158,8 +158,8 @@ "my_dict = {\"ham\": \"good\", \"carrot\": \"semi good\"}\n", "my_other_dict = dict(my_dict)\n", "my_other_dict[\"beer\"] = \"decent\"\n", - "print(\"my_dict: {}\\nother: {}\".format(my_dict, my_other_dict))\n", - "print(\"equal: {}\".format(my_dict == my_other_dict))" + "print(f\"{my_dict=}\\nother: {my_other_dict}\")\n", + "print(f\"equals: {my_dict == my_other_dict}\")" ] }, { @@ -178,11 +178,11 @@ "outputs": [], "source": [ "my_dict = {\"a\": 1, \"b\": 2, \"c\": 3}\n", - "d = my_dict.get(\"d\")\n", - "print(\"d: {}\".format(d))\n", + "value_of_d = my_dict.get(\"d\")\n", + "print(f\"d: {d}\")\n", "\n", "d = my_dict.get(\"d\", \"my default value\")\n", - "print(\"d: {}\".format(d))" + "print(f\"d: {d}\")" ] }, { @@ -199,15 +199,15 @@ "outputs": [], "source": [ "my_dict = dict(food=\"ham\", drink=\"beer\", sport=\"football\")\n", - "print(\"dict before pops: {}\".format(my_dict))\n", + "print(f\"dict before pops: {my_dict}\")\n", "\n", "food = my_dict.pop(\"food\")\n", - "print(\"food: {}\".format(food))\n", - "print(\"dict after popping food: {}\".format(my_dict))\n", + "print(f\"food: {food}\")\n", + "print(f\"dict after popping food: {my_dict}\")\n", "\n", "food_again = my_dict.pop(\"food\", \"default value for food\")\n", - "print(\"food again: {}\".format(food_again))\n", - "print(\"dict after popping food again: {}\".format(my_dict))" + "print(f\"food again: {food_again}\")\n", + "print(f\"dict after popping food again: {my_dict}\")" ] }, { @@ -227,7 +227,7 @@ "my_dict = {\"a\": 1, \"b\": 2, \"c\": 3}\n", "a = my_dict.setdefault(\"a\", \"my default value\")\n", "d = my_dict.setdefault(\"d\", \"my default value\")\n", - "print(\"a: {}\\nd: {}\\nmy_dict: {}\".format(a, d, my_dict))" + "print(f\"a: {a}\\nd: {d}\\nmy_dict: {my_dict}\")" ] }, { @@ -298,7 +298,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -312,7 +312,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/06_for_loops.ipynb b/notebooks/beginner/notebooks/06_for_loops.ipynb index eded387..91c7479 100644 --- a/notebooks/beginner/notebooks/06_for_loops.ipynb +++ b/notebooks/beginner/notebooks/06_for_loops.ipynb @@ -80,7 +80,7 @@ "outputs": [], "source": [ "for idx, val in enumerate(my_list):\n", - " print(\"idx: {}, value: {}\".format(idx, val))" + " print(f\"idx: {idx}, value: {val}\")" ] }, { @@ -108,7 +108,7 @@ "outputs": [], "source": [ "for key, val in my_dict.items():\n", - " print(\"{}={}\".format(key, val))" + " print(f\"{key}={val}\")" ] }, { diff --git a/notebooks/beginner/notebooks/07_functions.ipynb b/notebooks/beginner/notebooks/07_functions.ipynb index bd4957c..d1379a4 100644 --- a/notebooks/beginner/notebooks/07_functions.ipynb +++ b/notebooks/beginner/notebooks/07_functions.ipynb @@ -17,7 +17,7 @@ " print(\"Hello world!\")\n", "\n", "\n", - "print(\"type: {}\".format(my_first_function))\n", + "print(f\"type: {my_first_function}\")\n", "\n", "my_first_function() # Calling a function" ] @@ -36,7 +36,7 @@ "outputs": [], "source": [ "def greet_us(name1, name2):\n", - " print(\"Hello {} and {}!\".format(name1, name2))\n", + " print(f\"Hello {name1} and {name2}!\")\n", "\n", "\n", "greet_us(\"John Doe\", \"Superman\")" @@ -56,7 +56,7 @@ "\n", "uggly_string = \" MixED CaSe \"\n", "pretty = strip_and_lowercase(uggly_string)\n", - "print(\"pretty: {}\".format(pretty))" + "print(f\"pretty: {pretty}\")" ] }, { @@ -186,7 +186,7 @@ "source": [ "def print_sum(val1, val2):\n", " \"\"\"Function which prints the sum of given arguments.\"\"\"\n", - " print(\"sum: {}\".format(val1 + val2))\n", + " print(f\"sum: {val1 + val2}\")\n", "\n", "\n", "print(help(print_sum))" diff --git a/notebooks/beginner/notebooks/10_file_io.ipynb b/notebooks/beginner/notebooks/10_file_io.ipynb index e9b4865..b17e54b 100644 --- a/notebooks/beginner/notebooks/10_file_io.ipynb +++ b/notebooks/beginner/notebooks/10_file_io.ipynb @@ -24,15 +24,15 @@ "import os\n", "\n", "current_file = os.path.realpath(\"file_io.ipynb\")\n", - "print(\"current file: {}\".format(current_file))\n", + "print(f\"current file: {current_file}\")\n", "# Note: in .py files you can get the path of current file by __file__\n", "\n", "current_dir = os.path.dirname(current_file)\n", - "print(\"current directory: {}\".format(current_dir))\n", + "print(f\"current directory: {current_dir}\")\n", "# Note: in .py files you can get the dir of current file by os.path.dirname(__file__)\n", "\n", "data_dir = os.path.join(os.path.dirname(current_dir), \"data\")\n", - "print(\"data directory: {}\".format(data_dir))" + "print(f\"data directory: {data_dir}\")" ] }, { @@ -48,9 +48,9 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"exists: {}\".format(os.path.exists(data_dir)))\n", - "print(\"is file: {}\".format(os.path.isfile(data_dir)))\n", - "print(\"is directory: {}\".format(os.path.isdir(data_dir)))" + "print(f\"exists: {os.path.exists(data_dir)}\")\n", + "print(f\"is file: {os.path.isfile(data_dir)}\")\n", + "print(f\"is directory: {os.path.isdir(data_dir)}\")" ] }, { @@ -68,7 +68,7 @@ "source": [ "file_path = os.path.join(data_dir, \"simple_file.txt\")\n", "\n", - "with open(file_path, \"r\") as simple_file:\n", + "with open(file_path) as simple_file:\n", " for line in simple_file:\n", " print(line.strip())" ] @@ -93,7 +93,7 @@ "file_path = os.path.join(data_dir, \"simple_file.txt\")\n", "\n", "# THIS IS NOT THE PREFERRED WAY\n", - "simple_file = open(file_path, \"r\")\n", + "simple_file = open(file_path)\n", "for line in simple_file:\n", " print(line.strip())\n", "simple_file.close() # This has to be called explicitly" diff --git a/notebooks/beginner/notebooks/11_classes.ipynb b/notebooks/beginner/notebooks/11_classes.ipynb index 0eedf2e..c3c8747 100644 --- a/notebooks/beginner/notebooks/11_classes.ipynb +++ b/notebooks/beginner/notebooks/11_classes.ipynb @@ -18,7 +18,7 @@ " self.name = name\n", "\n", " def greet(self):\n", - " print(\"Hello {}!\".format(self.name))" + " print(f\"Hello {self.name}!\")" ] }, { @@ -28,9 +28,9 @@ "outputs": [], "source": [ "my_instance = MyFirstClass(\"John Doe\")\n", - "print(\"my_instance: {}\".format(my_instance))\n", - "print(\"type: {}\".format(type(my_instance)))\n", - "print(\"my_instance.name: {}\".format(my_instance.name))" + "print(f\"my_instance: {my_instance}\")\n", + "print(f\"type: {type(my_instance)}\")\n", + "print(f\"my_instance.name: {my_instance.name}\")" ] }, { @@ -94,7 +94,7 @@ " self.second_var = var2\n", "\n", " def print_variables(self):\n", - " print(\"{} {}\".format(self.first_var, self.second_var))\n", + " print(f\"{self.first_var} {self.second_var}\")\n", "\n", "\n", "e = Example(\"abc\", 123)\n", @@ -121,11 +121,11 @@ " self.age = age\n", "\n", " def __str__(self):\n", - " return \"Person: {}\".format(self.name)\n", + " return f\"Person: {self.name}\"\n", "\n", "\n", "jack = Person(\"Jack\", 82)\n", - "print(\"This is the string presentation of jack: {}\".format(jack))" + "print(f\"This is the string presentation of jack: {jack}\")" ] }, { @@ -251,7 +251,7 @@ "\n", " def celebrate_birthday(self):\n", " self._age += 1\n", - " print(\"Happy bday for {} years old!\".format(self._age))\n", + " print(f\"Happy bday for {self._age} years old!\")\n", "\n", "\n", "example_person = Person(age=15)\n", @@ -299,11 +299,11 @@ "source": [ "dog = Dog()\n", "dog.greet()\n", - "print(\"Dog's favorite food is {}\".format(dog.favorite_food))\n", + "print(f\"Dog's favorite food is {dog.favorite_food}\")\n", "\n", "cat = Cat()\n", "cat.greet()\n", - "print(\"Cat's favorite food is {}\".format(cat.favorite_food))" + "print(f\"Cat's favorite food is {cat.favorite_food}\")" ] } ], diff --git a/notebooks/beginner/notebooks/12_exceptions.ipynb b/notebooks/beginner/notebooks/12_exceptions.ipynb index 94d7268..86d1ea6 100644 --- a/notebooks/beginner/notebooks/12_exceptions.ipynb +++ b/notebooks/beginner/notebooks/12_exceptions.ipynb @@ -37,12 +37,12 @@ "file_name = \"not_existing.txt\"\n", "\n", "try:\n", - " with open(file_name, \"r\") as my_file:\n", + " with open(file_name) as my_file:\n", " print(\"File is successfully open\")\n", "\n", "except FileNotFoundError as e:\n", - " print(\"Uups, file: {} not found\".format(file_name))\n", - " print(\"Exception: {} was raised\".format(e))" + " print(f\"Uups, file: {file_name} not found\")\n", + " print(f\"Exception: {e} was raised\")" ] }, { @@ -66,19 +66,19 @@ " except ZeroDivisionError as ex1:\n", " print(\"Can't divide by zero\")\n", " except Exception as ex2:\n", - " print(\"Exception: {}\".format(ex2))\n", + " print(f\"Exception: {ex2}\")\n", "\n", " return result\n", "\n", "\n", "result1 = calculate_division(3, 3)\n", - "print(\"result1: {}\".format(result1))\n", + "print(f\"result1: {result1}\")\n", "\n", "result2 = calculate_division(3, \"3\")\n", - "print(\"result2: {}\".format(result2))\n", + "print(f\"result2: {result2}\")\n", "\n", "result3 = calculate_division(3, 0)\n", - "print(\"result3: {}\".format(result3))" + "print(f\"result3: {result3}\")" ] }, { diff --git a/notebooks/beginner/notebooks/14_debugging.ipynb b/notebooks/beginner/notebooks/14_debugging.ipynb index 57acdc4..cf47ac8 100644 --- a/notebooks/beginner/notebooks/14_debugging.ipynb +++ b/notebooks/beginner/notebooks/14_debugging.ipynb @@ -64,16 +64,16 @@ " self._greet_polite(person)\n", "\n", " def _greet_polite(self, name):\n", - " greeting = \"G'day {}! How are you doing?\".format(name)\n", + " greeting = f\"G'day {name}! How are you doing?\"\n", " print(greeting)\n", "\n", " def _greet_street_style(self, name):\n", " # import pdb; pdb.set_trace() # UNCOMMENT\n", " name = name.upper()\n", - " print(\"WASSUP {}!?\".format(name))\n", + " print(f\"WASSUP {name}!?\")\n", "\n", " def _greet_hawaii(self, name):\n", - " print(\"Aloha {}!\".format(name))\n", + " print(f\"Aloha {name}!\")\n", "\n", "\n", "def main():\n", diff --git a/notebooks/beginner/notebooks/15_std_lib.ipynb b/notebooks/beginner/notebooks/15_std_lib.ipynb index 3d13f3b..e2e4b50 100644 --- a/notebooks/beginner/notebooks/15_std_lib.ipynb +++ b/notebooks/beginner/notebooks/15_std_lib.ipynb @@ -24,10 +24,10 @@ "import datetime as dt\n", "\n", "local_now = dt.datetime.now()\n", - "print(\"local now: {}\".format(local_now))\n", + "print(f\"local now: {local_now}\")\n", "\n", "utc_now = dt.datetime.utcnow()\n", - "print(\"utc now: {}\".format(utc_now))\n", + "print(f\"utc now: {utc_now}\")\n", "\n", "# You can access any value separately:\n", "print(\n", @@ -41,8 +41,8 @@ " )\n", ")\n", "\n", - "print(\"date: {}\".format(local_now.date()))\n", - "print(\"time: {}\".format(local_now.time()))" + "print(f\"date: {local_now.date()}\")\n", + "print(f\"time: {local_now.time()}\")" ] }, { @@ -81,7 +81,7 @@ "outputs": [], "source": [ "my_dt = dt.datetime.strptime(\"2000-01-01 10:00:00\", \"%Y-%m-%d %H:%M:%S\")\n", - "print(\"my_dt: {}\".format(my_dt))" + "print(f\"my_dt: {my_dt}\")" ] }, { @@ -99,12 +99,12 @@ "outputs": [], "source": [ "tomorrow = local_now + dt.timedelta(days=1)\n", - "print(\"tomorrow this time: {}\".format(tomorrow))\n", + "print(f\"tomorrow this time: {tomorrow}\")\n", "\n", "delta = tomorrow - local_now\n", - "print(\"tomorrow - now = {}\".format(delta))\n", - "print(\"days: {}, seconds: {}\".format(delta.days, delta.seconds))\n", - "print(\"total seconds: {}\".format(delta.total_seconds()))" + "print(f\"tomorrow - now = {delta}\")\n", + "print(f\"days: {delta.days}, seconds: {delta.seconds}\")\n", + "print(f\"total seconds: {delta.total_seconds()}\")" ] }, { @@ -136,21 +136,21 @@ "import pytz\n", "\n", "naive_utc_now = dt.datetime.utcnow()\n", - "print(\"naive utc now: {}, tzinfo: {}\".format(naive_utc_now, naive_utc_now.tzinfo))\n", + "print(f\"naive utc now: {naive_utc_now}, tzinfo: {naive_utc_now.tzinfo}\")\n", "\n", "# Localizing naive datetimes\n", "UTC_TZ = pytz.timezone(\"UTC\")\n", "utc_now = UTC_TZ.localize(naive_utc_now)\n", - "print(\"utc now: {}, tzinfo: {}\".format(utc_now, utc_now.tzinfo))\n", + "print(f\"utc now: {utc_now}, tzinfo: {utc_now.tzinfo}\")\n", "\n", "# Converting localized datetimes to different timezone\n", "PARIS_TZ = pytz.timezone(\"Europe/Paris\")\n", "paris_now = PARIS_TZ.normalize(utc_now)\n", - "print(\"Paris: {}, tzinfo: {}\".format(paris_now, paris_now.tzinfo))\n", + "print(f\"Paris: {paris_now}, tzinfo: {paris_now.tzinfo}\")\n", "\n", "NEW_YORK_TZ = pytz.timezone(\"America/New_York\")\n", "ny_now = NEW_YORK_TZ.normalize(utc_now)\n", - "print(\"New York: {}, tzinfo: {}\".format(ny_now, ny_now.tzinfo))" + "print(f\"New York: {ny_now}, tzinfo: {ny_now.tzinfo}\")" ] }, { @@ -293,10 +293,10 @@ "import random\n", "\n", "rand_int = random.randint(1, 100)\n", - "print(\"random integer between 1-100: {}\".format(rand_int))\n", + "print(f\"random integer between 1-100: {rand_int}\")\n", "\n", "rand = random.random()\n", - "print(\"random float between 0-1: {}\".format(rand))" + "print(f\"random float between 0-1: {rand}\")" ] }, { @@ -348,12 +348,12 @@ "search_pattern = r\"(g12)\"\n", "\n", "match = re.search(search_pattern, secret_code)\n", - "print(\"match: {}\".format(match))\n", - "print(\"match.group(): {}\".format(match.group()))\n", + "print(f\"match: {match}\")\n", + "print(f\"match.group(): {match.group()}\")\n", "\n", "numbers_pattern = r\"[0-9]\"\n", "numbers_match = re.findall(numbers_pattern, secret_code)\n", - "print(\"numbers: {}\".format(numbers_match))" + "print(f\"numbers: {numbers_match}\")" ] }, { diff --git a/notebooks/beginner/notebooks/16_testing2.ipynb b/notebooks/beginner/notebooks/16_testing2.ipynb index 06b013f..7549d19 100644 --- a/notebooks/beginner/notebooks/16_testing2.ipynb +++ b/notebooks/beginner/notebooks/16_testing2.ipynb @@ -48,7 +48,7 @@ "\n", " @property\n", " def full_name(self):\n", - " return \"{} {}\".format(self.first_name, self.last_name)\n", + " return f\"{self.first_name} {self.last_name}\"\n", "\n", " @property\n", " def as_dict(self):\n", diff --git a/notebooks/intermediate/exercises/01_std_lib2_exercise.ipynb b/notebooks/intermediate/exercises/01_std_lib2_exercise.ipynb index 072d73a..c61bbb4 100644 --- a/notebooks/intermediate/exercises/01_std_lib2_exercise.ipynb +++ b/notebooks/intermediate/exercises/01_std_lib2_exercise.ipynb @@ -22,7 +22,7 @@ "\n", "\n", "def get_wiki_article(name):\n", - " url = \"https://en.wikipedia.org/wiki/{}\".format(name)\n", + " url = f\"https://en.wikipedia.org/wiki/{name}\"\n", " response = urlopen(url)\n", " content = str(response.read())\n", " return content" diff --git a/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb b/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb index e1776c3..bfae2e0 100644 --- a/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb +++ b/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb @@ -84,7 +84,7 @@ " 2. numeric values (list of floats)\n", " 3. non-numeric values (list of strings)\n", " \"\"\"\n", - " data_file = open(path, \"r\")\n", + " data_file = open(path)\n", " lines = data_file.readlines()\n", " line_count = len(lines)\n", " idx = 0\n", diff --git a/notebooks/intermediate/notebooks/01_idiomatic_loops.ipynb b/notebooks/intermediate/notebooks/01_idiomatic_loops.ipynb index 4b3f446..73c1b1a 100644 --- a/notebooks/intermediate/notebooks/01_idiomatic_loops.ipynb +++ b/notebooks/intermediate/notebooks/01_idiomatic_loops.ipynb @@ -90,7 +90,7 @@ "outputs": [], "source": [ "for idx, val in enumerate(data):\n", - " print(\"{}: {}\".format(idx, val))" + " print(f\"{idx}: {val}\")" ] }, { diff --git a/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb b/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb index fcc27e6..f1fdc2f 100644 --- a/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb +++ b/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb @@ -220,7 +220,7 @@ "outputs": [], "source": [ "def word_count_of_txt_file(file_path):\n", - " with open(file_path, \"r\") as f:\n", + " with open(file_path) as f:\n", " content = f.read()\n", " return len(content.split())" ] diff --git a/notebooks/intermediate/notebooks/01_std_lib2.ipynb b/notebooks/intermediate/notebooks/01_std_lib2.ipynb index b567924..2c0c84f 100644 --- a/notebooks/intermediate/notebooks/01_std_lib2.ipynb +++ b/notebooks/intermediate/notebooks/01_std_lib2.ipynb @@ -40,7 +40,7 @@ "import json\n", "\n", "json_data = json.dumps(data)\n", - "print(\"type: {} data: {}\".format(type(json_data), json_data))" + "print(f\"type: {type(json_data)} data: {json_data}\")" ] }, { @@ -57,7 +57,7 @@ "outputs": [], "source": [ "decoded = json.loads(json_data)\n", - "print(\"type: {} data: {}\".format(type(decoded), decoded))" + "print(f\"type: {type(decoded)} data: {decoded}\")" ] }, { @@ -217,7 +217,7 @@ "lisa = Person(\"Lis Doe\", age=77, is_gangster=False)\n", "\n", "print(john, lisa)\n", - "print(\"Is John a gangster: {}\".format(john.is_gangster))\n", + "print(f\"Is John a gangster: {john.is_gangster}\")\n", "\n", "# tuples are immutable, thus you can't do this\n", "# john.is_gangster = False" @@ -242,12 +242,12 @@ "data = [1, 2, 3, 1, 2, 4, 5, 6, 2]\n", "\n", "counter = Counter(data)\n", - "print(\"type: {}, counter: {}\".format(type(counter), counter))\n", + "print(f\"type: {type(counter)}, counter: {counter}\")\n", "\n", - "print(\"count of twos: {}\".format(counter[2]))\n", - "print(\"count of tens: {}\".format(counter[10])) # zero for non existing\n", + "print(f\"count of twos: {counter[2]}\")\n", + "print(f\"count of tens: {counter[10]}\") # zero for non existing\n", "\n", - "print(\"counter is a dict: {}\".format(isinstance(counter, dict)))" + "print(f\"counter is a dict: {isinstance(counter, dict)}\")" ] }, { diff --git a/notebooks/intermediate/notebooks/02_idiomatic_dicts.ipynb b/notebooks/intermediate/notebooks/02_idiomatic_dicts.ipynb index 0cccc10..4303755 100644 --- a/notebooks/intermediate/notebooks/02_idiomatic_dicts.ipynb +++ b/notebooks/intermediate/notebooks/02_idiomatic_dicts.ipynb @@ -295,7 +295,7 @@ "source": [ "for key in my_dict:\n", " val = my_dict[key]\n", - " print(\"key: {:15s} value: {}\".format(key, val))" + " print(f\"key: {key:15s} value: {val}\")" ] }, { @@ -312,7 +312,7 @@ "outputs": [], "source": [ "for key, val in my_dict.items():\n", - " print(\"key: {:15s} value: {}\".format(key, val))" + " print(f\"key: {key:15s} value: {val}\")" ] } ], diff --git a/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb b/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb index 8b9c642..ad6c8d1 100644 --- a/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb +++ b/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb @@ -328,7 +328,7 @@ " all_values_truthy = False\n", " break\n", "\n", - "print(\"any truthy: {}, all truthy: {}\".format(any_value_truthy, all_values_truthy))" + "print(f\"any truthy: {any_value_truthy}, all truthy: {all_values_truthy}\")" ] }, { @@ -346,7 +346,7 @@ "source": [ "any_value_truthy = any(example_collection)\n", "all_values_truthy = all(example_collection)\n", - "print(\"any truthy: {}, all truthy: {}\".format(any_value_truthy, all_values_truthy))" + "print(f\"any truthy: {any_value_truthy}, all truthy: {all_values_truthy}\")" ] }, { diff --git a/notebooks/intermediate/notebooks/04_idiomatic_misc2.ipynb b/notebooks/intermediate/notebooks/04_idiomatic_misc2.ipynb index 7500f1b..d709c07 100644 --- a/notebooks/intermediate/notebooks/04_idiomatic_misc2.ipynb +++ b/notebooks/intermediate/notebooks/04_idiomatic_misc2.ipynb @@ -149,10 +149,10 @@ " bad_calculation = 1 / 0\n", "\n", "except ValueError as e:\n", - " print(\"Oh boi, some value error: {}\".format(e))\n", + " print(f\"Oh boi, some value error: {e}\")\n", " exception_occured = True\n", "except Exception as e:\n", - " print(\"Oh boi, something bad happened: {}\".format(e))\n", + " print(f\"Oh boi, something bad happened: {e}\")\n", " exception_occured = True\n", "\n", "if not exception_occured:\n", @@ -178,9 +178,9 @@ " bad_calculation = 1 / 0\n", "\n", "except ValueError as e:\n", - " print(\"Oh boi, some keyerror: {}\".format(e))\n", + " print(f\"Oh boi, some keyerror: {e}\")\n", "except Exception as e:\n", - " print(\"Oh boi, something bad happened: {}\".format(e))\n", + " print(f\"Oh boi, something bad happened: {e}\")\n", "else:\n", " print(\"All went well!\")" ] @@ -221,7 +221,7 @@ " return result\n", "\n", "\n", - "print(\"return value: {}\".format(magical_calculation()))" + "print(f\"return value: {magical_calculation()}\")" ] }, { @@ -250,7 +250,7 @@ " return result\n", "\n", "\n", - "print(\"return value: {}\".format(magical_calculation()))" + "print(f\"return value: {magical_calculation()}\")" ] }, { @@ -283,13 +283,13 @@ "source": [ "try:\n", " some_file = open(\"tmp.txt\", \"w\")\n", - " print(\"the file is now open: {}\".format(not some_file.closed))\n", + " print(f\"the file is now open: {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))" + " print(f\"now it's closed: {some_file.closed}\")" ] }, { @@ -306,11 +306,11 @@ "outputs": [], "source": [ "with open(\"tmp.txt\", \"w\") as some_file:\n", - " print(\"the file is now open: {}\".format(not some_file.closed))\n", + " print(f\"the file is now open: {not some_file.closed}\")\n", "\n", " # here would be some logic\n", "\n", - "print(\"now it's closed: {}\".format(some_file.closed))" + "print(f\"now it's closed: {some_file.closed}\")" ] }, { @@ -476,7 +476,7 @@ " self.last_name = last_name\n", "\n", " def get_full_name(self):\n", - " return \"{} {}\".format(self.first_name, self.last_name)\n", + " return f\"{self.first_name} {self.last_name}\"\n", "\n", " def set_full_name(self, full_name):\n", " parts = full_name.split()\n", @@ -512,7 +512,7 @@ "\n", " @property\n", " def full_name(self):\n", - " return \"{} {}\".format(self.first_name, self.last_name)\n", + " return f\"{self.first_name} {self.last_name}\"\n", "\n", " @full_name.setter\n", " def full_name(self, name):\n", From 02436df8234f4a1d7fb4d154d52c765679739beb Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Fri, 21 Apr 2023 13:47:20 +0300 Subject: [PATCH 47/60] Update readme --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8c8ecd3..fac79a2 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,13 @@ # Learn Python 3 -[![Build Status](https://travis-ci.org/jerry-git/learn-python3.svg?branch=master)](https://travis-ci.org/jerry-git/learn-python3) - ## Introduction -This repository contains a collection of materials for teaching/learning Python 3 (3.5+). +This repository contains a collection of materials for teaching/learning Python 3 (3.10+). #### Requirements -* Have Python 3.5 or newer installed. You can check the version by typing `python3 --version` in your command line. You can download the latest Python version from [here](https://www.python.org/downloads/). -* Have [Jupyter Notebook installed](http://jupyter.readthedocs.io/en/latest/install.html). +* Have Python 3.10 or newer installed. You can check the version by typing `python3 --version` in your command line. You can download the latest Python version from [here](https://www.python.org/downloads/). +* Have [Jupyter Notebook installed](http://jupyter.readthedocs.io/en/latest/install.html). `pip install jupyter` is sufficient in most cases. If you can not access Python and/or Jupyter Notebook on your machine, you can still follow the web based materials. However, you should be able to use Jupyter Notebook in order to complete the exercises. From 4bc0a781f6da53105dc49d1c6ed894da82775737 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Fri, 21 Apr 2023 14:14:52 +0300 Subject: [PATCH 48/60] Fix undefined variable --- notebooks/beginner/notebooks/05_dictionaries.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/notebooks/beginner/notebooks/05_dictionaries.ipynb b/notebooks/beginner/notebooks/05_dictionaries.ipynb index e880cb6..152ee95 100644 --- a/notebooks/beginner/notebooks/05_dictionaries.ipynb +++ b/notebooks/beginner/notebooks/05_dictionaries.ipynb @@ -179,10 +179,10 @@ "source": [ "my_dict = {\"a\": 1, \"b\": 2, \"c\": 3}\n", "value_of_d = my_dict.get(\"d\")\n", - "print(f\"d: {d}\")\n", + "print(f\"d: {value_of_d}\")\n", "\n", - "d = my_dict.get(\"d\", \"my default value\")\n", - "print(f\"d: {d}\")" + "value_of_d = my_dict.get(\"d\", \"my default value\")\n", + "print(f\"d: {value_of_d}\")" ] }, { From 1409ba8bb41c59dcee87e8741185960aaf67073f Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Fri, 21 Apr 2023 14:15:08 +0300 Subject: [PATCH 49/60] Minor fixes --- notebooks/beginner/notebooks/07_functions.ipynb | 6 +++--- notebooks/beginner/notebooks/10_file_io.ipynb | 4 ++-- notebooks/beginner/notebooks/11_classes.ipynb | 6 ++---- notebooks/beginner/notebooks/12_exceptions.ipynb | 8 ++++---- .../beginner/notebooks/13_modules_and_packages.ipynb | 10 +++++----- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/notebooks/beginner/notebooks/07_functions.ipynb b/notebooks/beginner/notebooks/07_functions.ipynb index d1379a4..f6a6ded 100644 --- a/notebooks/beginner/notebooks/07_functions.ipynb +++ b/notebooks/beginner/notebooks/07_functions.ipynb @@ -17,7 +17,7 @@ " print(\"Hello world!\")\n", "\n", "\n", - "print(f\"type: {my_first_function}\")\n", + "print(f\"type: {type(my_first_function)}\")\n", "\n", "my_first_function() # Calling a function" ] @@ -240,7 +240,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -254,7 +254,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/10_file_io.ipynb b/notebooks/beginner/notebooks/10_file_io.ipynb index b17e54b..992136c 100644 --- a/notebooks/beginner/notebooks/10_file_io.ipynb +++ b/notebooks/beginner/notebooks/10_file_io.ipynb @@ -138,7 +138,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -152,7 +152,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/11_classes.ipynb b/notebooks/beginner/notebooks/11_classes.ipynb index c3c8747..81e50e9 100644 --- a/notebooks/beginner/notebooks/11_classes.ipynb +++ b/notebooks/beginner/notebooks/11_classes.ipynb @@ -152,9 +152,7 @@ " self.instance_variable = var1\n", "\n", " def show_info(self):\n", - " info = \"instance_variable: {}, name: {}, description: {}\".format(\n", - " self.instance_variable, Example.name, Example.description\n", - " )\n", + " info = f\"instance_variable: {self.instance_variable}, name: {Example.name}, description: {Example.description}\"\n", " print(info)\n", "\n", "\n", @@ -323,7 +321,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.3" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/12_exceptions.ipynb b/notebooks/beginner/notebooks/12_exceptions.ipynb index 86d1ea6..a50fc25 100644 --- a/notebooks/beginner/notebooks/12_exceptions.ipynb +++ b/notebooks/beginner/notebooks/12_exceptions.ipynb @@ -144,23 +144,23 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3.0 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/notebooks/beginner/notebooks/13_modules_and_packages.ipynb b/notebooks/beginner/notebooks/13_modules_and_packages.ipynb index 00833fd..fd2e680 100644 --- a/notebooks/beginner/notebooks/13_modules_and_packages.ipynb +++ b/notebooks/beginner/notebooks/13_modules_and_packages.ipynb @@ -62,13 +62,13 @@ "```python\n", "\n", "def get_available_brands():\n", - " return ['chiquita']\n", + " return [\"chiquita\"]\n", "\n", "\n", "class Banana:\n", - " def __init__(self, brand='chiquita'):\n", + " def __init__(self, brand=\"chiquita\"):\n", " if brand not in get_available_brands():\n", - " raise ValueError('Unkown brand: {}'.format(brand))\n", + " raise ValueError(f\"Unknown brand: {brand}\")\n", " self._brand = brand\n", " \n", "```" @@ -112,7 +112,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -126,7 +126,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, From 5f305d7bcb19c3da11fbb48a81e6b36304c112be Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sat, 22 Apr 2023 14:54:46 +0300 Subject: [PATCH 50/60] Use pathlib --- .../exercises/10_file_io_exercise.ipynb | 25 +++++------ .../exercises/19_recap2_exercise.ipynb | 14 +++--- notebooks/beginner/notebooks/10_file_io.ipynb | 27 ++++++------ notebooks/beginner/notebooks/15_std_lib.ipynb | 43 ++++++------------- .../05_idiomatic_python_exercise.ipynb | 18 ++++---- 5 files changed, 55 insertions(+), 72 deletions(-) diff --git a/notebooks/beginner/exercises/10_file_io_exercise.ipynb b/notebooks/beginner/exercises/10_file_io_exercise.ipynb index 2fcb284..bfeaec4 100644 --- a/notebooks/beginner/exercises/10_file_io_exercise.ipynb +++ b/notebooks/beginner/exercises/10_file_io_exercise.ipynb @@ -10,11 +10,11 @@ "source": [ "# EXECUTE THIS ONE FIRST!\n", "\n", - "import os\n", + "from pathlib import Path\n", "\n", "# Constants for the exercises:\n", - "WORKING_DIR = os.getcwd()\n", - "DATA_DIR = os.path.join(os.path.dirname(WORKING_DIR), \"data\")" + "WORKING_DIR = Path.cwd()\n", + "DATA_DIR = WORKING_DIR.parent / \"data\"" ] }, { @@ -32,12 +32,12 @@ "outputs": [], "source": [ "def sum_numbers_in_file(input_file):\n", - " sum_ = 0 # A common way to use variable names that collide with built-in/keyword words is to add underscore\n", - " with ____(input_file, ____) as ____:\n", + " total = 0\n", + " with ____(input_file) as ____:\n", " for line in ____:\n", " ____ = line.strip() # Remove potential white space\n", - " ____ += float(____)\n", - " return ____" + " total += float(____)\n", + " return _____" ] }, { @@ -48,7 +48,7 @@ }, "outputs": [], "source": [ - "in_file = os.path.join(DATA_DIR, \"numbers.txt\")\n", + "in_file = DATA_DIR / \"numbers.txt\"\n", "assert sum_numbers_in_file(in_file) == 189.5" ] }, @@ -77,8 +77,8 @@ }, "outputs": [], "source": [ - "in_file1 = os.path.join(DATA_DIR, \"simple_file.txt\")\n", - "in_file2 = os.path.join(DATA_DIR, \"simple_file_with_empty_lines.txt\")\n", + "in_file1 = DATA_DIR / \"simple_file.txt\"\n", + "in_file2 = DATA_DIR / \"simple_file_with_empty_lines.txt\"\n", "\n", "expected_file_1 = [\"First\", \"Second\", \"Third\", \"And\"]\n", "assert find_first_words(in_file1) == expected_file_1\n", @@ -89,8 +89,9 @@ } ], "metadata": { + "celltoolbar": "Edit Metadata", "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -104,7 +105,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/exercises/19_recap2_exercise.ipynb b/notebooks/beginner/exercises/19_recap2_exercise.ipynb index e5811e5..41c76b9 100644 --- a/notebooks/beginner/exercises/19_recap2_exercise.ipynb +++ b/notebooks/beginner/exercises/19_recap2_exercise.ipynb @@ -128,11 +128,11 @@ }, "outputs": [], "source": [ - "import os\n", + "from pathlib import Path\n", "\n", - "WORKING_DIR = os.getcwd()\n", - "DATA_DIR = os.path.join(os.path.dirname(WORKING_DIR), \"data\")\n", - "DATA_FILE = os.path.join(DATA_DIR, \"random_data.txt\")\n", + "WORKING_DIR = Path.cwd()\n", + "DATA_DIR = WORKING_DIR.parent / \"data\"\n", + "DATA_FILE = DATA_DIR / \"random_data.txt\"\n", "\n", "da = DataAnalyzer(DATA_FILE)\n", "\n", @@ -171,7 +171,7 @@ }, "outputs": [], "source": [ - "EMPTY_FILE = os.path.join(DATA_DIR, \"empty_file.txt\")\n", + "EMPTY_FILE = DATA_DIR / \"empty_file.txt\"\n", "try:\n", " da_empty = DataAnalyzer(EMPTY_FILE)\n", "except NoData:\n", @@ -183,7 +183,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -197,7 +197,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/10_file_io.ipynb b/notebooks/beginner/notebooks/10_file_io.ipynb index 992136c..5cfb788 100644 --- a/notebooks/beginner/notebooks/10_file_io.ipynb +++ b/notebooks/beginner/notebooks/10_file_io.ipynb @@ -21,17 +21,16 @@ "metadata": {}, "outputs": [], "source": [ - "import os\n", + "from pathlib import Path\n", "\n", - "current_file = os.path.realpath(\"file_io.ipynb\")\n", + "current_file = Path(\"file_io.ipynb\").resolve()\n", "print(f\"current file: {current_file}\")\n", - "# Note: in .py files you can get the path of current file by __file__\n", + "# Note: in .py files you can get the path of current file by Path(__file__)\n", "\n", - "current_dir = os.path.dirname(current_file)\n", + "current_dir = current_file.parent\n", "print(f\"current directory: {current_dir}\")\n", - "# Note: in .py files you can get the dir of current file by os.path.dirname(__file__)\n", "\n", - "data_dir = os.path.join(os.path.dirname(current_dir), \"data\")\n", + "data_dir = current_dir.parent / \"data\"\n", "print(f\"data directory: {data_dir}\")" ] }, @@ -48,9 +47,9 @@ "metadata": {}, "outputs": [], "source": [ - "print(f\"exists: {os.path.exists(data_dir)}\")\n", - "print(f\"is file: {os.path.isfile(data_dir)}\")\n", - "print(f\"is directory: {os.path.isdir(data_dir)}\")" + "print(f\"exists: {data_dir.exists()}\")\n", + "print(f\"is file: {data_dir.is_file()}\")\n", + "print(f\"is directory: {data_dir.is_dir()}\")" ] }, { @@ -66,7 +65,7 @@ "metadata": {}, "outputs": [], "source": [ - "file_path = os.path.join(data_dir, \"simple_file.txt\")\n", + "file_path = data_dir / \"simple_file.txt\"\n", "\n", "with open(file_path) as simple_file:\n", " for line in simple_file:\n", @@ -90,7 +89,7 @@ "metadata": {}, "outputs": [], "source": [ - "file_path = os.path.join(data_dir, \"simple_file.txt\")\n", + "file_path = data_dir / \"simple_file.txt\"\n", "\n", "# THIS IS NOT THE PREFERRED WAY\n", "simple_file = open(file_path)\n", @@ -112,7 +111,7 @@ "metadata": {}, "outputs": [], "source": [ - "new_file_path = os.path.join(data_dir, \"new_file.txt\")\n", + "new_file_path = data_dir / \"new_file.txt\"\n", "\n", "with open(new_file_path, \"w\") as my_file:\n", " my_file.write(\"This is my first file that I wrote with Python.\")" @@ -131,8 +130,8 @@ "metadata": {}, "outputs": [], "source": [ - "if os.path.exists(new_file_path): # make sure it's there\n", - " os.remove(new_file_path)" + "if new_file_path.exists(): # make sure it's there\n", + " new_file_path.unlink()" ] } ], diff --git a/notebooks/beginner/notebooks/15_std_lib.ipynb b/notebooks/beginner/notebooks/15_std_lib.ipynb index e2e4b50..085156f 100644 --- a/notebooks/beginner/notebooks/15_std_lib.ipynb +++ b/notebooks/beginner/notebooks/15_std_lib.ipynb @@ -31,14 +31,7 @@ "\n", "# You can access any value separately:\n", "print(\n", - " \"{} {} {} {} {} {}\".format(\n", - " local_now.year,\n", - " local_now.month,\n", - " local_now.day,\n", - " local_now.hour,\n", - " local_now.minute,\n", - " local_now.second,\n", - " )\n", + " f\"{local_now.year} {local_now.month} {local_now.day} {local_now.hour} {local_now.minute} {local_now.second}\"\n", ")\n", "\n", "print(f\"date: {local_now.date()}\")\n", @@ -111,19 +104,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Working with timezones\n", - "Let's first make sure [`pytz`](http://pytz.sourceforge.net/) is installed." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "\n", - "!{sys.executable} -m pip install pytz" + "### Working with timezones" ] }, { @@ -133,23 +114,23 @@ "outputs": [], "source": [ "import datetime as dt\n", - "import pytz\n", + "from zoneinfo import ZoneInfo\n", "\n", "naive_utc_now = dt.datetime.utcnow()\n", "print(f\"naive utc now: {naive_utc_now}, tzinfo: {naive_utc_now.tzinfo}\")\n", "\n", "# Localizing naive datetimes\n", - "UTC_TZ = pytz.timezone(\"UTC\")\n", - "utc_now = UTC_TZ.localize(naive_utc_now)\n", + "UTC_TZ = ZoneInfo(\"UTC\")\n", + "utc_now = naive_utc_now.replace(tzinfo=UTC_TZ)\n", "print(f\"utc now: {utc_now}, tzinfo: {utc_now.tzinfo}\")\n", "\n", "# Converting localized datetimes to different timezone\n", - "PARIS_TZ = pytz.timezone(\"Europe/Paris\")\n", - "paris_now = PARIS_TZ.normalize(utc_now)\n", + "PARIS_TZ = ZoneInfo(\"Europe/Paris\")\n", + "paris_now = utc_now.astimezone(PARIS_TZ)\n", "print(f\"Paris: {paris_now}, tzinfo: {paris_now.tzinfo}\")\n", "\n", - "NEW_YORK_TZ = pytz.timezone(\"America/New_York\")\n", - "ny_now = NEW_YORK_TZ.normalize(utc_now)\n", + "NEW_YORK_TZ = ZoneInfo(\"America/New_York\")\n", + "ny_now = utc_now.astimezone(NEW_YORK_TZ)\n", "print(f\"New York: {ny_now}, tzinfo: {ny_now.tzinfo}\")" ] }, @@ -248,8 +229,8 @@ "metadata": {}, "outputs": [], "source": [ - "import os\n", "import logging\n", + "from pathlib import Path\n", "\n", "# This is only required for Jupyter notebook environment\n", "from importlib import reload\n", @@ -259,7 +240,7 @@ "logger = logging.getLogger(\"MyFileLogger\")\n", "\n", "# Let's define a file_handler for our logger\n", - "log_path = os.path.join(os.getcwd(), \"my_log.txt\")\n", + "log_path = Path.cwd() / \"my_log.txt\"\n", "file_handler = logging.FileHandler(log_path)\n", "\n", "# And a nice format\n", @@ -401,7 +382,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.3" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb b/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb index bfae2e0..276873f 100644 --- a/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb +++ b/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb @@ -260,14 +260,15 @@ }, "outputs": [], "source": [ - "import os\n", + "from pathlib import Path\n", "\n", - "CURRENT_DIR = os.getcwd()\n", - "DATA_DIR = os.path.join(os.path.dirname(CURRENT_DIR), \"data\")\n", + "CURRENT_DIR = Path.cwd()\n", + "DATA_DIR = CURRENT_DIR.parent / \"data\"\n", + "\n", + "DATA_FILE1 = DATA_DIR / \"misc_data1.txt\"\n", + "DATA_FILE2 = DATA_DIR / \"misc_data2.txt\"\n", + "DATA_FILE3 = DATA_DIR / \"empty.txt\"\n", "\n", - "DATA_FILE1 = os.path.join(DATA_DIR, \"misc_data1.txt\")\n", - "DATA_FILE2 = os.path.join(DATA_DIR, \"misc_data2.txt\")\n", - "DATA_FILE3 = os.path.join(DATA_DIR, \"empty.txt\")\n", "\n", "expected1 = \"\"\"missing values: 2\n", "highest number: 99.0\n", @@ -317,8 +318,9 @@ } ], "metadata": { + "celltoolbar": "Edit Metadata", "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -332,7 +334,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, From 3e497ee5e3eea5fddc5d78956976c0232548c8cf Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sat, 22 Apr 2023 14:55:09 +0300 Subject: [PATCH 51/60] Use ipython friendly debugging --- .../exercises/14_debugging_exercise.ipynb | 3 ++- notebooks/beginner/notebooks/14_debugging.ipynb | 17 ++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/notebooks/beginner/exercises/14_debugging_exercise.ipynb b/notebooks/beginner/exercises/14_debugging_exercise.ipynb index 6bfbf4e..8577ddc 100644 --- a/notebooks/beginner/exercises/14_debugging_exercise.ipynb +++ b/notebooks/beginner/exercises/14_debugging_exercise.ipynb @@ -18,6 +18,7 @@ "source": [ "def stripped_reversed_lowercase(original):\n", " # Set a breakpoint here and start debugging\n", + " # from IPython.core.debugger import Pdb; Pdb().set_trace()\n", " stripped = original.lstrip()\n", " reversed = \" \".join(reversed(stripped))\n", " reversed.lower()\n", @@ -55,7 +56,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.3" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/notebooks/beginner/notebooks/14_debugging.ipynb b/notebooks/beginner/notebooks/14_debugging.ipynb index cf47ac8..f628cb4 100644 --- a/notebooks/beginner/notebooks/14_debugging.ipynb +++ b/notebooks/beginner/notebooks/14_debugging.ipynb @@ -12,8 +12,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## `import pdb; pdb.set_trace()`\n", - "The basic use case for debugging is that you want to stop the execution of your program at some certain point and monitor variable values or program execution in general from that specific point onward. You stop the execution at the point you want by setting a breakpoint into code by `import pdb; pdb.set_trace()` (note in Python versions >= 3.7, there's a shortcut: `breakpoint()`).\n", + "## `breakpoint()`\n", + "The basic use case for debugging is that you want to stop the execution of your program at some certain point and monitor variable values or program execution in general from that specific point onward. You stop the execution at the point you want by setting a breakpoint into code by `breakpoint()`.\n", "\n", "When you execute your program, the execution will stop at this point and will enter to interactive debugger session. You can add as many breakpoints into your code as you want." ] @@ -41,7 +41,7 @@ "metadata": {}, "source": [ "## Let's see how it works\n", - "Uncomment the `import pdb; pdb.set_trace()` lines and execute the cell. Execute the program line by line by using the commands defined above. Try all the above mentioned commands at least once. Pay attention to the difference between `n` and `s`." + "Uncomment the `Pdb().set_trace()` (this is the Jupyter notebook equivalent for `breakpoint()`) lines and execute the cell. Execute the program line by line by using the commands defined above. Try all the above mentioned commands at least once. Pay attention to the difference between `n` and `s`." ] }, { @@ -50,6 +50,9 @@ "metadata": {}, "outputs": [], "source": [ + "from IPython.core.debugger import Pdb\n", + "\n", + "\n", "class SuperGreeter:\n", " def __init__(self, people_to_greet):\n", " self.people = people_to_greet\n", @@ -68,7 +71,7 @@ " print(greeting)\n", "\n", " def _greet_street_style(self, name):\n", - " # import pdb; pdb.set_trace() # UNCOMMENT\n", + " # Pdb().set_trace() # UNCOMMENT\n", " name = name.upper()\n", " print(f\"WASSUP {name}!?\")\n", "\n", @@ -78,7 +81,7 @@ "\n", "def main():\n", " people = [\"John Doe\", \"Donald\", \"Lisa\", \"alex\"]\n", - " # import pdb; pdb.set_trace() # UNCOMMENT\n", + " # Pdb().set_trace() # UNCOMMENT\n", " greeter = SuperGreeter(people)\n", " greeter.greet()\n", "\n", @@ -89,7 +92,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -103,7 +106,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, From d3633a0d47857ad639ef4d83868c29311afd98c1 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sat, 22 Apr 2023 14:55:42 +0300 Subject: [PATCH 52/60] Use ZoneInfo from the Standard Library --- .../exercises/15_std_lib1_exercise.ipynb | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/notebooks/beginner/exercises/15_std_lib1_exercise.ipynb b/notebooks/beginner/exercises/15_std_lib1_exercise.ipynb index 4897a12..8b059cf 100644 --- a/notebooks/beginner/exercises/15_std_lib1_exercise.ipynb +++ b/notebooks/beginner/exercises/15_std_lib1_exercise.ipynb @@ -1,17 +1,5 @@ { "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# pytz will be needed in the exercise\n", - "import sys\n", - "\n", - "!{sys.executable} -m pip install pytz" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -31,7 +19,7 @@ "outputs": [], "source": [ "import datetime as dt\n", - "import pytz\n", + "from zoneinfo import ZoneInfo, available_timezones\n", "\n", "NAIVE_DT = dt.datetime(2000, 1, 1, 10)" ] @@ -51,7 +39,7 @@ }, "outputs": [], "source": [ - "for tz in pytz.all_timezones:\n", + "for tz in available_timezones():\n", " print(tz)" ] }, @@ -96,7 +84,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -110,7 +98,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, From 0381fb0bd02599a873867ffae1f3d577041fc11c Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sat, 22 Apr 2023 14:56:10 +0300 Subject: [PATCH 53/60] Use f-strings --- notebooks/beginner/notebooks/12_exceptions.ipynb | 4 +--- .../intermediate/notebooks/01_pytest_fixtures.ipynb | 3 +-- .../intermediate/notebooks/03_idiomatic_misc1.ipynb | 10 +++------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/notebooks/beginner/notebooks/12_exceptions.ipynb b/notebooks/beginner/notebooks/12_exceptions.ipynb index a50fc25..f062793 100644 --- a/notebooks/beginner/notebooks/12_exceptions.ipynb +++ b/notebooks/beginner/notebooks/12_exceptions.ipynb @@ -129,9 +129,7 @@ "# Dummy example how to use your custom exception\n", "def secret_calculation(number1, number2):\n", " if number1 < 0 or number2 < 0:\n", - " msg = \"Negative number in at least one of the parameters: {}, {}\".format(\n", - " number1, number2\n", - " )\n", + " msg = f\"Negative number in at least one of the parameters: {number1}, {number2}\"\n", " raise NegativeNumbersNotSupported(msg)\n", "\n", " return math.sqrt(number1) + math.sqrt(number2)\n", diff --git a/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb b/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb index f1fdc2f..8bf6da0 100644 --- a/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb +++ b/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb @@ -102,8 +102,7 @@ " pass\n", " \n", " def test_some_other_stuff(self, other_fixture):\n", - " print('here we use also other_fixture which returns: {}'.format(other_fixture))\n", - " pass" + " print(f'here we use also other_fixture which returns: {other_fixture}')" ] }, { diff --git a/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb b/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb index ad6c8d1..437343e 100644 --- a/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb +++ b/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb @@ -414,11 +414,7 @@ "outputs": [], "source": [ "def show_person_details(name, is_gangster, is_hacker, age):\n", - " print(\n", - " \"name: {}, gangster: {}, hacker: {}, age: {}\".format(\n", - " name, is_gangster, is_hacker, age\n", - " )\n", - " )" + " print(f\"name: {name}, gangster: {is_gangster}, hacker: {is_hacker}, age: {age}\")" ] }, { @@ -595,7 +591,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -609,7 +605,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.4" + "version": "3.11.0" } }, "nbformat": 4, From dbf5aafd883d56bd60ebd885714944da552178a1 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Sat, 22 Apr 2023 14:59:56 +0300 Subject: [PATCH 54/60] RE-generate htmls --- notebooks/beginner/html/01_strings.html | 35 ++-- notebooks/beginner/html/02_numbers.html | 6 +- notebooks/beginner/html/03_conditionals.html | 160 +++++------------ notebooks/beginner/html/04_lists.html | 35 ++-- notebooks/beginner/html/05_dictionaries.html | 54 +++--- notebooks/beginner/html/06_for_loops.html | 4 +- notebooks/beginner/html/07_functions.html | 10 +- notebooks/beginner/html/08_testing1.html | 71 ++++---- notebooks/beginner/html/10_file_io.html | 43 +++-- notebooks/beginner/html/11_classes.html | 26 ++- notebooks/beginner/html/12_exceptions.html | 18 +- .../html/13_modules_and_packages.html | 6 +- notebooks/beginner/html/14_debugging.html | 19 ++- notebooks/beginner/html/15_std_lib.html | 161 ++++++------------ notebooks/beginner/html/16_testing2.html | 99 +++++------ .../intermediate/html/01_idiomatic_loops.html | 2 +- .../intermediate/html/01_pytest_fixtures.html | 132 +++++++------- notebooks/intermediate/html/01_std_lib2.html | 14 +- .../intermediate/html/02_idiomatic_dicts.html | 4 +- .../intermediate/html/03_idiomatic_misc1.html | 10 +- .../intermediate/html/04_idiomatic_misc2.html | 24 +-- 21 files changed, 377 insertions(+), 556 deletions(-) diff --git a/notebooks/beginner/html/01_strings.html b/notebooks/beginner/html/01_strings.html index 5355ce0..d2bc0e8 100644 --- a/notebooks/beginner/html/01_strings.html +++ b/notebooks/beginner/html/01_strings.html @@ -15481,7 +15481,7 @@

    str.replace() @@ -15493,8 +15493,11 @@

    str.format()In [9]: @@ -15531,13 +15535,7 @@

    str.format()In [10]: @@ -15605,7 +15602,7 @@

    str.join()In [12]: diff --git a/notebooks/beginner/html/02_numbers.html b/notebooks/beginner/html/02_numbers.html index ae0fc6e..b80b9ac 100644 --- a/notebooks/beginner/html/02_numbers.html +++ b/notebooks/beginner/html/02_numbers.html @@ -15134,7 +15134,7 @@

    int

    @@ -15201,7 +15201,7 @@

    Initialization
    {'value1': 1.6, 'value2': 10, 'name': 'John Doe'}
     {'value1': 1.6, 'value2': 10, 'name': 'John Doe'}
    -equal: True
    +equals: True
     length: 3
     
    @@ -15230,9 +15230,9 @@

    dict.keys(), dict.values

    @@ -15373,7 +15373,7 @@

    Deleting

    if key_to_delete in my_dict: del my_dict[key_to_delete] else: - print("{key} is not in {dictionary}".format(key=key_to_delete, dictionary=my_dict)) + print(f"{key_to_delete} is not in {my_dict}")

    @@ -15426,8 +15426,8 @@

    Dictionaries are mutablemy_other_dict = my_dict my_other_dict["carrot"] = "super tasty" my_other_dict["sausage"] = "best ever" -print("my_dict: {}\nother: {}".format(my_dict, my_other_dict)) -print("equal: {}".format(my_dict == my_other_dict)) +print(f"{my_dict=}\nother: {my_other_dict}") +print(f"equals: {my_dict == my_other_dict}")

    @@ -15447,9 +15447,9 @@

    Dictionaries are mutable -
    my_dict: {'ham': 'good', 'carrot': 'super tasty', 'sausage': 'best ever'}
    +
    my_dict={'ham': 'good', 'carrot': 'super tasty', 'sausage': 'best ever'}
     other: {'ham': 'good', 'carrot': 'super tasty', 'sausage': 'best ever'}
    -equal: True
    +equals: True
     
    @@ -15481,8 +15481,8 @@

    Dictionaries are mutable
    my_dict = {"ham": "good", "carrot": "semi good"}
     my_other_dict = dict(my_dict)
     my_other_dict["beer"] = "decent"
    -print("my_dict: {}\nother: {}".format(my_dict, my_other_dict))
    -print("equal: {}".format(my_dict == my_other_dict))
    +print(f"{my_dict=}\nother: {my_other_dict}")
    +print(f"equals: {my_dict == my_other_dict}")
     
    @@ -15502,9 +15502,9 @@

    Dictionaries are mutable -
    my_dict: {'ham': 'good', 'carrot': 'semi good'}
    +
    my_dict={'ham': 'good', 'carrot': 'semi good'}
     other: {'ham': 'good', 'carrot': 'semi good', 'beer': 'decent'}
    -equal: False
    +equals: False
     
    @@ -15535,11 +15535,11 @@

    dict.get()
    my_dict = {"a": 1, "b": 2, "c": 3}
    -d = my_dict.get("d")
    -print("d: {}".format(d))
    +value_of_d = my_dict.get("d")
    +print(f"d: {value_of_d}")
     
    -d = my_dict.get("d", "my default value")
    -print("d: {}".format(d))
    +value_of_d = my_dict.get("d", "my default value")
    +print(f"d: {value_of_d}")
     
    @@ -15589,15 +15589,15 @@

    dict.pop()
    my_dict = dict(food="ham", drink="beer", sport="football")
    -print("dict before pops: {}".format(my_dict))
    +print(f"dict before pops: {my_dict}")
     
     food = my_dict.pop("food")
    -print("food: {}".format(food))
    -print("dict after popping food: {}".format(my_dict))
    +print(f"food: {food}")
    +print(f"dict after popping food: {my_dict}")
     
     food_again = my_dict.pop("food", "default value for food")
    -print("food again: {}".format(food_again))
    -print("dict after popping food again: {}".format(my_dict))
    +print(f"food again: {food_again}")
    +print(f"dict after popping food again: {my_dict}")
     
    @@ -15653,7 +15653,7 @@

    dict.setdefault()
    my_dict = {"a": 1, "b": 2, "c": 3}
     a = my_dict.setdefault("a", "my default value")
     d = my_dict.setdefault("d", "my default value")
    -print("a: {}\nd: {}\nmy_dict: {}".format(a, d, my_dict))
    +print(f"a: {a}\nd: {d}\nmy_dict: {my_dict}")
     
    diff --git a/notebooks/beginner/html/06_for_loops.html b/notebooks/beginner/html/06_for_loops.html index 933d5bc..e0c7cc8 100644 --- a/notebooks/beginner/html/06_for_loops.html +++ b/notebooks/beginner/html/06_for_loops.html @@ -15303,7 +15303,7 @@

    enumerate()
    for idx, val in enumerate(my_list):
    -    print("idx: {}, value: {}".format(idx, val))
    +    print(f"idx: {idx}, value: {val}")
     
    @@ -15399,7 +15399,7 @@

    Looping dictionaries
    for key, val in my_dict.items():
    -    print("{}={}".format(key, val))
    +    print(f"{key}={val}")
     
    diff --git a/notebooks/beginner/html/07_functions.html b/notebooks/beginner/html/07_functions.html index 6a34ddc..7ba5c6d 100644 --- a/notebooks/beginner/html/07_functions.html +++ b/notebooks/beginner/html/07_functions.html @@ -15126,7 +15126,7 @@

    Functions< print("Hello world!") -print("type: {}".format(my_first_function)) +print(f"type: {type(my_first_function)}") my_first_function() # Calling a function

    @@ -15148,7 +15148,7 @@

    Functions< @@ -15178,7 +15178,7 @@

    Arguments<

    @@ -15351,9 +15351,7 @@

    Creating your custom exceptions# Dummy example how to use your custom exception def secret_calculation(number1, number2): if number1 < 0 or number2 < 0: - msg = "Negative number in at least one of the parameters: {}, {}".format( - number1, number2 - ) + msg = f"Negative number in at least one of the parameters: {number1}, {number2}" raise NegativeNumbersNotSupported(msg) return math.sqrt(number1) + math.sqrt(number2) diff --git a/notebooks/beginner/html/13_modules_and_packages.html b/notebooks/beginner/html/13_modules_and_packages.html index db32a4d..a347b2a 100644 --- a/notebooks/beginner/html/13_modules_and_packages.html +++ b/notebooks/beginner/html/13_modules_and_packages.html @@ -15170,13 +15170,13 @@

    How to use

    Let's consider that banana.py file contains:

    def get_available_brands():
    -    return ['chiquita']
    +    return ["chiquita"]
     
     
     class Banana:
    -    def __init__(self, brand='chiquita'):
    +    def __init__(self, brand="chiquita"):
             if brand not in get_available_brands():
    -            raise ValueError('Unkown brand: {}'.format(brand))
    +            raise ValueError(f"Unknown brand: {brand}")
             self._brand = brand
     
    diff --git a/notebooks/beginner/html/14_debugging.html b/notebooks/beginner/html/14_debugging.html index 0ce26e2..096fded 100644 --- a/notebooks/beginner/html/14_debugging.html +++ b/notebooks/beginner/html/14_debugging.html @@ -15122,7 +15122,7 @@

    Debugging with @@ -15157,7 +15157,7 @@

    Useful commands @@ -15170,7 +15170,10 @@

    Let's see how it worksIn [1]: @@ -15232,8 +15225,8 @@

    strftime() -
    2023/04/19-10:15:30
    -date: 2023-04-19 time:10:15:30
    +
    2023/04/22-14:56:40
    +date: 2023-04-22 time:14:56:40
     
    @@ -15263,7 +15256,7 @@

    strptime()
    my_dt = dt.datetime.strptime("2000-01-01 10:00:00", "%Y-%m-%d %H:%M:%S")
    -print("my_dt: {}".format(my_dt))
    +print(f"my_dt: {my_dt}")
     
    @@ -15313,12 +15306,12 @@

    tomorrow = local_now + dt.timedelta(days=1)
    -print("tomorrow this time: {}".format(tomorrow))
    +print(f"tomorrow this time: {tomorrow}")
     
     delta = tomorrow - local_now
    -print("tomorrow - now = {}".format(delta))
    -print("days: {}, seconds: {}".format(delta.days, delta.seconds))
    -print("total seconds: {}".format(delta.total_seconds()))
    +print(f"tomorrow - now = {delta}")
    +print(f"days: {delta.days}, seconds: {delta.seconds}")
    +print(f"total seconds: {delta.total_seconds()}")
     
    @@ -15338,7 +15331,7 @@

    -
    tomorrow this time: 2023-04-20 10:15:30.717348
    +
    tomorrow this time: 2023-04-23 14:56:40.502649
     tomorrow - now = 1 day, 0:00:00
     days: 1, seconds: 0
     total seconds: 86400.0
    @@ -15357,8 +15350,7 @@ 

    @@ -15368,69 +15360,27 @@

    Working with timezones - - - - -

    @@ -15561,7 +15561,7 @@

    try - finallyreturn result -print("return value: {}".format(magical_calculation())) +print(f"return value: {magical_calculation()}")

    @@ -15623,7 +15623,7 @@

    This is better return result -print("return value: {}".format(magical_calculation())) +print(f"return value: {magical_calculation()}")

    @@ -15699,13 +15699,13 @@

    Use context managers when possible
    try:
         some_file = open("tmp.txt", "w")
    -    print("the file is now open: {}".format(not some_file.closed))
    +    print(f"the file is now open: {not some_file.closed}")
     
         # here would be some logic
     
     finally:
         some_file.close()
    -    print("now it's closed: {}".format(some_file.closed))
    +    print(f"now it's closed: {some_file.closed}")
     
    @@ -15755,11 +15755,11 @@

    Use context manager in - - - - - - - - - - - - - - - - diff --git a/notebooks/beginner/html/11_classes.html b/notebooks/beginner/html/11_classes.html index 23acab0..7404906 100644 --- a/notebooks/beginner/html/11_classes.html +++ b/notebooks/beginner/html/11_classes.html @@ -15166,7 +15166,7 @@

    -
    my_instance: <__main__.MyFirstClass object at 0x10e7bc410>
    +
    my_instance: <__main__.MyFirstClass object at 0x10d893220>
     type: <class '__main__.MyFirstClass'>
     my_instance.name: John Doe
     
    diff --git a/notebooks/beginner/html/15_std_lib.html b/notebooks/beginner/html/15_std_lib.html index 844d3a6..88e5232 100644 --- a/notebooks/beginner/html/15_std_lib.html +++ b/notebooks/beginner/html/15_std_lib.html @@ -15168,11 +15168,11 @@

    -
    local now: 2023-04-22 14:56:40.502649
    -utc now: 2023-04-22 11:56:40.502813
    -2023 4 22 14 56 40
    -date: 2023-04-22
    -time: 14:56:40.502649
    +
    local now: 2023-04-24 13:19:22.350525
    +utc now: 2023-04-24 10:19:22.350692
    +2023 4 24 13 19 22
    +date: 2023-04-24
    +time: 13:19:22.350525
     
    @@ -15225,8 +15225,8 @@

    strftime() -
    2023/04/22-14:56:40
    -date: 2023-04-22 time:14:56:40
    +
    2023/04/24-13:19:22
    +date: 2023-04-24 time:13:19:22
     
    @@ -15331,7 +15331,7 @@

    -
    tomorrow this time: 2023-04-23 14:56:40.502649
    +
    tomorrow this time: 2023-04-25 13:19:22.350525
     tomorrow - now = 1 day, 0:00:00
     days: 1, seconds: 0
     total seconds: 86400.0
    @@ -15400,10 +15400,10 @@ 

    Working with timezones -
    naive utc now: 2023-04-22 11:56:40.575404, tzinfo: None
    -utc now: 2023-04-22 11:56:40.575404+00:00, tzinfo: UTC
    -Paris: 2023-04-22 13:56:40.575404+02:00, tzinfo: Europe/Paris
    -New York: 2023-04-22 07:56:40.575404-04:00, tzinfo: America/New_York
    +
    naive utc now: 2023-04-24 10:19:22.431004, tzinfo: None
    +utc now: 2023-04-24 10:19:22.431004+00:00, tzinfo: UTC
    +Paris: 2023-04-24 12:19:22.431004+02:00, tzinfo: Europe/Paris
    +New York: 2023-04-24 06:19:22.431004-04:00, tzinfo: America/New_York
     
    @@ -15529,9 +15529,8 @@

    Logging expections
    ERROR:root:All went south in my calculation
     Traceback (most recent call last):
    -  File "/var/folders/q4/_vnp7m_d625g5prgrz28h_fr0000gn/T/ipykernel_46498/3366486048.py", line 2, in <module>
    +  File "/var/folders/q4/_vnp7m_d625g5prgrz28h_fr0000gn/T/ipykernel_59325/3366486048.py", line 2, in <module>
         path_calculation = 1 / 0
    -                       ~~^~~
     ZeroDivisionError: division by zero
     
    @@ -15593,8 +15592,8 @@

    Formatting log entries -
    2023-04-22 14:56:40,601 | MyLogger     | WARNING    | Something bad is going to happen
    -2023-04-22 14:56:40,602 | MyLogger     | ERROR      | Uups, it already happened
    +
    2023-04-24 13:19:22,459 | MyLogger     | WARNING    | Something bad is going to happen
    +2023-04-24 13:19:22,460 | MyLogger     | ERROR      | Uups, it already happened
     
    @@ -15701,8 +15700,8 @@

    -
    random integer between 1-100: 18
    -random float between 0-1: 0.5674405898646947
    +
    random integer between 1-100: 22
    +random float between 0-1: 0.010400736609471939
     
    diff --git a/notebooks/beginner/html/16_testing2.html b/notebooks/beginner/html/16_testing2.html index 5c16b2f..64abcec 100644 --- a/notebooks/beginner/html/16_testing2.html +++ b/notebooks/beginner/html/16_testing2.html @@ -15152,39 +15152,43 @@

    Testing with -
    Requirement already satisfied: pytest in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (7.3.1)
    -Requirement already satisfied: iniconfig in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from pytest) (2.0.0)
    -Requirement already satisfied: packaging in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from pytest) (23.1)
    -Requirement already satisfied: pluggy<2.0,>=0.12 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from pytest) (1.0.0)
    +
    Requirement already satisfied: pytest in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (7.3.1)
    +Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pytest) (1.1.1)
    +Requirement already satisfied: tomli>=1.0.0 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pytest) (2.0.1)
    +Requirement already satisfied: pluggy<2.0,>=0.12 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pytest) (1.0.0)
    +Requirement already satisfied: iniconfig in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pytest) (2.0.0)
    +Requirement already satisfied: packaging in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pytest) (23.1)
     
    -[notice] A new release of pip available: 22.3.1 -> 23.1
    +[notice] A new release of pip available: 22.3.1 -> 23.1.1
     [notice] To update, run: pip install --upgrade pip
    -Requirement already satisfied: ipytest in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (0.13.1)
    -Requirement already satisfied: packaging in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipytest) (23.1)
    -Requirement already satisfied: ipython in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipytest) (8.12.0)
    -Requirement already satisfied: pytest>=5.4 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipytest) (7.3.1)
    -Requirement already satisfied: iniconfig in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from pytest>=5.4->ipytest) (2.0.0)
    -Requirement already satisfied: pluggy<2.0,>=0.12 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from pytest>=5.4->ipytest) (1.0.0)
    -Requirement already satisfied: backcall in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (0.2.0)
    -Requirement already satisfied: decorator in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (5.1.1)
    -Requirement already satisfied: jedi>=0.16 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (0.18.2)
    -Requirement already satisfied: matplotlib-inline in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (0.1.6)
    -Requirement already satisfied: pickleshare in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (0.7.5)
    -Requirement already satisfied: prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (3.0.38)
    -Requirement already satisfied: pygments>=2.4.0 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (2.15.1)
    -Requirement already satisfied: stack-data in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (0.6.2)
    -Requirement already satisfied: traitlets>=5 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (5.9.0)
    -Requirement already satisfied: pexpect>4.3 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (4.8.0)
    -Requirement already satisfied: appnope in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from ipython->ipytest) (0.1.3)
    -Requirement already satisfied: parso<0.9.0,>=0.8.0 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from jedi>=0.16->ipython->ipytest) (0.8.3)
    -Requirement already satisfied: ptyprocess>=0.5 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from pexpect>4.3->ipython->ipytest) (0.7.0)
    -Requirement already satisfied: wcwidth in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30->ipython->ipytest) (0.2.6)
    -Requirement already satisfied: executing>=1.2.0 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from stack-data->ipython->ipytest) (1.2.0)
    -Requirement already satisfied: asttokens>=2.1.0 in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from stack-data->ipython->ipytest) (2.2.1)
    -Requirement already satisfied: pure-eval in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from stack-data->ipython->ipytest) (0.2.2)
    -Requirement already satisfied: six in /Users/jerrypussinen/.virtualenvs/learn-python-311/lib/python3.11/site-packages (from asttokens>=2.1.0->stack-data->ipython->ipytest) (1.16.0)
    +Requirement already satisfied: ipytest in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (0.13.1)
    +Requirement already satisfied: pytest>=5.4 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipytest) (7.3.1)
    +Requirement already satisfied: ipython in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipytest) (8.12.0)
    +Requirement already satisfied: packaging in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipytest) (23.1)
    +Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pytest>=5.4->ipytest) (1.1.1)
    +Requirement already satisfied: tomli>=1.0.0 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pytest>=5.4->ipytest) (2.0.1)
    +Requirement already satisfied: pluggy<2.0,>=0.12 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pytest>=5.4->ipytest) (1.0.0)
    +Requirement already satisfied: iniconfig in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pytest>=5.4->ipytest) (2.0.0)
    +Requirement already satisfied: pexpect>4.3 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (4.8.0)
    +Requirement already satisfied: pygments>=2.4.0 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (2.15.0)
    +Requirement already satisfied: jedi>=0.16 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (0.18.2)
    +Requirement already satisfied: prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (3.0.38)
    +Requirement already satisfied: traitlets>=5 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (5.9.0)
    +Requirement already satisfied: pickleshare in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (0.7.5)
    +Requirement already satisfied: backcall in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (0.2.0)
    +Requirement already satisfied: stack-data in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (0.6.2)
    +Requirement already satisfied: matplotlib-inline in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (0.1.6)
    +Requirement already satisfied: decorator in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (5.1.1)
    +Requirement already satisfied: appnope in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from ipython->ipytest) (0.1.3)
    +Requirement already satisfied: parso<0.9.0,>=0.8.0 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from jedi>=0.16->ipython->ipytest) (0.8.3)
    +Requirement already satisfied: ptyprocess>=0.5 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from pexpect>4.3->ipython->ipytest) (0.7.0)
    +Requirement already satisfied: wcwidth in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30->ipython->ipytest) (0.2.6)
    +Requirement already satisfied: asttokens>=2.1.0 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from stack-data->ipython->ipytest) (2.2.1)
    +Requirement already satisfied: executing>=1.2.0 in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from stack-data->ipython->ipytest) (1.2.0)
    +Requirement already satisfied: pure-eval in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from stack-data->ipython->ipytest) (0.2.2)
    +Requirement already satisfied: six in /Users/jerrypussinen/.virtualenvs/learn-python/lib/python3.10/site-packages (from asttokens>=2.1.0->stack-data->ipython->ipytest) (1.16.0)
     
    -[notice] A new release of pip available: 22.3.1 -> 23.1
    +[notice] A new release of pip available: 22.3.1 -> 23.1.1
     [notice] To update, run: pip install --upgrade pip
     
    diff --git a/notebooks/intermediate/html/01_pytest_fixtures.html b/notebooks/intermediate/html/01_pytest_fixtures.html index f462fc9..9c65c0d 100644 --- a/notebooks/intermediate/html/01_pytest_fixtures.html +++ b/notebooks/intermediate/html/01_pytest_fixtures.html @@ -15166,39 +15166,43 @@

    Efficient use of pytest f @@ -15275,7 +15279,7 @@

    Parametrizing fixtures/foo/bar.txt ./bar/baz.txt . -2 passed in 0.02s +2 passed in 0.01s

    From c0d0c4a6f1ef20f46f6248f68b42f66336c02d15 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Mon, 24 Apr 2023 13:54:14 +0300 Subject: [PATCH 58/60] Fix links --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index fac79a2..a0a0071 100644 --- a/README.md +++ b/README.md @@ -51,21 +51,21 @@ See [contributing](https://github.com/jerry-git/learn-python3/blob/master/CONTRI #### Idiomatic Python Python is a powerful language which contains many features not presented in most other programming languages. Idiomatic section will cover some of these Pythonic features in detail. These materials are especially useful for people with background in other programming languages. -1. [Idiomatic loops](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/idiomatic_loops.ipynb) -1. [Idiomatic dictionaries](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_dicts.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/idiomatic_dicts.ipynb) -1. [Idiomatic Python - miscellaneous part 1](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_misc1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/idiomatic_misc1.ipynb) -1. [Idiomatic Python - miscellaneous part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/idiomatic_misc2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/idiomatic_misc2.ipynb) -1. Idiomatic Python exercise [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/idiomatic_python_exercise.ipynb) +1. [Idiomatic loops](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/01_idiomatic_loops.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/01_idiomatic_loops.ipynb) +2. [Idiomatic dictionaries](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/02_idiomatic_dicts.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/02_idiomatic_dicts.ipynb) +3. [Idiomatic Python - miscellaneous part 1](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/03_idiomatic_misc1.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/03_idiomatic_misc1.ipynb) +4. [Idiomatic Python - miscellaneous part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/04_idiomatic_misc2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/04_idiomatic_misc2.ipynb) +5. Idiomatic Python exercise [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/05_idiomatic_python_exercise.ipynb) #### Step up your `pytest` game -1. [Efficient use of fixtures](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/pytest_fixtures.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/pytest_fixtures.ipynb) +1. [Efficient use of fixtures](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/01_pytest_fixtures.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/01_pytest_fixtures.ipynb) #### Best practices A list of best development practices for Python projects. Most of the practices listed here are also applicable for other languages, however the presented tooling focuses mainly on Python. -1. [Best practices](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/best_practices.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/best_practices.ipynb) +1. [Best practices](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/01_best_practices.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/01_best_practices.ipynb) #### General topics -1. [Goodies of the Standard Library - part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/std_lib2_exercise.ipynb) +1. [Goodies of the Standard Library - part 2](https://jerry-git.github.io/learn-python3/notebooks/intermediate/html/01_std_lib2.html) [[notebook]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/notebooks/01_std_lib2.ipynb) [[exercise]](http://nbviewer.jupyter.org/github/jerry-git/learn-python3/blob/master/notebooks/intermediate/exercises/01_std_lib2_exercise.ipynb) ## Credits From 69afbfccbc049418ee98ed17ccda45c3fa42b877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Key?= Date: Mon, 24 Apr 2023 18:53:13 +0200 Subject: [PATCH 59/60] re #12 --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a0a0071..59da373 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,16 @@ This repository contains a collection of materials for teaching/learning Python If you can not access Python and/or Jupyter Notebook on your machine, you can still follow the web based materials. However, you should be able to use Jupyter Notebook in order to complete the exercises. -#### Usage +#### Usage (locally) 1. Clone or download this repository. 2. Run `jupyter notebook` command in your command line in the repository directory. 3. Jupyter Notebook session will open in the browser and you can start navigating through the materials. +#### Usage (Binder in the cloud) + +You can also just use [Binder:](https://mybinder.org/) By clicking of this [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jerry-git/learn-python3/master) badge, the project is opened in a Jupyter instance in the cloud and you can then navigate to the folders containing the notebooks and start them each and interactively explorte them! + #### Contributing See [contributing](https://github.com/jerry-git/learn-python3/blob/master/CONTRIBUTING.md) guide. From bdc2e297185d9c0440ad0867cd5fbb8623e3f8d0 Mon Sep 17 00:00:00 2001 From: Jerry Pussinen Date: Tue, 25 Apr 2023 09:02:37 +0300 Subject: [PATCH 60/60] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59da373..ca05ac1 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ If you can not access Python and/or Jupyter Notebook on your machine, you can st #### Usage (Binder in the cloud) -You can also just use [Binder:](https://mybinder.org/) By clicking of this [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jerry-git/learn-python3/master) badge, the project is opened in a Jupyter instance in the cloud and you can then navigate to the folders containing the notebooks and start them each and interactively explorte them! +You can also just use [Binder:](https://mybinder.org/) By clicking of this [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jerry-git/learn-python3/master) badge, the project is opened in a Jupyter instance in the cloud and you can then navigate to the folders containing the notebooks and start them each and interactively explore them! #### Contributing See [contributing](https://github.com/jerry-git/learn-python3/blob/master/CONTRIBUTING.md) guide.