diff --git a/irrelevant/notebook_generator.py b/irrelevant/notebook_generator.py index d9818b3..17551df 100644 --- a/irrelevant/notebook_generator.py +++ b/irrelevant/notebook_generator.py @@ -34,7 +34,7 @@ STATEMENT_PREFIXES = ["...", ">>> ", "$ "] HOSTED_NOTEBOOK_INSTRUCTIONS = """ -# Hosted notebook instructions +## Hosted notebook instructions This is just an experimental attempt of browsing wtfpython through jupyter notebooks. Some examples are read-only because, - they either require a version of Python that's not supported in the hosted runtime. @@ -48,7 +48,7 @@ The expected outputs are already present in collapsed cells following the code c # Prints out Python version here. ``` -That being said, most of tbe examples do work as expected. If you face any trouble, feel free to consult the original content on wtfpython and create an issue in the repo. Have fun! +That being said, most of the examples do work as expected. If you face any trouble, feel free to consult the original content on wtfpython and create an issue in the repo. Have fun! --- """ @@ -350,4 +350,5 @@ with open(fpath, 'r+', encoding="utf-8") as f: except StopIteration as e: #pprint.pprint(result, indent=2) pre_stuff.append(HOSTED_NOTEBOOK_INSTRUCTIONS) + result.sort(key = lambda x: x["read_only"]) convert_to_notebook(pre_stuff, result, post_stuff) diff --git a/irrelevant/notebook_instructions.md b/irrelevant/notebook_instructions.md new file mode 100644 index 0000000..891698a --- /dev/null +++ b/irrelevant/notebook_instructions.md @@ -0,0 +1,26 @@ +## Generating the notebook + +- Expand the relative links in README.md to absolute ones +- Remove the TOC in README.md (because Google colab generates its own anyway) +- Reorder the examples, so that the ones that work are upfront. +- Run the `notebook_generator.py`, it will generate a notebook named `wtf.ipynb` +- Revert the README.md changes (optional) + + +# Hosted notebook instructions + +This is just an experimental attempt of browsing wtfpython through jupyter notebooks. Some examples are read-only because, +- they either require a version of Python that's not supported in the hosted runtime. +- or they can't be reproduced in the notebook envrinonment. + +The expected outputs are already present in collapsed cells following the code cells. The Google colab provides Python2 (2.7) and Python3 (3.6, default) runtimes. You can switch among these for Python2 specific examples. For examples specific to other minor versions, you can simply refer to collapsed outputs (it's not possible to control the minor version in hosted notebooks as of now). You can check the active version using + +```py +>>> import sys +>>> sys.version +# Prints out Python version here. +``` + +That being said, most of tbe examples do work as expected. If you face any trouble, feel free to consult the original content on wtfpython and create an issue in the repo. Have fun! + + diff --git a/irrelevant/wtf.ipynb b/irrelevant/wtf.ipynb index 64e315b..0464b36 100644 --- a/irrelevant/wtf.ipynb +++ b/irrelevant/wtf.ipynb @@ -162,7 +162,7 @@ "\n", "\n", "\n", - "# Hosted notebook instructions\n", + "## Hosted notebook instructions\n", "\n", "This is just an experimental attempt of browsing wtfpython through jupyter notebooks. Some examples are read-only because, \n", "- they either require a version of Python that's not supported in the hosted runtime.\n", @@ -176,306 +176,11 @@ "# Prints out Python version here.\n", "```\n", "\n", - "That being said, most of tbe examples do work as expected. If you face any trouble, feel free to consult the original content on wtfpython and create an issue in the repo. Have fun!\n", + "That being said, most of the examples do work as expected. If you face any trouble, feel free to consult the original content on wtfpython and create an issue in the repo. Have fun!\n", "\n", "---\n" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ▶ First things first! *\n", - "For some reason, the Python 3.8's \"Walrus\" operator (`:=`) has become quite popular. Let's check it out,\n", - "\n", - "1\\.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - "# Python version 3.8+\n", - "\n", - ">>> a = \"wtf_walrus\"\n", - ">>> a\n", - "```\n", - "```py\n", - "'wtf_walrus'\n", - "\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> a := \"wtf_walrus\"\n", - "```\n", - "```py\n", - "File \"\", line 1\n", - " a := \"wtf_walrus\"\n", - " ^\n", - "SyntaxError: invalid syntax\n", - "\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> (a := \"wtf_walrus\") # This works though\n", - ">>> a\n", - "```\n", - "```py\n", - "'wtf_walrus'\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "2 \\.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - "# Python version 3.8+\n", - "\n", - ">>> a = 6, 9\n", - ">>> a\n", - "```\n", - "```py\n", - "(6, 9)\n", - "\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> (a := 6, 9)\n", - ">>> a\n", - "```\n", - "```py\n", - "6\n", - "\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> a, b = 6, 9 # Typcial unpacking\n", - ">>> a, b\n", - "```\n", - "```py\n", - "(6, 9)\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> (a, b = 16, 19) # Oops\n", - "```\n", - "```py\n", - " File \"\", line 1\n", - " (a, b = 6, 9)\n", - " ^\n", - "SyntaxError: invalid syntax\n", - "\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> (a, b := 16, 19) # This prints out a weird 3-tuple\n", - "```\n", - "```py\n", - "(6, 16, 19)\n", - "\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> a # a is still unchanged?\n", - "```\n", - "```py\n", - "6\n", - "\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> b\n", - "```\n", - "```py\n", - "16\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### 💡 Explanation\n", - "\n", - "**Quick walrus operator refresher**\n", - "\n", - "The Walrus operator (`:=`) was introduced in Python 3.8, it can be useful in situations where you'd want to assign values to variables within an expression.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - "def some_func():\n", - " # Assume some expensive computation here\n", - " # time.sleep(1000)\n", - " return 5\n", - "\n", - "# So instead of,\n", - "if some_func():\n", - " print(some_func()) # Which is bad practice since computation is happening twice\n", - "\n", - "# or\n", - "a = some_func()\n", - "if a:\n", - " print(a)\n", - "\n", - "# Now you can concisely write\n", - "if a := some_func():\n", - " print(a)\n", - "```\n", - "```py\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "**Output (> 3.8):**\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - "5\n", - "5\n", - "5\n", - "```\n", - "```py\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "This saved one line of code, and implicitly prevented invoking `some_func` twice.\n", - "\n", - "- Unparenthesized \"assignment expression\" (use of walrus operator), is restricted at the top level, hence the `SyntaxError` in the `a := \"wtf_walrus\"` statement of the first snippet. Parenthesizing it worked as expected and assigned `a`. \n", - "\n", - "- As usual, parenthesizing of an expression containing `=` operator is not allowed. Hence the syntax error in `(a, b = 6, 9)`. \n", - "\n", - "- The syntax of the Walrus operator is of the form `NAME: expr`, where `NAME` is a valid identifier, and `expr` is a valid expression. Hence, iterable packing and unpacking are not supported which means, \n", - "\n", - " - `(a := 6, 9)` is equivalent to `((a := 6), 9)` and ultimately `(a, 9) ` (where `a`'s value is 6')\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - " >>> (a := 6, 9) == ((a := 6), 9)\n", - "```\n", - "```py\n", - " True\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - " >>> x = (a := 696, 9)\n", - " >>> x\n", - "```\n", - "```py\n", - " (696, 9)\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - " >>> x[0] is a # Both reference same memory location\n", - "```\n", - "```py\n", - " True\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - " - Similarly, `(a, b := 16, 19)` is equivalent to `(a, (b := 16), 19)` which is nothing but a 3-tuple. \n", - "\n" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -1850,9 +1555,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -6926,110 +6629,6 @@ "\n" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ▶ Stubborn `del` operation\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - "class SomeClass:\n", - " def __del__(self):\n", - " print(\"Deleted!\")\n", - "```\n", - "```py\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "**Output:**\n", - "1\\.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> x = SomeClass()\n", - ">>> y = x\n", - ">>> del x # this should print \"Deleted!\"\n", - ">>> del y\n", - "```\n", - "```py\n", - "Deleted!\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Phew, deleted at last. You might have guessed what saved from `__del__` being called in our first attempt to delete `x`. Let's add more twists to the example.\n", - "\n", - "2\\.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> x = SomeClass()\n", - ">>> y = x\n", - ">>> del x\n", - ">>> y # check if y exists\n", - "```\n", - "```py\n", - "<__main__.SomeClass instance at 0x7f98a1a67fc8>\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> del y # Like previously, this should print \"Deleted!\"\n", - ">>> globals() # oh, it didn't. Let's check all our global variables and confirm\n", - "```\n", - "```py\n", - "Deleted!\n", - "{'__builtins__': , 'SomeClass': , '__package__': None, '__name__': '__main__', '__doc__': None}\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Okay, now it's deleted :confused:\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### 💡 Explanation:\n", - "+ `del x` doesn’t directly call `x.__del__()`.\n", - "+ Whenever `del x` is encountered, Python decrements the reference count for `x` by one, and `x.__del__()` when x’s reference count reaches zero.\n", - "+ In the second output snippet, `y.__del__()` was not called because the previous statement (`>>> y`) in the interactive interpreter created another reference to the same object, thus preventing the reference count from reaching zero when `del y` was encountered.\n", - "+ Calling `globals` caused the existing reference to be destroyed, and hence we can see \"Deleted!\" being printed (finally!).\n", - "\n" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -9750,162 +9349,6 @@ "\n" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ▶ Wild imports *\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - "# File: module.py\n", - "\n", - "def some_weird_name_func_():\n", - " print(\"works!\")\n", - "\n", - "def _another_weird_name_func():\n", - " print(\"works!\")\n", - "\n", - "```\n", - "```py\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "**Output**\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> from module import *\n", - ">>> some_weird_name_func_()\n", - "```\n", - "```py\n", - "\"works!\"\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - ">>> _another_weird_name_func()\n", - "```\n", - "```py\n", - "Traceback (most recent call last):\n", - " File \"\", line 1, in \n", - "NameError: name '_another_weird_name_func' is not defined\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### 💡 Explanation:\n", - "\n", - "- It is often advisable to not use wildcard imports. The first obvious reason for this is, in wildcard imports, the names with a leading underscore get imported. This may lead to errors during runtime.\n", - "- Had we used `from ... import a, b, c` syntax, the above `NameError` wouldn't have occurred.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - " >>> from module import some_weird_name_func_, _another_weird_name_func\n", - " >>> _another_weird_name_func()\n", - "```\n", - "```py\n", - " works!\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- If you really want to use wildcard imports, then you'd have to define the list `__all__` in your module that will contain a list of public objects that'll be available when we do wildcard imports.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - " __all__ = ['_another_weird_name_func']\n", - "\n", - " def some_weird_name_func_():\n", - " print(\"works!\")\n", - "\n", - " def _another_weird_name_func():\n", - " print(\"works!\")\n", - "```\n", - "```py\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " **Output**\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - " >>> _another_weird_name_func()\n", - "```\n", - "```py\n", - " \"works!\"\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```py\n", - " >>> some_weird_name_func_()\n", - "```\n", - "```py\n", - " Traceback (most recent call last):\n", - " File \"\", line 1, in \n", - " NameError: name 'some_weird_name_func_' is not defined\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -12156,15 +11599,20 @@ }, { "cell_type": "code", - "execution_count": 1, - "metadata": {}, + "execution_count": null, + "metadata": { + "collapsed": true + }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "339 µs ± 28.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" - ] + "data": { + "text/plain": [ + " 388 µs ± 22.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -12358,6 +11806,561 @@ "\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ▶ First things first! *\n", + "For some reason, the Python 3.8's \"Walrus\" operator (`:=`) has become quite popular. Let's check it out,\n", + "\n", + "1\\.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + "# Python version 3.8+\n", + "\n", + ">>> a = \"wtf_walrus\"\n", + ">>> a\n", + "```\n", + "```py\n", + "'wtf_walrus'\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> a := \"wtf_walrus\"\n", + "```\n", + "```py\n", + "File \"\", line 1\n", + " a := \"wtf_walrus\"\n", + " ^\n", + "SyntaxError: invalid syntax\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> (a := \"wtf_walrus\") # This works though\n", + ">>> a\n", + "```\n", + "```py\n", + "'wtf_walrus'\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "2 \\.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + "# Python version 3.8+\n", + "\n", + ">>> a = 6, 9\n", + ">>> a\n", + "```\n", + "```py\n", + "(6, 9)\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> (a := 6, 9)\n", + ">>> a\n", + "```\n", + "```py\n", + "6\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> a, b = 6, 9 # Typcial unpacking\n", + ">>> a, b\n", + "```\n", + "```py\n", + "(6, 9)\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> (a, b = 16, 19) # Oops\n", + "```\n", + "```py\n", + " File \"\", line 1\n", + " (a, b = 6, 9)\n", + " ^\n", + "SyntaxError: invalid syntax\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> (a, b := 16, 19) # This prints out a weird 3-tuple\n", + "```\n", + "```py\n", + "(6, 16, 19)\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> a # a is still unchanged?\n", + "```\n", + "```py\n", + "6\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> b\n", + "```\n", + "```py\n", + "16\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 💡 Explanation\n", + "\n", + "**Quick walrus operator refresher**\n", + "\n", + "The Walrus operator (`:=`) was introduced in Python 3.8, it can be useful in situations where you'd want to assign values to variables within an expression.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + "def some_func():\n", + " # Assume some expensive computation here\n", + " # time.sleep(1000)\n", + " return 5\n", + "\n", + "# So instead of,\n", + "if some_func():\n", + " print(some_func()) # Which is bad practice since computation is happening twice\n", + "\n", + "# or\n", + "a = some_func()\n", + "if a:\n", + " print(a)\n", + "\n", + "# Now you can concisely write\n", + "if a := some_func():\n", + " print(a)\n", + "```\n", + "```py\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "**Output (> 3.8):**\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + "5\n", + "5\n", + "5\n", + "```\n", + "```py\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "This saved one line of code, and implicitly prevented invoking `some_func` twice.\n", + "\n", + "- Unparenthesized \"assignment expression\" (use of walrus operator), is restricted at the top level, hence the `SyntaxError` in the `a := \"wtf_walrus\"` statement of the first snippet. Parenthesizing it worked as expected and assigned `a`. \n", + "\n", + "- As usual, parenthesizing of an expression containing `=` operator is not allowed. Hence the syntax error in `(a, b = 6, 9)`. \n", + "\n", + "- The syntax of the Walrus operator is of the form `NAME: expr`, where `NAME` is a valid identifier, and `expr` is a valid expression. Hence, iterable packing and unpacking are not supported which means, \n", + "\n", + " - `(a := 6, 9)` is equivalent to `((a := 6), 9)` and ultimately `(a, 9) ` (where `a`'s value is 6')\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + " >>> (a := 6, 9) == ((a := 6), 9)\n", + "```\n", + "```py\n", + " True\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + " >>> x = (a := 696, 9)\n", + " >>> x\n", + "```\n", + "```py\n", + " (696, 9)\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + " >>> x[0] is a # Both reference same memory location\n", + "```\n", + "```py\n", + " True\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " - Similarly, `(a, b := 16, 19)` is equivalent to `(a, (b := 16), 19)` which is nothing but a 3-tuple. \n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ▶ Stubborn `del` operation\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + "class SomeClass:\n", + " def __del__(self):\n", + " print(\"Deleted!\")\n", + "```\n", + "```py\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "**Output:**\n", + "1\\.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> x = SomeClass()\n", + ">>> y = x\n", + ">>> del x # this should print \"Deleted!\"\n", + ">>> del y\n", + "```\n", + "```py\n", + "Deleted!\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Phew, deleted at last. You might have guessed what saved from `__del__` being called in our first attempt to delete `x`. Let's add more twists to the example.\n", + "\n", + "2\\.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> x = SomeClass()\n", + ">>> y = x\n", + ">>> del x\n", + ">>> y # check if y exists\n", + "```\n", + "```py\n", + "<__main__.SomeClass instance at 0x7f98a1a67fc8>\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> del y # Like previously, this should print \"Deleted!\"\n", + ">>> globals() # oh, it didn't. Let's check all our global variables and confirm\n", + "```\n", + "```py\n", + "Deleted!\n", + "{'__builtins__': , 'SomeClass': , '__package__': None, '__name__': '__main__', '__doc__': None}\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Okay, now it's deleted :confused:\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 💡 Explanation:\n", + "+ `del x` doesn’t directly call `x.__del__()`.\n", + "+ Whenever `del x` is encountered, Python decrements the reference count for `x` by one, and `x.__del__()` when x’s reference count reaches zero.\n", + "+ In the second output snippet, `y.__del__()` was not called because the previous statement (`>>> y`) in the interactive interpreter created another reference to the same object, thus preventing the reference count from reaching zero when `del y` was encountered.\n", + "+ Calling `globals` caused the existing reference to be destroyed, and hence we can see \"Deleted!\" being printed (finally!).\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ▶ Wild imports *\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + "# File: module.py\n", + "\n", + "def some_weird_name_func_():\n", + " print(\"works!\")\n", + "\n", + "def _another_weird_name_func():\n", + " print(\"works!\")\n", + "\n", + "```\n", + "```py\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "**Output**\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> from module import *\n", + ">>> some_weird_name_func_()\n", + "```\n", + "```py\n", + "\"works!\"\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + ">>> _another_weird_name_func()\n", + "```\n", + "```py\n", + "Traceback (most recent call last):\n", + " File \"\", line 1, in \n", + "NameError: name '_another_weird_name_func' is not defined\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 💡 Explanation:\n", + "\n", + "- It is often advisable to not use wildcard imports. The first obvious reason for this is, in wildcard imports, the names with a leading underscore get imported. This may lead to errors during runtime.\n", + "- Had we used `from ... import a, b, c` syntax, the above `NameError` wouldn't have occurred.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + " >>> from module import some_weird_name_func_, _another_weird_name_func\n", + " >>> _another_weird_name_func()\n", + "```\n", + "```py\n", + " works!\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- If you really want to use wildcard imports, then you'd have to define the list `__all__` in your module that will contain a list of public objects that'll be available when we do wildcard imports.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + " __all__ = ['_another_weird_name_func']\n", + "\n", + " def some_weird_name_func_():\n", + " print(\"works!\")\n", + "\n", + " def _another_weird_name_func():\n", + " print(\"works!\")\n", + "```\n", + "```py\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " **Output**\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + " >>> _another_weird_name_func()\n", + "```\n", + "```py\n", + " \"works!\"\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```py\n", + " >>> some_weird_name_func_()\n", + "```\n", + "```py\n", + " Traceback (most recent call last):\n", + " File \"\", line 1, in \n", + " NameError: name 'some_weird_name_func_' is not defined\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n" + ] + }, { "cell_type": "markdown", "metadata": {},