diff --git a/content/00_about_the_course.ipynb b/content/00_about_the_course.ipynb index f875613..b32c841 100644 --- a/content/00_about_the_course.ipynb +++ b/content/00_about_the_course.ipynb @@ -64,8 +64,8 @@ "You should already have knowledge of:\n", "- Python fundamentals (identifier, data types, loops, functions, OOP) is assumed.\n", "- If you are new to Python, consider completing a beginner Python course first.\n", - "- We assume that we are on Python 3.8+\n", - "- Git (In case you want to clone this repo and run it locally)." + "- Any Python version 3.8+ is compatible with this material.\n", + "- Git (on case you want to clone this repo and run it locally)." ] }, { @@ -76,7 +76,7 @@ "## What can you expect?\n", "\n", "- Dive deeper into intermediate and somewhat advanced Python concepts and topics.\n", - "- Gain a comprehensive understanding of intermediate Python features.\n", + "- Understand the mechanics of memory, namespaces, sequences, and other types of Python constructs.\n", "- Explore real-world applications of intermediate Python concepts." ] }, @@ -154,7 +154,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/02_memory_management_in_python.ipynb b/content/02_memory_management_in_python.ipynb index 21a9be5..142c514 100644 --- a/content/02_memory_management_in_python.ipynb +++ b/content/02_memory_management_in_python.ipynb @@ -181,7 +181,7 @@ "\n", "c_address = id(c)\n", "print(c_address)\n", - "print(hex(c_address))" + "print(hex(c_address))\n" ] }, { @@ -198,7 +198,12 @@ "print(ctypes.cast(a_address, ctypes.py_object).value)\n", "\n", "# *c_address\n", - "print(ctypes.cast(c_address, ctypes.py_object).value)" + "print(ctypes.cast(c_address, ctypes.py_object).value)\n", + "\n", + "a = 10\n", + "a_id = id(a)\n", + "print(a)\n", + "print(ctypes.cast(a_id, ctypes.py_object).value)\n" ] }, { @@ -218,7 +223,9 @@ "metadata": {}, "outputs": [], "source": [ - "my_var = 12324" + "foo = 104\n", + "x = sys.getrefcount(foo)\n", + "print(f'{x = }')\n" ] }, { @@ -303,7 +310,8 @@ "source": [ "print(id(my_var))\n", "print(id(my_var2))\n", - "id(my_var) == id(my_var2)" + "id(my_var) == id(my_var2)\n", + "my_var is my_var2" ] }, { @@ -396,7 +404,7 @@ "id": "7ae99b2c-84ec-4086-bd9d-bc6afbd7dca2", "metadata": {}, "source": [ - "**Best PyCon talk in Memory management**\n", + "**Excellent PyCon talk in Memory management**\n", "\n", "[![](https://img.youtube.com/vi/F6u5rhUQ6dU/0.jpg)](https://youtu.be/F6u5rhUQ6dU)" ] @@ -599,7 +607,9 @@ "metadata": {}, "outputs": [], "source": [ - "sys.getsizeof([1, 2, [1, 2, 3, 4]])" + "print(sys.getsizeof([1, 2, [1, 2, 3, 4]]))\n", + "\n", + "print(sys.getsizeof([1,2,[1,2,3,4],(1,2,3,4)]))" ] }, { @@ -618,7 +628,7 @@ "There are snippets and tools which can be used to get the actual size of a object.\n", "- [COMPUTE MEMORY FOOTPRINT OF AN OBJECT AND ITS CONTENTS (PYTHON RECIPE)](https://code.activestate.com/recipes/577504/)\n", "- [memray](https://bloomberg.github.io/memray/index.html) - only works on Linux and macOS. \n", - "- [Pympler](https://py`thonhosted.org/Pympler/#)\n", + "- [Pympler](https://pythonhosted.org/Pympler/#)\n", "- [memory-profiler](https://github.com/pythonprofilers/memory_profiler)\n", "- [Scalene](https://github.com/plasma-umass/scalene) - only works properly on Linux and macOS." ] @@ -642,7 +652,7 @@ "source": [ "from pympler import asizeof\n", "\n", - "asizeof.asizeof([1, 2, [1, 2, 3, 4]])" + "print(asizeof.asizeof([1, 2, [1, 2, 3, 4]]))" ] }, { @@ -660,11 +670,9 @@ "source": [ "## Garbage collection Gotcha!\n", "\n", - "**NOTE**: This might seems a bit advance and can be skipped for intermediate level! Maybe revisit this once other topics are covered.\n", - "\n", - "- This section covers some of the gocha of how we can have objects which are still not automatically collected by the garbage collector, sometimes also called as `memory leak`.\n", + "- Garbage collection works 99.9% of the time. Here are some of the 0.1% cases that can cause memory leaks.\n", "- Some may be collected manually by running `gc.collect()`.\n", - "- Other may not be because of the way they were referencec.\n", + "- Others may not be garbage collected without refactoring.\n", "We will also see the BKM of maintaining weak references which are removed as soon as the object goes out of scope." ] }, @@ -700,7 +708,12 @@ "metadata": {}, "outputs": [], "source": [ - "c = None" + "c = C(11)\n", + "c = None\n", + "print('hi')\n", + "import gc\n", + "gc.collect()\n", + "print('hi2')" ] }, { @@ -719,8 +732,10 @@ "outputs": [], "source": [ "a = [1, 2]\n", - "a.append(a)\n", - "\n", + "b = [3, 4]\n", + "a.append(b)\n", + "print(a)\n", + "b.append(a)\n", "print(a)" ] }, @@ -765,6 +780,14 @@ "c = None" ] }, + { + "cell_type": "markdown", + "id": "8362a791", + "metadata": {}, + "source": [ + "`gc.collect()` can be used to explicitly invoke the garbage collector, which will attempt to detect circular references." + ] + }, { "cell_type": "code", "execution_count": null, @@ -982,7 +1005,7 @@ "id": "ca2c0c04-c1be-43f8-9724-746dfb6aeeb9", "metadata": {}, "source": [ - "#### `@lru_cache` in methods can also cause memory leak!\n", + "#### Using `@lru_cache` in methods can be a source of memory leaks.\n", "\n", "- ref: [issue19859 in python bugs](https://bugs.python.org/issue19859)\n", "- ref: [How do I cache method calls](https://docs.python.org/3/faq/programming.html#how-do-i-cache-method-calls)" @@ -1322,8 +1345,12 @@ "a_list = [1, 2, 3, 4]\n", "b_list = [1, 2, 3, 4]\n", "\n", + "a_list.append(5)\n", + "\n", "print(a_list == b_list)\n", - "print(a_list is b_list)" + "print(a_list is b_list)\n", + "\n", + "print(a_list,b_list)" ] }, { @@ -1385,6 +1412,22 @@ "- Numbers outside the interned range or those created dynamically are not interned. For example, `x = 1000` and `y = 1000` will have `x is y` evaluate to `False`." ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ab0181e", + "metadata": {}, + "outputs": [], + "source": [ + "smallx = 5\n", + "smally = 5\n", + "print(f'{smallx} is {smally}? {smallx is smally}')\n", + "\n", + "bigx = 5000\n", + "bigy = 5000\n", + "print(f'{bigx} is {bigy}? {bigx is bigy}')\n" + ] + }, { "cell_type": "markdown", "id": "159bc2f9", @@ -1471,15 +1514,25 @@ "\n", "[From Wikipedia](https://en.wikipedia.org/wiki/Peephole_optimization)\n", "\n", - "> Peephole optimization is an optimization technique performed on a small set of compiler-generated instructions; the small set is known as the peephole or window." + "> Peephole optimization is an optimization technique performed on a small set of compiler-generated instructions; the small set is known as the peephole or window.\n", + "\n", + "Note: `__code__.co_consts` displays all the literals used in a function's bytecode: [co_consts](https://python-reference.readthedocs.io/en/latest/docs/code/consts.html)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "id": "c03a5b04", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1440,)\n" + ] + } + ], "source": [ "c = compile(\"24 * 60\", \"\", \"eval\")\n", "print(c.co_consts)" @@ -1487,10 +1540,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "id": "e34bfdb7", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "((1, 2, 1, 2, 1, 2, 1, 2, 1, 2),)\n" + ] + } + ], "source": [ "c = compile(\"(1, 2) * 5\", \"\", \"eval\")\n", "print(c.co_consts)" @@ -1498,10 +1559,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 41, "id": "0dfadd57", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('xyzxyzxyzxyz',)\n" + ] + } + ], "source": [ "c = compile('\"xyz\" * 4', \"\", \"eval\")\n", "print(c.co_consts)" @@ -1509,10 +1578,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 42, "id": "5299ffe6", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(None, 1440, (1, 2, 1, 2, 1, 2, 1, 2, 1, 2), 'xyzxyzxyzxyz')" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "def a_func():\n", " a_int = 24 * 60\n", @@ -1537,7 +1617,7 @@ "id": "1143c1be-07d9-48c7-9949-478a5af565f9", "metadata": {}, "source": [ - "Use `del` to delete reference when a object is not required anymore" + "`del` can be used to manually delete an object that is no longer required." ] }, { @@ -1545,7 +1625,7 @@ "id": "f8001c69-c9e0-4c6a-bf24-da8a8c37327b", "metadata": {}, "source": [ - "Use `__slot__` to save on memory." + "`__slots__` can declare the fields of a class to save memory per instance: [UsingSlots](https://wiki.python.org/moin/UsingSlots)." ] }, { @@ -1604,6 +1684,8 @@ "metadata": {}, "outputs": [], "source": [ + "print(sys.getsizeof(c))\n", + "print(sys.getsizeof(c.__dict__))\n", "sys.getsizeof(c) + sys.getsizeof(c.__dict__)" ] }, @@ -1701,7 +1783,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/03_function_parameters_and_arguments.ipynb b/content/03_function_parameters_and_arguments.ipynb index 33c6b9d..46824f8 100644 --- a/content/03_function_parameters_and_arguments.ipynb +++ b/content/03_function_parameters_and_arguments.ipynb @@ -77,9 +77,9 @@ "id": "d99ca786", "metadata": {}, "source": [ - "### Argument are always passed by reference\n", + "### Python arguments are passed by assignment\n", "\n", - "Other languages like C++ you can pass argument by value or reference:\n", + "In C++ and many other languages, you can choose to pass arguments by value or by reference:\n", "\n", "![](./static/pass_by_reference.png)\n", "\n", @@ -346,7 +346,9 @@ "outputs": [], "source": [ "my_tuple = (1, 2, 3)\n", - "my_tuple2 = 1, 2, 3 # Doesn't need (). Those are just syntactic sugar" + "my_tuple2 = 1, 2, 3 # Doesn't need (). Those are just syntactic sugar\n", + "print(my_tuple)\n", + "print(my_tuple2)" ] }, { @@ -408,7 +410,8 @@ "outputs": [], "source": [ "my_tuple3 = (1,)\n", - "my_tuple4 = (1,)" + "my_tuple4 = (1,)\n", + "my_tuple5 = 1," ] }, { @@ -520,14 +523,12 @@ "metadata": {}, "outputs": [], "source": [ - "my_set = {1, 2, 3}\n", + "my_set = {1, 10, 100, 1000, 10000, 100000, 1000000}\n", "\n", - "x, y, z = my_set\n", - "print(f\"{x = }, {y = }, {z = }\")\n", - "# Can be x = 1, y = 2, z = 3\n", - "# Or x = 2, y = 1, z = 3\n", - "# Or x = 3, y = 2, z = 1\n", - "# ..." + "a, b, c, d, e, f, g = my_set\n", + "print(f\"{a = }, {b = }, {c = }, {d = }, {e = }, {f = }, {g = }\")\n", + "# order of unpacked set elements is undefined, an example result is:\n", + "# a = 100000, b = 1, c = 1000000, d = 10000, e = 100, f = 1000, g = 10" ] }, { @@ -557,7 +558,7 @@ "source": [ "my_list = [1, 2, 3, 4, 5]\n", "\n", - "x, y, z = my_list[0], my_list[1:-1], my_list[-1]\n", + "x, y, z = my_list[0:2], my_list[2:-1], my_list[-1]\n", "\n", "print(f\"{x = }, {y = }, {z = }\")" ] @@ -695,7 +696,7 @@ "id": "e46e49ca", "metadata": {}, "source": [ - "### Unpacking nested value\n", + "### Unpacking nested values\n", "\n", "Nested values can be unpacked in Python to assign them to multiple variables.\n" ] @@ -780,7 +781,6 @@ "def func(x, y, *z):\n", " print(f\"{x = }, {y = }, {z = }\")\n", "\n", - "\n", "func(1, 2, 3, 4, 5)" ] }, @@ -852,7 +852,7 @@ "id": "73c1b58f", "metadata": {}, "source": [ - "### Mandatory keyword argument\n", + "### Mandatory keyword arguments\n", "\n", "In Python, you can make an argument mandatory by specifying it after the `*args` parameter. This means that the argument must be passed as a keyword argument when calling the function.\n" ] @@ -918,7 +918,7 @@ "outputs": [], "source": [ "def func(x, y, *, z):\n", - " print(f\"{x = }, {y = }, {z = }\")" + " print(f\"{x = }, {y = }, {z = }\")\n" ] }, { @@ -1010,7 +1010,7 @@ "metadata": {}, "outputs": [], "source": [ - "no_positional_argument(1, 2, y=2, z=3)\n", + "no_positional_argument(1, 2, 3, y=2, z=3)\n", "no_positional_argument(1, 2, y=2)\n", "no_positional_argument(1, y=2)" ] @@ -1063,7 +1063,7 @@ "metadata": {}, "outputs": [], "source": [ - "func(1, x=2, y=3, z=4)" + "func(1, x=2, y=3, z=4, b=2)" ] }, { @@ -1196,7 +1196,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/04_namespaces_scopes_and_closures.ipynb b/content/04_namespaces_scopes_and_closures.ipynb index 061db03..780f8ff 100644 --- a/content/04_namespaces_scopes_and_closures.ipynb +++ b/content/04_namespaces_scopes_and_closures.ipynb @@ -92,7 +92,7 @@ "\n", "\n", "def func():\n", - " val += 50 # This line is changed\n", + " val = val + 50 # This line is changed\n", " print(f\"Inside func: Value of local {val = }\\n\")\n", "\n", "\n", @@ -145,16 +145,18 @@ "val = [1, 2, 3]\n", "\n", "print(f\"Outside: Value of global {val = }\\n\")\n", - "\n", + "print(id(val))\n", "\n", "def func():\n", " val += [4]\n", + " print(id(val))\n", " print(f\"Inside func: Value of local {val = }\\n\")\n", "\n", "\n", "func()\n", "\n", - "print(f\"Outside after func call: Value of global {val = }\\n\")" + "print(f\"Outside after func call: Value of global {val = }\\n\")\n", + "print(id(val))" ] }, { @@ -204,12 +206,22 @@ "\n", "print(f\"Outside: Value of global {val = }\\n\")\n", "\n", - "\n", "def func():\n", " val[\"b\"] = \"β\"\n", " print(f\"Inside func: Value of local {val = }\\n\")\n", "\n", "\n", + "foo = [1,2,3]\n", + "print(id(foo))\n", + "foo.append(4)\n", + "print(id(foo))\n", + "\n", + "bar = [4,5,6]\n", + "print(id(bar))\n", + "bar = bar + [7]\n", + "bar += [7]\n", + "print(id(bar))\n", + "\n", "func()\n", "\n", "print(f\"Outside after func call: Value of global {val = }\\n\")" @@ -643,7 +655,7 @@ "def outer_func():\n", " # Free variable\n", " name = \"Brian\"\n", - "\n", + " \n", " def inner_func():\n", " print(name)\n", "\n", @@ -657,7 +669,8 @@ "outputs": [], "source": [ "func = outer_func() # inner() + extended scope `name`\n", - "func()" + "func()\n", + "\n" ] }, { @@ -741,7 +754,10 @@ "metadata": {}, "outputs": [], "source": [ - "func = outer_func(\"Hello\")" + "func = outer_func(\"Hello\")\n", + "print()\n", + "\n", + "func()" ] }, { @@ -750,6 +766,9 @@ "metadata": {}, "outputs": [], "source": [ + "myfunc = outer_func(\"hello2\")\n", + "myfunc()\n", + "\n", "func.__code__.co_freevars" ] }, @@ -786,7 +805,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/05_other_functions_concepts.ipynb b/content/05_other_functions_concepts.ipynb index 2446838..6d58c95 100644 --- a/content/05_other_functions_concepts.ipynb +++ b/content/05_other_functions_concepts.ipynb @@ -174,7 +174,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "**Best PyCon talk on lambda**\n", + "**Good PyCon talk on Lambda Calculus**\n", "\n", "[![](https://img.youtube.com/vi/pkCLMl0e_0k/0.jpg)](https://youtu.be/pkCLMl0e_0k)" ] @@ -183,16 +183,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Higher order function\n", + "## Higher order functions\n", "\n", "[From Wikipedia](https://en.wikipedia.org/wiki/Higher-order_function):\n", "> In mathematics and computer science, a higher-order function (HOF) is a function that does at least one of the following:\n", "> - takes one or more functions as arguments (i.e. a procedural parameter, which is a parameter of a procedure that is itself a procedure),\n", "> - returns a function as its result.\n", "\n", - "Some of the built-in `higher order functions` are `map`, `zip`, `filter`\n", + "Some of the built-in higher-order functions are `map`, `zip`, `filter`\n", "\n", - "> Note: `list comprehension` or `generators` can also do lot of things which `map`, `zip` or `filter` does." + "Note: `list comprehensions` and `generators` can also do lot of things which `map`, `zip` or `filter` does." ] }, { @@ -836,7 +836,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### user define function or methods are callable" + "### user-defined function and methods are callable" ] }, { @@ -859,7 +859,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### classes and methods (function bound to an object) are callable\n", + "### classes and methods (functions bound to an object) are callable\n", "\n", "Objects can also be callable if the class implements __call__ method." ] @@ -894,7 +894,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Generators are callable (discussed in details later section)" + "### Generators are callable" ] }, { @@ -915,11 +915,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Decorator\n", + "## Decorators\n", "\n", - "Most of the decorator from standard library are mentioned here: [wiki.python.org - Decorators](https://wiki.python.org/moin/Decorators)\n", + "Python `@decorators` are syntactic sugar for defining higher-order functions.\n", "\n", - "In simple term decorator `accepts` a `callable` and `returns` a `callable`." + "There are many decorators used in the standard Python library: [wiki.python.org - Decorators](https://wiki.python.org/moin/Decorators)\n", + "\n", + "In simple terms, a decorator accepts a `callable` and returns a `callable`.\n", + "\n", + "[Primer on Python Decorators](https://realpython.com/primer-on-python-decorators)" ] }, { @@ -929,8 +933,6 @@ "outputs": [], "source": [ "# Closure\n", - "\n", - "\n", "def outer_func():\n", " # outer_func body before inner_func\n", " def inner_func():\n", @@ -994,7 +996,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You can actually pass `add` to `trace` function as in python we support `high order function`. This will return a new function (note the address is different)" + "As Python supports higher-order functions, you can pass `add` to the `trace` function. This will return a new function (note the address is different)" ] }, { @@ -1025,13 +1027,6 @@ "print(f\"{add.__closure__ = }\")" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The part in trace will be part of the new add function" - ] - }, { "cell_type": "code", "execution_count": null, @@ -1075,6 +1070,13 @@ "print(f\"The gravitational force between the Earth and the Moon is {force:.2e} Newtons.\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `@decorator` syntax is simply a convenient way to state the above relationship between decorator and decorated:" + ] + }, { "cell_type": "code", "execution_count": null, @@ -1161,7 +1163,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### functools.wraps" + "### functools.wraps\n", + "\n", + "`@functools.wraps` is a decorator that allows your returned function to retain the docstring, name, and other metadata from the decorated function." ] }, { @@ -1170,14 +1174,36 @@ "metadata": {}, "outputs": [], "source": [ - "import functools\n", + "def my_decorator(f):\n", + " @functools.wraps(f)\n", + " def wrapper(*args, **kwds):\n", + " print('Calling decorated function')\n", + " return f(*args, **kwds)\n", + " return wrapper\n", "\n", + "@my_decorator\n", + "def example():\n", + " \"\"\"Docstring\"\"\"\n", + " print('Called example function')\n", + "\n", + "example()\n", + "print(f'{example.__name__ = }')\n", + "print(f'{example.__doc__ = }')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import functools\n", "\n", "def trace(func):\n", " @functools.wraps(func)\n", " def call(*args, **kwargs):\n", " # print(\"Calling {} with args={} and kwargs={}\".format(func.__name__, args, kwargs))\n", - " print(f\"Caling {func.__name__} with {args = } and {kwargs = }\")\n", + " print(f\"Calling {func.__name__} with {args = } and {kwargs = }\")\n", " return func(*args, **kwargs)\n", "\n", " return call" @@ -1218,7 +1244,7 @@ "source": [ "### Decorators with parameters\n", "\n", - "You will see lot of built-in decorator which also allows you to pass parametes (`@lru_cache(maxsize=256)`)" + "Decorators can consume parameters. Many built-in decorators use this to enable customization at the call site: (`@lru_cache(maxsize=256)`)" ] }, { @@ -1289,10 +1315,7 @@ "outputs": [], "source": [ "# Use nested closures\n", - "\n", "import time\n", - "\n", - "\n", "def run_multiple_times(num_times):\n", " def inner_decorator(func):\n", " def wrapper(*args, **kwargs):\n", @@ -1343,7 +1366,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`run_multiple_times` is generally refered to as a `decorator factory` since it generates a decorator." + "`run_multiple_times` is an example of a `factory` design pattern, since it generates a decorator." ] }, { @@ -1379,6 +1402,13 @@ "print(f\"{some_computational_task(3, 5) = }\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`pickle` is a Python module for object serialization. Here, we use it to make a key (bytes type) based on function signature." + ] + }, { "cell_type": "code", "execution_count": null, @@ -1386,8 +1416,6 @@ "outputs": [], "source": [ "import pickle\n", - "\n", - "\n", "def cache(func):\n", " seen = {}\n", "\n", @@ -1431,7 +1459,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "**Best PyCon talk on decorator**\n", + "**Good PyCon talk on decorators**\n", "\n", "[![](https://img.youtube.com/vi/MjHpMCIvwsY/0.jpg)](https://youtu.be/MjHpMCIvwsY)" ] @@ -1460,7 +1488,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/06_sequence_iterators_and_generators.ipynb b/content/06_sequence_iterators_and_generators.ipynb index 97dfca3..44f3457 100644 --- a/content/06_sequence_iterators_and_generators.ipynb +++ b/content/06_sequence_iterators_and_generators.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Sequence, Iterator and Generator" + "# Sequences, Iterators and Generators" ] }, { @@ -139,10 +139,10 @@ "source": [ "numbers = [1, 2, 1, 3, 5, 7, 2, 9, 3, 7, 3, 4, 5]\n", "\n", - "print(f\"{numbers[2] = }\")\n", - "print(f\"{numbers[2:10] = }\")\n", + "print(f\"{numbers[2] = }\")\n", + "print(f\"{numbers[2:10] = }\")\n", "print(f\"{numbers[2:10:3] = }\")\n", - "print(f\"{numbers[-1] = }\")" + "print(f\"{numbers[-1] = }\")" ] }, { @@ -224,7 +224,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`for` loop under the hood" + "The Pythonn `for` loop is equivalent to the below `while` loop under the hood:" ] }, { @@ -248,9 +248,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "**Creating custom iterator**\n", + "**Creating custom iterators**\n", "\n", - "You may want to support a custom iterator for your class. To do this, you define an `__iter__` method and a `__next__` method.\n", + "You may want to support iteration over your class. To do this, you define an `__iter__` method and a `__next__` method.\n", "\n", "As Python is duck typed, any class that supplies suitable definitions for `__iter__` and `__next__` can be passed to any operation that expects to iterate over a sequence.\n", "\n", @@ -272,10 +272,12 @@ " self.step = step\n", "\n", " def __iter__(self):\n", - " # An iterator must return itself as an iterator\n", + " # __iter__ returns an object with a valid __next__ method\n", " return self\n", "\n", " def __next__(self):\n", + " # __next__ returns the next value in the iteration and maintains the state of the iterator\n", + " # typically, by incrementing something\n", " if self.current < self.end:\n", " value = self.current\n", " self.current += self.step\n", @@ -298,9 +300,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You can also have infinite iterator which iterates forever. User have to put bound to make sure they don't end up with infinite loop. This can be used to implement [lazy evaluation](https://en.wikipedia.org/wiki/Lazy_evaluation).\n", - "\n", - "Example of creating an infinite iterator which produce square sequence starting from number 1:" + "It is possible to create infinite iterators. If you do so, your user will need to establish a break condition to ensure the iteration terminates. This can be used to implement [lazy evaluation](https://en.wikipedia.org/wiki/Lazy_evaluation)." ] }, { @@ -350,12 +350,12 @@ "source": [ "**Generators**\n", "\n", - "- A generator is a special type of iterator that simplifies iterator creation using functions.\n", + "- A generator is a function that behaves like an iterator.\n", "- Instead of implementing `__iter__()` and `__next__()` methods, you can use the `yield` keyword within a function.\n", "- When a generator function is called, it returns a generator object that can be iterated over.\n", "- The `yield` statement produces a value on-the-fly during iteration, and the function's state is saved between yields.\n", "- Generators are memory-efficient as they generate values as needed, making them ideal for handling large datasets or infinite sequences.\n", - "- Infinite sequences can be created easily using generators without consuming excessive memory." + "- Infinite sequences can be created using generators without consuming excessive memory." ] }, { @@ -410,7 +410,7 @@ "metadata": {}, "source": [ "---\n", - "The `yield from` statement is used in Python to delegate part of the operations of a generator to another generator, iterable, or iterator. It simplifies and enhances the capabilities of nested generators, allowing you to avoid writing complex nested loops or repetitive `for` loops. The `yield from` statement was introduced in Python 3.3 to improve the clarity and efficiency of working with nested generators.\n", + "The `yield from` statement was introduced in Python 3.3 to improve the clarity and efficiency of working with nested generators. This allows you to delegate generation to one or more other generator, iterable, or iterator objects. It simplifies and enhances the capabilities of nested generators, allowing you to avoid writing complex nested loops or repetitive `for` loops. \n", "\n", "When to use `yield from`:\n", "\n", @@ -461,7 +461,7 @@ "metadata": {}, "source": [ "---\n", - "**Iterator** are more memory-efficient than **Generator** " + "**Iterator** is more memory-efficient than **Generator** " ] }, { @@ -486,7 +486,7 @@ "metadata": {}, "source": [ "---\n", - "**Generator** are faster then **Iterator**" + "**Generator** is faster then **Iterator**" ] }, { @@ -496,7 +496,7 @@ "outputs": [], "source": [ "gen = square_generator()\n", - "%timeit -n 100000 -r 5 next(gen)" + "%timeit -n 100000 -r 50 next(gen)" ] }, { @@ -506,7 +506,7 @@ "outputs": [], "source": [ "it = SquareIterator()\n", - "%timeit -n 100000 -r 5 next(it)" + "%timeit -n 100000 -r 50 next(it)" ] }, { @@ -514,7 +514,7 @@ "metadata": {}, "source": [ "---\n", - "Useful `built-in functions`, `itertools functions`, `functools functions` to work with Iterators" + "Useful built-in functions for working with iterators can be found in `itertools` and `functools`." ] }, { @@ -650,7 +650,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "1. `slice()` - Works only with sequence:\n", + "1. `slice()` - Works only with sequences:\n", " - Example: Extracting a specific portion of a string representing a date." ] }, @@ -676,7 +676,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`slice` will not work on iterators." + "`slice` is not supported on iterators. Instead, use `islice` when working with an iterator." ] }, { @@ -786,7 +786,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "3. `functools.partial()` (for filtering with a custom function):\n", + "3. `functools.partial()`\n", + " - `partial()` allows you to create a new function by binding one or more arguments to the function to a constant value.\n", " - Example: Using `functools.partial()` to filter scores above a certain threshold from a list of exam results." ] }, @@ -797,11 +798,25 @@ "outputs": [], "source": [ "from functools import partial\n", - "\n", - "\n", + "basetwo = partial(int, base=2)\n", + "basetwo.__doc__ = 'Convert a base 2 string into an integer'\n", + "print(f'{basetwo(\"10010\") = }')\n", + "print(f'{int(\"10010\",base=2) = }')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functools import partial\n", "def is_above_threshold(threshold, score):\n", " return score >= threshold\n", "\n", + "# === partial(is_above_threshold, 90)\n", + "def is_above_threshold90_manual(score):\n", + " return score >= 90\n", "\n", "exam_results = [85, 90, 78, 92, 68, 95]\n", "\n", @@ -830,10 +845,9 @@ "def is_positive(num):\n", " return num > 0\n", "\n", - "\n", "numbers = [1, 2, 3, -4, 5, 6]\n", "for positive_number in takewhile(is_positive, numbers):\n", - " print(positive_number)" + " print(positive_number)\n" ] }, { @@ -1036,7 +1050,6 @@ "from itertools import starmap\n", "from functools import reduce\n", "\n", - "\n", "# Function to calculate total sales for a product\n", "def calculate_total_sales(product, sales_list):\n", " total_sales = reduce(lambda x, y: x + y, sales_list)\n", @@ -1057,7 +1070,6 @@ "source": [ "from functools import reduce\n", "\n", - "\n", "# Using functools.reduce() to get the grand total sales for all products\n", "grand_total_sales = reduce(\n", " lambda total, product_sales: total + sum(product_sales[1]), sales_data, 0\n", @@ -1201,7 +1213,6 @@ " else:\n", " return \"F\"\n", "\n", - "\n", "students = [\n", " {\"name\": \"Alice\", \"score\": 88},\n", " {\"name\": \"Bob\", \"score\": 95},\n", @@ -1313,8 +1324,8 @@ "source": [ "from itertools import product\n", "\n", - "numbers = [1, 2]\n", - "letters = [\"A\", \"B\"]\n", + "numbers = [1, 2, 3, 4]\n", + "letters = [\"A\", \"B\", 'C', 'D']\n", "\n", "for prod in product(numbers, letters):\n", " print(prod)" @@ -1344,7 +1355,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/07_context_managers.ipynb b/content/07_context_managers.ipynb index b5eac11..4fc60e0 100644 --- a/content/07_context_managers.ipynb +++ b/content/07_context_managers.ipynb @@ -458,7 +458,7 @@ "metadata": {}, "outputs": [], "source": [ - "with CtxMng() as x, y, z:\n", + "with CtxMng() as (x, y, z):\n", " print(f\"{x = }, {y = }, {z = }\")" ] }, @@ -647,7 +647,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/08_argparse.ipynb b/content/08_argparse.ipynb index 8780609..2e9b8f8 100644 --- a/content/08_argparse.ipynb +++ b/content/08_argparse.ipynb @@ -129,7 +129,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python 08_argparse/vm_cli.py vm1" + "!python 08_argparse/vm_cli.py vm1 --vm-type windows" ] }, { @@ -191,7 +191,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python 08_argparse/vm_cli.py vm1 -c 32 -m 256" + "!python 08_argparse/vm_cli.py vm1 -c 32 -m 256 --vm-type windows" ] }, { @@ -200,7 +200,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python 08_argparse/vm_cli.py vm1 -c x -m 256" + "!python 08_argparse/vm_cli.py vm1 -c x -m 256 --vm-type windows" ] }, { @@ -418,7 +418,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/09_unittest.ipynb b/content/09_unittest.ipynb index a8e6d03..df69edb 100644 --- a/content/09_unittest.ipynb +++ b/content/09_unittest.ipynb @@ -396,11 +396,17 @@ " yield\n", " print(\"Teardown - After the test\")\n", "\n", + "@pytest.fixture\n", + "def setup_and_teardown_example2():\n", + " print(\"Setup - Before the test2\")\n", + " yield\n", + " print(\"Teardown - After the test2\") \n", + "\n", "def test_add(setup_and_teardown_example):\n", " print(\"Running test_add\")\n", " assert 1 + 1 == 2\n", "\n", - "@pytest.mark.usefixtures('setup_and_teardown_example')\n", + "@pytest.mark.usefixtures('setup_and_teardown_example', 'setup_and_teardown_example2')\n", "def test_sub():\n", " print(\"Running test_sub\")\n", " assert 1 - 1 == 0" @@ -472,6 +478,172 @@ " assert 1 - 1 == 0" ] }, + { + "cell_type": "markdown", + "id": "0570ba2f", + "metadata": {}, + "source": [ + "`hypothesis` is a Python module for automatically generating test data sets. Highly recommended to add to your testing process.\n", + "https://hypothesis.readthedocs.io/en/latest/\n", + "[Hypothesis quick start guide](https://hypothesis.readthedocs.io/en/latest/quickstart.html)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%pip install hypothesis\n", + "%pip install ipytest" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def heapnew():\n", + " return []\n", + "\n", + "\n", + "def heapempty(heap):\n", + " return not heap\n", + "\n", + "\n", + "def heappush(heap, value):\n", + " heap.append(value)\n", + " index = len(heap) - 1\n", + " while index > 0:\n", + " parent = (index - 1) // 2\n", + " if heap[parent] > heap[index]:\n", + " heap[parent], heap[index] = heap[index], heap[parent]\n", + " index = parent\n", + " else:\n", + " break\n", + "\n", + "\n", + "def heappop(heap):\n", + " return heap.pop(0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import hypothesis\n", + "import ipytest\n", + "ipytest.autoconfig()\n", + "\n", + "from hypothesis.strategies import integers, lists\n", + "from hypothesis import given" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b1611b6", + "metadata": {}, + "outputs": [], + "source": [ + "%%ipytest\n", + "\n", + "@given(lists(integers()))\n", + "def test_myheap_pop_in_sorted_order(ls):\n", + " h = heapnew()\n", + " for l in ls:\n", + " heappush(h, l)\n", + " r = []\n", + " while not heapempty(h):\n", + " r.append(heappop(h))\n", + " assert r == sorted(ls)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46b600e5", + "metadata": {}, + "outputs": [], + "source": [ + "%%ipytest\n", + "\n", + "import heapq\n", + "\n", + "@given(lists(integers()))\n", + "def test_heapq_pop_in_sorted_order(ls):\n", + " h = []\n", + " for l in ls:\n", + " heapq.heappush(h, l)\n", + " r = []\n", + " while len(h):\n", + " r.append(heapq.heappop(h))\n", + " assert r == sorted(ls)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def encode(input_string):\n", + " count = 1\n", + " prev = \"\"\n", + " lst = []\n", + " for character in input_string:\n", + " if character != prev:\n", + " if prev:\n", + " entry = (prev, count)\n", + " lst.append(entry)\n", + " count = 1\n", + " prev = character\n", + " else:\n", + " count += 1\n", + " entry = (character, count)\n", + " lst.append(entry)\n", + " return lst\n", + "\n", + "\n", + "def decode(lst):\n", + " q = \"\"\n", + " for character, count in lst:\n", + " q += character * count\n", + " return q" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "helloenc = encode('hello')\n", + "print(helloenc)\n", + "\n", + "hello = decode(helloenc)\n", + "print(hello)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%ipytest\n", + "\n", + "from hypothesis import given\n", + "from hypothesis.strategies import text\n", + "\n", + "@given(text())\n", + "def test_decode_inverts_encode(s):\n", + " assert decode(encode(s)) == s" + ] + }, { "cell_type": "markdown", "id": "b176970f-a560-4766-bac8-e356029573e2", @@ -497,7 +669,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/10_concurrency.ipynb b/content/10_concurrency.ipynb index 1997c4f..0df2d4d 100644 --- a/content/10_concurrency.ipynb +++ b/content/10_concurrency.ipynb @@ -936,7 +936,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" } }, "nbformat": 4, diff --git a/content/python.ipynb b/content/python.ipynb deleted file mode 100644 index 689e883..0000000 --- a/content/python.ipynb +++ /dev/null @@ -1,721 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "# A Python kernel backed by Pyodide\n", - "\n", - "![](https://raw.githubusercontent.com/pyodide/pyodide/master/docs/_static/img/pyodide-logo.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "import pyodide_kernel\n", - "pyodide_kernel.__version__" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Simple code execution" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "a = 3" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "a" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "b = 89\n", - "\n", - "def sq(x):\n", - " return x * x\n", - "\n", - "sq(b)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "print" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "# Redirected streams" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "import sys\n", - "\n", - "print(\"Error !!\", file=sys.stderr)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Error handling" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true, - "trusted": true - }, - "outputs": [], - "source": [ - "\"Hello\"\n", - "\n", - "def dummy_function():\n", - " import missing_module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "dummy_function()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Code completion" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### press `tab` to see what is available in `sys` module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from sys import " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Code inspection" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### using the question mark" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "?print" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### by pressing `shift+tab`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "print(" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Input support" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "name = await input('Enter your name: ')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "'Hello, ' + name" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Rich representation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from IPython.display import display, Markdown, HTML, JSON, Latex" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "## HTML" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "print('Before display')\n", - "\n", - "s = '

HTML Title

'\n", - "display(HTML(s))\n", - "\n", - "print('After display')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Markdown" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "Markdown('''\n", - "# Title\n", - "\n", - "**in bold**\n", - "\n", - "~~Strikthrough~~\n", - "''')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Pandas DataFrame" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import numpy as np\n", - "from string import ascii_uppercase as letters\n", - "from IPython.display import display\n", - "\n", - "df = pd.DataFrame(np.random.randint(0, 100, size=(100, len(letters))), columns=list(letters))\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Show the same DataFrame " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## IPython.display module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from IPython.display import clear_output, display, update_display\n", - "from asyncio import sleep" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Update display" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "class Square:\n", - " color = 'PeachPuff'\n", - " def _repr_html_(self):\n", - " return '''\n", - "
\n", - "
''' % self.color\n", - "square = Square()\n", - "\n", - "display(square, display_id='some-square')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "square.color = 'OliveDrab'\n", - "update_display(square, display_id='some-square')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Clear output" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "print(\"hello\")\n", - "await sleep(3)\n", - "clear_output() # will flicker when replacing \"hello\" with \"goodbye\"\n", - "print(\"goodbye\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "print(\"hello\")\n", - "await sleep(3)\n", - "clear_output(wait=True) # prevents flickering\n", - "print(\"goodbye\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Display classes" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from IPython.display import HTML\n", - "HTML('''\n", - "
\n", - "
''')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from IPython.display import Math\n", - "Math(r'F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from IPython.display import Latex\n", - "Latex(r\"\"\"\\begin{eqnarray}\n", - "\\nabla \\times \\vec{\\mathbf{B}} -\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{E}}}{\\partial t} & = \\frac{4\\pi}{c}\\vec{\\mathbf{j}} \\\\\n", - "\\nabla \\cdot \\vec{\\mathbf{E}} & = 4 \\pi \\rho \\\\\n", - "\\nabla \\times \\vec{\\mathbf{E}}\\, +\\, \\frac1c\\, \\frac{\\partial\\vec{\\mathbf{B}}}{\\partial t} & = \\vec{\\mathbf{0}} \\\\\n", - "\\nabla \\cdot \\vec{\\mathbf{B}} & = 0 \n", - "\\end{eqnarray}\"\"\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from IPython.display import ProgressBar\n", - "\n", - "for i in ProgressBar(10):\n", - " await sleep(0.1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from IPython.display import JSON\n", - "JSON(['foo', {'bar': ('baz', None, 1.0, 2)}], metadata={}, expanded=True, root='test')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from IPython.display import GeoJSON\n", - "GeoJSON(\n", - " data={\n", - " \"type\": \"Feature\",\n", - " \"geometry\": {\n", - " \"type\": \"Point\",\n", - " \"coordinates\": [11.8, -45.04]\n", - " }\n", - " }, url_template=\"http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png\",\n", - " layer_options={\n", - " \"basemap_id\": \"celestia_mars-shaded-16k_global\",\n", - " \"attribution\" : \"Celestia/praesepe\",\n", - " \"tms\": True,\n", - " \"minZoom\" : 0,\n", - " \"maxZoom\" : 5\n", - " }\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Network requests and JSON" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "import json\n", - "from js import fetch" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "res = await fetch('https://httpbin.org/get')\n", - "text = await res.text()\n", - "obj = json.loads(text) \n", - "JSON(obj)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Sympy" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "from sympy import Integral, sqrt, symbols, init_printing\n", - "\n", - "init_printing()\n", - "\n", - "x = symbols('x')\n", - "\n", - "Integral(sqrt(1 / x), x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Magics" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "import os\n", - "os.listdir()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "%cd /home" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "%pwd" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "current_path = %pwd\n", - "print(current_path)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "%%writefile test.txt\n", - "\n", - "This will create a new file. \n", - "With the text that you see here." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "%history" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "import time" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true - }, - "outputs": [], - "source": [ - "%%timeit \n", - "\n", - "time.sleep(0.1)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python (Pyodide)", - "language": "python", - "name": "python" - }, - "language_info": { - "codemirror_mode": { - "name": "python", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 4 -}