1
0
Fork 0
mirror of https://github.com/satwikkansal/wtfpython synced 2025-07-04 12:28:05 +02:00

Merge branch 'satwikkansal:master' into patch-1

This commit is contained in:
Docle 2024-10-29 11:16:19 +08:00 committed by GitHub
commit f198817aa1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 7459 additions and 4346 deletions

8
.gitignore vendored
View file

@ -2,9 +2,6 @@
node_modules
npm-debug.log
wtfpython-pypi/build/
wtfpython-pypi/dist/
wtfpython-pypi/wtfpython.egg-info
# Python-specific byte-compiled files should be ignored
__pycache__/
@ -16,3 +13,8 @@ irrelevant/.ipynb_checkpoints/
irrelevant/.python-version
.idea/
.vscode/
# Virtual envitonments
venv/
.venv/

21
CONTRIBUTING.md vendored
View file

@ -40,3 +40,24 @@ Few things that you can consider while writing an example,
- Try to be consistent with the namings and the values you use with the variables. For instance, most variable names in the project are along the lines of `some_string`, `some_list`, `some_dict`, etc. You'd see a lot of `x`s for single letter variable names, and `"wtf"` as values for strings. There's no strictly enforced scheme in the project as such, but you can take a glance at other examples to get a gist.
- Try to be as creative as possible to add that element of "surprise" in the setting up part of an example. Sometimes this may mean writing a snippet a sane programmer would never write.
- Also, feel free to add your name to the [contributors list](/CONTRIBUTORS.md).
**Some FAQs**
What is is this after every snippet title (###) in the README: <!-- Example ID: 30f1d3fc-e267-4b30-84ef-4d9e7091ac1a --->? Should it be added manually or can it be ignored when creating new snippets?
That's a random UUID, it is used to keep identify the examples across multiple translations of the project. As a contributor, you don't have to worry about behind the scenes of how it is used, you just have to add a new random UUID to new examples in that format.
Where should new snippets be added? Top/bottom of the section, doesn't ?
There are multiple things that are considered to decide the order (the dependency on the other examples, difficulty level, category, etc). I'd suggest simply adding the new example at the bottom of a section you find more fitting (or just add it to the Miscellaneous section). Its order will be taken care of in future revisions.
What's the difference between the sections (the first two feel very similar)?
The section "Strain your brain" contains more contrived examples that you may not really encounter in real life, whereas the section "Slippery Slopes" contains examples that have the potential to be encountered more frequently while programming.
Before the table of contents it says that markdown-toc -i README.md --maxdepth 3 was used to create it. The pip package markdown-toc does not contain either -i or --maxdepth flags. Which package is meant, or what version of that package?
Should the new table of contents entry for the snippet be created with the above command or created manually (in case the above command does more than only add the entry)?
We use the [markdown-toc](https://www.npmjs.com/package/markdown-toc) npm package to generate ToC. It has some issues with special characters though (I'm not sure if it's fixed yet). More often than not, I just end up inserting the toc link manually at the right place. The tool is handy when I have to big reordering, otherwise just updating toc manually is more convenient imo.
If you have any questions feel free to ask on [this issue](https://github.com/satwikkansal/wtfpython/issues/269) (thanks to [@LiquidFun](https://github.com/LiquidFun) for starting it).

7
CONTRIBUTORS.md vendored
View file

@ -18,11 +18,13 @@ Following are the wonderful people (in no specific order) who have contributed t
| leisurelicht | [leisurelicht](https://github.com/leisurelicht) | [#112](https://github.com/satwikkansal/wtfpython/issues/112) |
| mishaturnbull | [mishaturnbull](https://github.com/mishaturnbull) | [#108](https://github.com/satwikkansal/wtfpython/issues/108) |
| MuseBoy | [MuseBoy](https://github.com/MuseBoy) | [#101](https://github.com/satwikkansal/wtfpython/issues/101) |
| Ghost account | N/A | [#96](https://github.com/satwikkansal/wtfpython/issues/96)
| Ghost account | N/A | [#96](https://github.com/satwikkansal/wtfpython/issues/96) |
| koddo | [koddo](https://github.com/koddo) | [#80](https://github.com/satwikkansal/wtfpython/issues/80), [#73](https://github.com/satwikkansal/wtfpython/issues/73) |
| jab | [jab](https://github.com/jab) | [#77](https://github.com/satwikkansal/wtfpython/issues/77) |
| Jongy | [Jongy](https://github.com/Jongy) | [#208](https://github.com/satwikkansal/wtfpython/issues/208), [#210](https://github.com/satwikkansal/wtfpython/issues/210), [#233](https://github.com/satwikkansal/wtfpython/issues/233) |
| Diptangsu Goswami | [diptangsu](https://github.com/diptangsu) | [#193](https://github.com/satwikkansal/wtfpython/issues/193) |
| Charles | [charles-l](https://github.com/charles-l) | [#245](https://github.com/satwikkansal/wtfpython/issues/245) |
| LiquidFun | [LiquidFun](https://github.com/LiquidFun) | [#267](https://github.com/satwikkansal/wtfpython/issues/267) |
---
@ -32,7 +34,8 @@ Following are the wonderful people (in no specific order) who have contributed t
|-------------|--------|--------|
| leisurelicht | [leisurelicht](https://github.com/leisurelicht) | [Chinese](https://github.com/leisurelicht/wtfpython-cn) |
| vuduclyunitn | [vuduclyunitn](https://github.com/vuduclyunitn) | [Vietnamese](https://github.com/vuduclyunitn/wtfptyhon-vi) |
| José De Freitas | [JoseDeFreitas](https://github.com/JoseDeFreitas) | [Spanish](https://github.com/JoseDeFreitas/wtfpython-es) |
| Vadim Nifadev | [nifadyev](https://github.com/nifadyev) | [Russian](https://github.com/satwikkansal/wtfpython/tree/master/translations/ru-russian) |
Thank you all for your time and making wtfpython more awesome! :smile:

211
README.md vendored
View file

@ -1,10 +1,17 @@
<p align="center"><img src="/images/logo.png" alt=""></p>
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="/images/logo_dark_theme.svg">
<source media="(prefers-color-scheme: light)" srcset="/images/logo.svg">
<img alt="Shows a wtfpython logo." src="/images/logo.svg">
</picture>
</p>
<h1 align="center">What the f*ck Python! 😱</h1>
<p align="center">Exploring and understanding Python through surprising snippets.</p>
Translations: [Chinese 中文](https://github.com/leisurelicht/wtfpython-cn) | [Vietnamese Tiếng Việt](https://github.com/vuduclyunitn/wtfptyhon-vi) | [Add translation](https://github.com/satwikkansal/wtfpython/issues/new?title=Add%20translation%20for%20[LANGUAGE]&body=Expected%20time%20to%20finish:%20[X]%20weeks.%20I%27ll%20start%20working%20on%20it%20from%20[Y].)
Other modes: [Interactive](https://colab.research.google.com/github/satwikkansal/wtfpython/blob/master/irrelevant/wtf.ipynb) | [CLI](https://pypi.python.org/pypi/wtfpython)
Translations: [Chinese 中文](https://github.com/leisurelicht/wtfpython-cn) | [Vietnamese Tiếng Việt](https://github.com/vuduclyunitn/wtfptyhon-vi) | [Spanish Español](https://web.archive.org/web/20220511161045/https://github.com/JoseDeFreitas/wtfpython-es) | [Korean 한국어](https://github.com/buttercrab/wtfpython-ko) | [Russian Русский](https://github.com/satwikkansal/wtfpython/tree/master/translations/ru-russian) | [German Deutsch](https://github.com/BenSt099/wtfpython) | [Add translation](https://github.com/satwikkansal/wtfpython/issues/new?title=Add%20translation%20for%20[LANGUAGE]&body=Expected%20time%20to%20finish:%20[X]%20weeks.%20I%27ll%20start%20working%20on%20it%20from%20[Y].)
Other modes: [Interactive Website](https://wtfpython-interactive.vercel.app) | [Interactive Notebook](https://colab.research.google.com/github/satwikkansal/wtfpython/blob/master/irrelevant/wtf.ipynb)
Python, being a beautifully designed high-level and interpreter-based programming language, provides us with many features for the programmer's comfort. But sometimes, the outcomes of a Python snippet may not seem obvious at first sight.
@ -41,7 +48,7 @@ So, here we go...
+ [ Evaluation time discrepancy](#-evaluation-time-discrepancy)
+ [ `is not ...` is not `is (not ...)`](#-is-not--is-not-is-not-)
+ [ A tic-tac-toe where X wins in the first attempt!](#-a-tic-tac-toe-where-x-wins-in-the-first-attempt)
+ [ The sticky output function](#-the-sticky-output-function)
+ [ Schrödinger's variable](#-schrödingers-variable-)
+ [ The chicken-egg problem *](#-the-chicken-egg-problem-)
+ [ Subclass relationships](#-subclass-relationships)
+ [ Methods equality and identity](#-methods-equality-and-identity)
@ -59,6 +66,7 @@ So, here we go...
+ [ The disappearing variable from outer scope](#-the-disappearing-variable-from-outer-scope)
+ [ The mysterious key type conversion](#-the-mysterious-key-type-conversion)
+ [ Let's see if you can guess this?](#-lets-see-if-you-can-guess-this)
+ [ Exceeds the limit for integer string conversion](#-exceeds-the-limit-for-integer-string-conversion)
* [Section: Slippery Slopes](#section-slippery-slopes)
+ [ Modifying a dictionary while iterating over it](#-modifying-a-dictionary-while-iterating-over-it)
+ [ Stubborn `del` operation](#-stubborn-del-operation)
@ -70,6 +78,7 @@ So, here we go...
+ [ Catching the Exceptions](#-catching-the-exceptions)
+ [ Same operands, different story!](#-same-operands-different-story)
+ [ Name resolution ignoring class scope](#-name-resolution-ignoring-class-scope)
+ [ Rounding like a banker *](#-rounding-like-a-banker-)
+ [ Needles in a Haystack *](#-needles-in-a-haystack-)
+ [ Splitsies *](#-splitsies-)
+ [ Wild imports *](#-wild-imports-)
@ -141,7 +150,7 @@ All the examples are structured like below:
# Usage
A nice way to get the most out of these examples, in my opinion, is to read them chronologically, and for every example:
A nice way to get the most out of these examples, in my opinion, is to read them in sequential order, and for every example:
- Carefully read the initial code for setting up the example. If you're an experienced Python programmer, you'll successfully anticipate what's going to happen next most of the time.
- Read the output snippets and,
+ Check if the outputs are the same as you'd expect.
@ -149,11 +158,6 @@ A nice way to get the most out of these examples, in my opinion, is to read them
- If the answer is no (which is perfectly okay), take a deep breath, and read the explanation (and if you still don't understand, shout out! and create an issue [here](https://github.com/satwikkansal/wtfpython/issues/new)).
- If yes, give a gentle pat on your back, and you may skip to the next example.
PS: You can also read WTFPython at the command line using the [pypi package](https://pypi.python.org/pypi/wtfpython),
```sh
$ pip install wtfpython -U
$ wtfpython
```
---
# 👀 Examples
@ -207,7 +211,7 @@ SyntaxError: invalid syntax
(6, 9)
>>> (a, b = 16, 19) # Oops
File "<stdin>", line 1
(a, b = 6, 9)
(a, b = 16, 19)
^
SyntaxError: invalid syntax
@ -349,7 +353,14 @@ Makes sense, right?
* All length 0 and length 1 strings are interned.
* Strings are interned at compile time (`'wtf'` will be interned but `''.join(['w', 't', 'f'])` will not be interned)
* Strings that are not composed of ASCII letters, digits or underscores, are not interned. This explains why `'wtf!'` was not interned due to `!`. CPython implementation of this rule can be found [here](https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19)
![image](/images/string-intern/string_intern.png)
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="/images/string-intern/string_interning_dark_theme.svg">
<source media="(prefers-color-scheme: light)" srcset="/images/string-intern/string_interning.svg">
<img alt="Shows a string interning process." src="/images/string-intern/string_interning.svg">
</picture>
</p>
+ When `a` and `b` are set to `"wtf!"` in the same line, the Python interpreter creates a new object, then references the second variable at the same time. If you do it on separate lines, it doesn't "know" that there's already `"wtf!"` as an object (because `"wtf!"` is not implicitly interned as per the facts mentioned above). It's a compile-time optimization. This optimization doesn't apply to 3.7.x versions of CPython (check this [issue](https://github.com/satwikkansal/wtfpython/issues/100) for more discussion).
+ A compile unit in an interactive environment like IPython consists of a single statement, whereas it consists of the entire module in case of modules. `a, b = "wtf!", "wtf!"` is single statement, whereas `a = "wtf!"; b = "wtf!"` are two statements in a single line. This explains why the identities are different in `a = "wtf!"; b = "wtf!"`, and also explain why they are same when invoked in `some_file.py`
+ The abrupt change in the output of the fourth snippet is due to a [peephole optimization](https://en.wikipedia.org/wiki/Peephole_optimization) technique known as Constant folding. This means the expression `'a'*20` is replaced by `'aaaaaaaaaaaaaaaaaaaa'` during compilation to save a few clock cycles during runtime. Constant folding only occurs for strings having a length of less than 21. (Why? Imagine the size of `.pyc` file generated as a result of the expression `'a'*10**10`). [Here's](https://github.com/python/cpython/blob/3.6/Python/peephole.c#L288) the implementation source for the same.
@ -383,15 +394,15 @@ False
#### 💡 Explanation:
As per https://docs.python.org/3/reference/expressions.html#membership-test-operations
As per https://docs.python.org/3/reference/expressions.html#comparisons
> Formally, if a, b, c, ..., y, z are expressions and op1, op2, ..., opN are comparison operators, then a op1 b op2 c ... y opN z is equivalent to a op1 b and b op2 c and ... y opN z, except that each expression is evaluated at most once.
While such behavior might seem silly to you in the above examples, it's fantastic with stuff like `a == b == c` and `0 <= x <= 100`.
* `False is False is False` is equivalent to `(False is False) and (False is False)`
* `True is False == False` is equivalent to `True is False and False == False` and since the first part of the statement (`True is False`) evaluates to `False`, the overall expression evaluates to `False`.
* `1 > 0 < 1` is equivalent to `1 > 0 and 0 < 1` which evaluates to `True`.
* `True is False == False` is equivalent to `(True is False) and (False == False)` and since the first part of the statement (`True is False`) evaluates to `False`, the overall expression evaluates to `False`.
* `1 > 0 < 1` is equivalent to `(1 > 0) and (0 < 1)` which evaluates to `True`.
* The expression `(1 > 0) < 1` is equivalent to `True < 1` and
```py
>>> int(True)
@ -448,7 +459,7 @@ True
```py
>>> a, b = 257, 257
>> a is b
>>> a is b
False
```
@ -618,7 +629,7 @@ True
* When `id` was called, Python created a `WTF` class object and passed it to the `id` function. The `id` function takes its `id` (its memory location), and throws away the object. The object is destroyed.
* When we do this twice in succession, Python allocates the same memory location to this second object as well. Since (in CPython) `id` uses the memory location as the object id, the id of the two objects is the same.
* So, the object's id is unique only for the lifetime of the object. After the object is destroyed, or before it is created, something else can have the same id.
* But why did the `is` operator evaluated to `False`? Let's see with this snippet.
* But why did the `is` operator evaluate to `False`? Let's see with this snippet.
```py
class WTF(object):
def __init__(self): print("I")
@ -916,9 +927,9 @@ array_4 = [400, 500, 600]
- In a [generator](https://wiki.python.org/moin/Generators) expression, the `in` clause is evaluated at declaration time, but the conditional clause is evaluated at runtime.
- So before runtime, `array` is re-assigned to the list `[2, 8, 22]`, and since out of `1`, `8` and `15`, only the count of `8` is greater than `0`, the generator only yields `8`.
- The differences in the output of `g1` and `g2` in the second part is due the way variables `array_1` and `array_2` are re-assigned values.
- In the first case, `array_1` is binded to the new object `[1,2,3,4,5]` and since the `in` clause is evaluated at the declaration time it still refers to the old object `[1,2,3,4]` (which is not destroyed).
- In the first case, `array_1` is bound to the new object `[1,2,3,4,5]` and since the `in` clause is evaluated at the declaration time it still refers to the old object `[1,2,3,4]` (which is not destroyed).
- In the second case, the slice assignment to `array_2` updates the same old object `[1,2,3,4]` to `[1,2,3,4,5]`. Hence both the `g2` and `array_2` still have reference to the same object (which has now been updated to `[1,2,3,4,5]`).
- Okay, going by the logic discussed so far, shouldn't be the value of `list(g)` in the third snippet be `[11, 21, 31, 12, 22, 32, 13, 23, 33]`? (because `array_3` and `array_4` are going to behave just like `array_1`). The reason why (only) `array_4` values got updated is explained in [PEP-289](https://www.python.org/dev/peps/pep-0289/#the-details)
- Okay, going by the logic discussed so far, shouldn't be the value of `list(gen)` in the third snippet be `[11, 21, 31, 12, 22, 32, 13, 23, 33]`? (because `array_3` and `array_4` are going to behave just like `array_1`). The reason why (only) `array_4` values got updated is explained in [PEP-289](https://www.python.org/dev/peps/pep-0289/#the-details)
> Only the outermost for-expression is evaluated immediately, the other expressions are deferred until the generator is run.
@ -972,11 +983,23 @@ We didn't assign three `"X"`s, did we?
When we initialize `row` variable, this visualization explains what happens in the memory
![image](/images/tic-tac-toe/after_row_initialized.png)
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="/images/tic-tac-toe/after_row_initialized_dark_theme.svg">
<source media="(prefers-color-scheme: light)" srcset="/images/tic-tac-toe/after_row_initialized.svg">
<img alt="Shows a memory segment after row is initialized." src="/images/tic-tac-toe/after_row_initialized.svg">
</picture>
</p>
And when the `board` is initialized by multiplying the `row`, this is what happens inside the memory (each of the elements `board[0]`, `board[1]` and `board[2]` is a reference to the same list referred by `row`)
![image](/images/tic-tac-toe/after_board_initialized.png)
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="/images/tic-tac-toe/after_board_initialized_dark_theme.svg">
<source media="(prefers-color-scheme: light)" srcset="/images/tic-tac-toe/after_board_initialized.svg">
<img alt="Shows a memory segment after board is initialized." src="/images/tic-tac-toe/after_board_initialized.svg">
</picture>
</p>
We can avoid this scenario here by not using `row` variable to generate `board`. (Asked in [this](https://github.com/satwikkansal/wtfpython/issues/68) issue).
@ -989,10 +1012,9 @@ We can avoid this scenario here by not using `row` variable to generate `board`.
---
### ▶ The sticky output function
### ▶ Schrödinger's variable *
<!-- Example ID: 4dc42f77-94cb-4eb5-a120-8203d3ed7604 --->
1\.
```py
funcs = []
@ -1006,17 +1028,17 @@ for x in range(7):
funcs_results = [func() for func in funcs]
```
**Output:**
**Output (Python version):**
```py
>>> results
[0, 1, 2, 3, 4, 5, 6]
>>> funcs_results
[6, 6, 6, 6, 6, 6, 6]
```
Even when the values of `x` were different in every iteration prior to appending `some_func` to `funcs`, all the functions return 6.
2\.
The values of `x` were different in every iteration prior to appending `some_func` to `funcs`, but all the functions return 6 when they're evaluated after the loop completes.
2.
```py
>>> powers_of_x = [lambda x: x**i for i in range(10)]
@ -1024,12 +1046,22 @@ Even when the values of `x` were different in every iteration prior to appending
[512, 512, 512, 512, 512, 512, 512, 512, 512, 512]
```
#### 💡 Explanation
#### 💡 Explanation:
* When defining a function inside a loop that uses the loop variable in its body, the loop function's closure is bound to the *variable*, not its *value*. The function looks up `x` in the surrounding context, rather than using the value of `x` at the time the function is created. So all of the functions use the latest value assigned to the variable for computation. We can see that it's using the `x` from the surrounding context (i.e. *not* a local variable) with:
```py
>>> import inspect
>>> inspect.getclosurevars(funcs[0])
ClosureVars(nonlocals={}, globals={'x': 6}, builtins={}, unbound=set())
```
Since `x` is a global value, we can change the value that the `funcs` will lookup and return by updating `x`:
- When defining a function inside a loop that uses the loop variable in its body, the loop function's closure is bound to the variable, not its value. So all of the functions use the latest value assigned to the variable for computation.
```py
>>> x = 42
>>> [func() for func in funcs]
[42, 42, 42, 42, 42, 42, 42]
```
- To get the desired behavior you can pass in the loop variable as a named variable to the function. **Why does this work?** Because this will define the variable
within the function's scope.
* To get the desired behavior you can pass in the loop variable as a named variable to the function. **Why does this work?** Because this will define the variable *inside* the function's scope. It will no longer go to the surrounding (global) scope to look up the variables value but will create a local variable that stores the value of `x` at that point in time.
```py
funcs = []
@ -1040,12 +1072,20 @@ within the function's scope.
```
**Output:**
```py
>>> funcs_results = [func() for func in funcs]
>>> funcs_results
[0, 1, 2, 3, 4, 5, 6]
```
It is not longer using the `x` in the global scope:
```py
>>> inspect.getclosurevars(funcs[0])
ClosureVars(nonlocals={}, globals={}, builtins={}, unbound=set())
```
---
### ▶ The chicken-egg problem *
@ -1102,7 +1142,7 @@ False
<!-- Example ID: 9f6d8cf0-e1b5-42d0-84a0-4cfab25a0bc0 --->
**Output:**
```py
>>> from collections import Hashable
>>> from collections.abc import Hashable
>>> issubclass(list, object)
True
>>> issubclass(object, Hashable)
@ -1256,8 +1296,8 @@ Why's this True-False alteration?
```
- `all([])` returns `True` since the iterable is empty.
- `all([[]])` returns `False` because `not []` is `True` is equivalent to `not False` as the list inside the iterable is empty.
- `all([[[]]])` and higher recursive variants are always `True` since `not [[]]`, `not [[[]]]`, and so on are equivalent to `not True`.
- `all([[]])` returns `False` because the passed array has one element, `[]`, and in python, an empty list is falsy.
- `all([[[]]])` and higher recursive variants are always `True`. This is because the passed array's single element (`[[...]]`) is no longer empty, and lists with values are truthy.
---
@ -1324,7 +1364,7 @@ True
```py
>>> r'wt\"f' == 'wt\\"f'
True
>>> print(repr(r'wt\"f')
>>> print(repr(r'wt\"f'))
'wt\\"f'
>>> print("\n")
@ -1957,9 +1997,45 @@ a, b = a[b] = {}, 5
True
```
---
### ▶ Exceeds the limit for integer string conversion
```py
>>> # Python 3.10.6
>>> int("2" * 5432)
>>> # Python 3.10.8
>>> int("2" * 5432)
```
**Output:**
```py
>>> # Python 3.10.6
222222222222222222222222222222222222222222222222222222222222222...
>>> # Python 3.10.8
Traceback (most recent call last):
...
ValueError: Exceeds the limit (4300) for integer string conversion:
value has 5432 digits; use sys.set_int_max_str_digits()
to increase the limit.
```
#### 💡 Explanation:
This call to `int()` works fine in Python 3.10.6 and raises a ValueError in Python 3.10.8. Note that Python can still work with large integers. The error is only raised when converting between integers and strings.
Fortunately, you can increase the limit for the allowed number of digits when you expect an operation to exceed it. To do this, you can use one of the following:
- The -X int_max_str_digits command-line flag
- The set_int_max_str_digits() function from the sys module
- The PYTHONINTMAXSTRDIGITS environment variable
[Check the documentation](https://docs.python.org/3/library/stdtypes.html#int-max-str-digits) for more details on changing the default limit if you expect your code to exceed this value.
---
## Section: Slippery Slopes
### ▶ Modifying a dictionary while iterating over it
@ -2118,7 +2194,7 @@ UnboundLocalError: local variable 'a' referenced before assignment
>>> another_func()
2
```
* The keywords `global` and `nonlocal` tell the python interpreter to not delcare new variables and look them up in the corresponding outer scopes.
* The keywords `global` and `nonlocal` tell the python interpreter to not declare new variables and look them up in the corresponding outer scopes.
* Read [this](https://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html) short but an awesome guide to learn more about how namespaces and scope resolution works in Python.
---
@ -2515,6 +2591,56 @@ class SomeClass:
---
### ▶ Rounding like a banker *
Let's implement a naive function to get the middle element of a list:
```py
def get_middle(some_list):
mid_index = round(len(some_list) / 2)
return some_list[mid_index - 1]
```
**Python 3.x:**
```py
>>> get_middle([1]) # looks good
1
>>> get_middle([1,2,3]) # looks good
2
>>> get_middle([1,2,3,4,5]) # huh?
2
>>> len([1,2,3,4,5]) / 2 # good
2.5
>>> round(len([1,2,3,4,5]) / 2) # why?
2
```
It seems as though Python rounded 2.5 to 2.
#### 💡 Explanation:
- This is not a float precision error, in fact, this behavior is intentional. Since Python 3.0, `round()` uses [banker's rounding](https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even) where .5 fractions are rounded to the nearest **even** number:
```py
>>> round(0.5)
0
>>> round(1.5)
2
>>> round(2.5)
2
>>> import numpy # numpy does the same
>>> numpy.round(0.5)
0.0
>>> numpy.round(1.5)
2.0
>>> numpy.round(2.5)
2.0
```
- This is the recommended way to round .5 fractions as described in [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules). However, the other way (round away from zero) is taught in school most of the time, so banker's rounding is likely not that well known. Furthermore, some of the most popular programming languages (for example: JavaScript, Java, C/C++, Ruby, Rust) do not use banker's rounding either. Therefore, this is still quite special to Python and may result in confusion when rounding fractions.
- See the [round() docs](https://docs.python.org/3/library/functions.html#round) or [this stackoverflow thread](https://stackoverflow.com/questions/10825926/python-3-x-rounding-behavior) for more information.
- Note that `get_middle([1])` only returned 1 because the index was `round(0.5) - 1 = 0 - 1 = -1`, returning the last element in the list.
---
### ▶ Needles in a Haystack *
<!-- Example ID: 52a199b1-989a-4b28-8910-dff562cebba9 --->
@ -2685,7 +2811,7 @@ def similar_recursive_func(a):
* As for the fifth snippet, most methods that modify the items of sequence/mapping objects like `list.append`, `dict.update`, `list.sort`, etc. modify the objects in-place and return `None`. The rationale behind this is to improve performance by avoiding making a copy of the object if the operation can be done in-place (Referred from [here](https://docs.python.org/3/faq/design.html#why-doesn-t-list-sort-return-the-sorted-list)).
* Last one should be fairly obvious, mutable object (like `list`) can be altered in the function, and the reassignation of an immutable (`a -= 1`) is not an alteration of the value.
* Last one should be fairly obvious, mutable object (like `list`) can be altered in the function, and the reassignment of an immutable (`a -= 1`) is not an alteration of the value.
* Being aware of these nitpicks can save you hours of debugging effort in the long run.
@ -3097,7 +3223,7 @@ Ellipsis
>>> ...
Ellipsis
```
- Eliipsis can be used for several purposes,
- Ellipsis can be used for several purposes,
+ As a placeholder for code that hasn't been written yet (just like `pass` statement)
+ In slicing syntax to represent the full slices in remaining direction
```py
@ -3542,7 +3668,7 @@ What makes those dictionaries become bloated? And why are newly created objects
+ CPython is able to reuse the same "keys" object in multiple dictionaries. This was added in [PEP 412](https://www.python.org/dev/peps/pep-0412/) with the motivation to reduce memory usage, specifically in dictionaries of instances - where keys (instance attributes) tend to be common to all instances.
+ This optimization is entirely seamless for instance dictionaries, but it is disabled if certain assumptions are broken.
+ Key-sharing dictionaries do not support deletion; if an instance attribute is deleted, the dictionary is "unshared", and key-sharing is disabled for all future instances of the same class.
+ Additionaly, if the dictionary keys have be resized (because new keys are inserted), they are kept shared *only* if they are used by a exactly single dictionary (this allows adding many attributes in the `__init__` of the very first created instance, without causing an "unshare"). If multiple instances exist when a resize happens, key-sharing is disabled for all future instances of the same class: CPython can't tell if your instances are using the same set of attributes anymore, and decides to bail out on attempting to share their keys.
+ Additionally, if the dictionary keys have been resized (because new keys are inserted), they are kept shared *only* if they are used by a exactly single dictionary (this allows adding many attributes in the `__init__` of the very first created instance, without causing an "unshare"). If multiple instances exist when a resize happens, key-sharing is disabled for all future instances of the same class: CPython can't tell if your instances are using the same set of attributes anymore, and decides to bail out on attempting to share their keys.
+ A small tip, if you aim to lower your program's memory footprint: don't delete instance attributes, and make sure to initialize all attributes in your `__init__`!
@ -3554,7 +3680,7 @@ What makes those dictionaries become bloated? And why are newly created objects
* Few weird looking but semantically correct statements:
+ `[] = ()` is a semantically correct statement (unpacking an empty `tuple` into an empty `list`)
+ `'a'[0][0][0][0][0]` is also a semantically correct statement as strings are [sequences](https://docs.python.org/3/glossary.html#term-sequence)(iterables supporting element access using integer indices) in Python.
+ `'a'[0][0][0][0][0]` is also semantically correct, because Python doesn't have a character data type like other languages branched from C. So selecting a single character from a string returns a single-character string.
+ `3 --0-- 5 == 8` and `--5 == 5` are both semantically correct statements and evaluate to `True`.
* Given that `a` is a number, `++a` and `--a` are both valid Python statements but don't behave the same way as compared with similar statements in languages like C, C++, or Java.
@ -3717,7 +3843,6 @@ The idea and design for this collection were initially inspired by Denys Dovhan'
* https://stackoverflow.com/questions/1011431/common-pitfalls-in-python
* https://www.python.org/doc/humor/
* https://github.com/cosmologicon/pywat#the-undocumented-converse-implication-operator
* https://www.codementor.io/satwikkansal/python-practices-for-efficient-code-performance-memory-and-usability-aze6oiq65
* https://github.com/wemake-services/wemake-python-styleguide/search?q=wtfpython&type=Issues
* WFTPython discussion threads on [Hacker News](https://news.ycombinator.com/item?id=21862073) and [Reddit](https://www.reddit.com/r/programming/comments/edsh3q/what_the_fck_python_30_exploring_and/).
@ -3738,7 +3863,7 @@ If you like wtfpython, you can use these quick links to share it with your frien
## Need a pdf version?
I've received a few requests for the pdf (and epub) version of wtfpython. You can add your details [here](https://satwikkansal.xyz/wtfpython-pdf/) to get them as soon as they are finished.
I've received a few requests for the pdf (and epub) version of wtfpython. You can add your details [here](https://form.jotform.com/221593245656057) to get them as soon as they are finished.
**That's all folks!** For upcoming content like this, you can add your email [here](https://www.satwikkansal.xyz/content-like-wtfpython/).
**That's all folks!** For upcoming content like this, you can add your email [here](https://form.jotform.com/221593598380062).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

BIN
images/logo.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

38
images/logo.svg vendored Executable file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400px" height="300px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
<g><path style="opacity:0.534" fill="#000000" d="M 93.5,49.5 C 106.479,48.4209 118.479,51.2543 129.5,58C 151.339,72.4912 157.172,91.9912 147,116.5C 137.557,132.756 123.391,141.423 104.5,142.5C 104.669,147.181 105.002,151.848 105.5,156.5C 109.607,156.925 113.274,158.425 116.5,161C 121.053,166.43 126.053,171.43 131.5,176C 138.937,179.109 146.604,181.442 154.5,183C 145.628,183.366 137.294,181.366 129.5,177C 124.5,172 119.5,167 114.5,162C 111.852,159.95 108.852,158.784 105.5,158.5C 105.714,175.884 104.881,193.217 103,210.5C 88.7522,229.986 75.7522,250.319 64,271.5C 63.1072,272.711 62.2739,272.711 61.5,271.5C 73.4183,249.987 86.585,229.32 101,209.5C 102.454,195.86 103.62,182.193 104.5,168.5C 103.868,164.183 103.368,159.85 103,155.5C 92.0497,160.785 81.8831,167.285 72.5,175C 67.7905,182.253 62.9572,189.42 58,196.5C 57.5,196 57,195.5 56.5,195C 61.2528,187.493 66.2528,180.16 71.5,173C 80.7973,165.048 91.1306,158.715 102.5,154C 103.803,150.532 103.803,147.032 102.5,143.5C 69.2933,139.465 53.7933,120.798 56,87.5C 60.0825,66.2519 72.5825,53.5853 93.5,49.5 Z M 87.5,53.5 C 82.3351,57.5863 76.6685,60.9196 70.5,63.5C 74.752,57.8701 80.4187,54.5368 87.5,53.5 Z M 92.5,54.5 C 135.035,52.8481 151.202,72.5148 141,113.5C 134.7,128.967 123.2,136.634 106.5,136.5C 64.7957,133.711 50.629,112.711 64,73.5C 65.4578,71.04 67.2911,68.8734 69.5,67C 77.2602,62.7905 84.9269,58.6238 92.5,54.5 Z M 92.5,64.5 C 106.636,61.5508 114.969,67.0508 117.5,81C 115.943,91.5504 109.776,96.7171 99,96.5C 97.8468,99.7111 97.1802,103.044 97,106.5C 94.6194,105.565 92.1194,105.232 89.5,105.5C 85.8309,91.9324 90.8309,85.4324 104.5,86C 108.876,72.8768 104.543,68.7101 91.5,73.5C 87.2971,69.7273 87.6304,66.7273 92.5,64.5 Z M 111.5,65.5 C 112.077,64.2267 112.743,64.2267 113.5,65.5C 113.03,66.463 112.363,66.463 111.5,65.5 Z M 114.5,68.5 C 115.497,67.2875 116.497,67.4542 117.5,69C 116.423,69.4696 115.423,69.3029 114.5,68.5 Z M 117.5,70.5 C 119.852,71.5426 120.019,72.8759 118,74.5C 116.666,73.1221 116.499,71.7887 117.5,70.5 Z M 119.5,75.5 C 120.773,76.0768 120.773,76.7435 119.5,77.5C 118.537,77.0302 118.537,76.3635 119.5,75.5 Z M 144.5,75.5 C 146.856,78.7145 148.356,82.3812 149,86.5C 150.768,98.9946 148.434,110.661 142,121.5C 139.91,124.428 137.41,126.761 134.5,128.5C 145.662,112.482 148.995,94.8151 144.5,75.5 Z M 118.5,79.5 C 120.337,79.6395 120.67,80.3061 119.5,81.5C 118.702,81.0431 118.369,80.3764 118.5,79.5 Z M 100.5,101.5 C 100.783,100.711 101.283,100.044 102,99.5C 102.528,100.816 102.028,101.483 100.5,101.5 Z M 101.5,104.5 C 100.923,105.773 100.257,105.773 99.5,104.5C 99.9698,103.537 100.637,103.537 101.5,104.5 Z M 96.5,112.5 C 101.732,113.702 102.898,116.702 100,121.5C 97.4406,124.349 94.2739,125.183 90.5,124C 87.2091,121.668 86.7091,118.835 89,115.5C 90,114.167 91,114.167 92,115.5C 93.4087,114.219 94.9087,113.219 96.5,112.5 Z M 73.5,130.5 C 87.7227,137.443 102.723,139.943 118.5,138C 105.586,141.789 92.9193,141.123 80.5,136C 77.7339,134.629 75.4006,132.796 73.5,130.5 Z"/></g>
<g><path style="opacity:0.547" fill="#000000" d="M 99.5,59.5 C 118.613,60.4501 125.446,70.1167 120,88.5C 116.128,93.0516 111.295,95.885 105.5,97C 104.851,100.195 104.018,103.361 103,106.5C 101.806,107.43 100.473,108.097 99,108.5C 95.2825,107.904 91.6158,107.238 88,106.5C 85.4312,99.218 86.2645,92.3846 90.5,86C 94.7594,84.958 99.0928,84.1246 103.5,83.5C 105.947,77.3939 103.947,73.7272 97.5,72.5C 94.9272,73.2525 92.7605,74.5859 91,76.5C 88.6764,73.8629 86.843,70.8629 85.5,67.5C 86.3128,66.1861 87.3128,65.0195 88.5,64C 92.2618,62.5834 95.9285,61.0834 99.5,59.5 Z M 92.5,64.5 C 87.6304,66.7273 87.2971,69.7273 91.5,73.5C 104.543,68.7101 108.876,72.8768 104.5,86C 90.8309,85.4324 85.8309,91.9324 89.5,105.5C 92.1194,105.232 94.6194,105.565 97,106.5C 97.1802,103.044 97.8468,99.7111 99,96.5C 109.776,96.7171 115.943,91.5504 117.5,81C 114.969,67.0508 106.636,61.5508 92.5,64.5 Z M 111.5,65.5 C 112.363,66.463 113.03,66.463 113.5,65.5C 112.743,64.2267 112.077,64.2267 111.5,65.5 Z M 114.5,68.5 C 115.423,69.3029 116.423,69.4696 117.5,69C 116.497,67.4542 115.497,67.2875 114.5,68.5 Z M 117.5,70.5 C 116.499,71.7887 116.666,73.1221 118,74.5C 120.019,72.8759 119.852,71.5426 117.5,70.5 Z M 119.5,75.5 C 118.537,76.3635 118.537,77.0302 119.5,77.5C 120.773,76.7435 120.773,76.0768 119.5,75.5 Z M 118.5,79.5 C 118.369,80.3764 118.702,81.0431 119.5,81.5C 120.67,80.3061 120.337,79.6395 118.5,79.5 Z M 100.5,101.5 C 102.028,101.483 102.528,100.816 102,99.5C 101.283,100.044 100.783,100.711 100.5,101.5 Z M 101.5,104.5 C 100.637,103.537 99.9698,103.537 99.5,104.5C 100.257,105.773 100.923,105.773 101.5,104.5 Z"/></g>
<g><path style="opacity:0.565" fill="#000000" d="M 201.5,84.5 C 230.503,85.6463 259.503,85.6463 288.5,84.5C 294.507,84.9098 300.507,85.4098 306.5,86C 306.887,100.522 307.554,115.189 308.5,130C 308.109,140.236 307.109,150.403 305.5,160.5C 321.506,157.534 335.006,161.867 346,173.5C 354.246,186.356 352.08,197.19 339.5,206C 331.632,208.547 324.799,212.714 319,218.5C 318,221.167 317,223.833 316,226.5C 313.343,227.573 311.177,229.24 309.5,231.5C 311.422,232.711 313.255,234.044 315,235.5C 315.667,237.167 315.667,238.833 315,240.5C 310.425,245.746 305.258,250.246 299.5,254C 294.97,254.947 290.636,254.447 286.5,252.5C 284.605,250.133 284.105,247.466 285,244.5C 289.21,235.31 296.376,231.143 306.5,232C 308.392,228.442 311.225,225.942 315,224.5C 315.389,219.102 317.889,214.935 322.5,212C 331.254,208.545 339.088,203.712 346,197.5C 351.72,185.315 348.886,175.482 337.5,168C 327.484,162.386 316.818,160.553 305.5,162.5C 306.834,169.656 304.5,175.156 298.5,179C 285.181,180.07 271.847,180.904 258.5,181.5C 242.793,180.438 227.127,178.938 211.5,177C 200.505,176.5 189.505,176.333 178.5,176.5C 177.393,148.181 177.227,119.848 178,91.5C 178.374,90.5838 178.874,89.7504 179.5,89C 186.877,87.0251 194.211,85.5251 201.5,84.5 Z M 199.5,86.5 C 212.855,86.4009 226.188,86.9009 239.5,88C 223.48,89.8508 207.48,89.8508 191.5,88C 194.365,87.8171 197.031,87.3171 199.5,86.5 Z M 276.5,86.5 C 285.884,86.1841 295.218,86.6841 304.5,88C 302.541,89.0963 300.375,89.5963 298,89.5C 288.51,88.8265 279.01,88.3265 269.5,88C 272.036,87.8138 274.369,87.3138 276.5,86.5 Z M 184.5,89.5 C 193.572,90.7076 202.738,91.3742 212,91.5C 241.518,88.8408 271.018,88.8408 300.5,91.5C 301.659,118.76 301.492,146.426 300,174.5C 299.5,175 299,175.5 298.5,176C 273.182,180.597 247.849,180.597 222.5,176C 208.516,175.001 194.516,174.501 180.5,174.5C 178.703,149.358 178.037,124.191 178.5,99C 178.762,96.4528 179.262,93.9528 180,91.5C 181.622,90.9011 183.122,90.2344 184.5,89.5 Z M 303.5,91.5 C 304.465,92.7211 304.298,94.0544 303,95.5C 302.421,94.0715 302.588,92.7382 303.5,91.5 Z M 240.5,100.5 C 251.838,100.333 263.172,100.5 274.5,101C 277.226,101.182 279.893,101.682 282.5,102.5C 282.754,120.447 283.421,138.447 284.5,156.5C 284.441,158.891 284.107,161.225 283.5,163.5C 273.451,163.351 263.284,163.684 253,164.5C 233.502,163.71 214.002,163.043 194.5,162.5C 193.29,143.18 192.29,123.847 191.5,104.5C 208.032,103.86 224.365,102.527 240.5,100.5 Z M 241.5,107.5 C 244.861,108.203 245.194,109.537 242.5,111.5C 241.571,110.311 241.238,108.978 241.5,107.5 Z M 304.5,111.5 C 305.097,111.735 305.43,112.235 305.5,113C 304.683,114.49 303.85,115.99 303,117.5C 302.591,115.305 303.091,113.305 304.5,111.5 Z M 305.5,116.5 C 306.598,117.601 306.765,118.934 306,120.5C 305,122.167 304,123.833 303,125.5C 303.206,122.394 304.039,119.394 305.5,116.5 Z M 305.5,129.5 C 306.27,132.383 305.437,135.05 303,137.5C 302.333,136.167 302.333,134.833 303,133.5C 304.095,132.307 304.928,130.973 305.5,129.5 Z M 252.5,142.5 C 253.5,142.5 254.5,142.5 255.5,142.5C 255.778,144.346 255.111,145.68 253.5,146.5C 252.571,145.311 252.238,143.978 252.5,142.5 Z M 304.5,147.5 C 305.629,149.666 305.129,151.666 303,153.5C 303.15,151.494 303.65,149.494 304.5,147.5 Z M 296.5,234.5 C 301.511,234.334 306.511,234.501 311.5,235C 313.211,236.133 313.711,237.633 313,239.5C 307.764,248.865 299.93,253.032 289.5,252C 286.797,250.18 285.964,247.68 287,244.5C 289.056,240.008 292.223,236.675 296.5,234.5 Z"/></g>
<g><path style="opacity:0.581" fill="#000000" d="M 258.5,98.5 C 267.212,98.7261 275.879,99.3928 284.5,100.5C 284.977,122.497 285.311,144.497 285.5,166.5C 254.603,165.98 223.77,164.98 193,163.5C 191.215,143.28 190.382,123.114 190.5,103C 213.274,100.85 235.941,99.3501 258.5,98.5 Z M 240.5,100.5 C 224.365,102.527 208.032,103.86 191.5,104.5C 192.29,123.847 193.29,143.18 194.5,162.5C 214.002,163.043 233.502,163.71 253,164.5C 263.284,163.684 273.451,163.351 283.5,163.5C 284.107,161.225 284.441,158.891 284.5,156.5C 283.421,138.447 282.754,120.447 282.5,102.5C 279.893,101.682 277.226,101.182 274.5,101C 263.172,100.5 251.838,100.333 240.5,100.5 Z M 241.5,107.5 C 241.238,108.978 241.571,110.311 242.5,111.5C 245.194,109.537 244.861,108.203 241.5,107.5 Z M 252.5,142.5 C 252.238,143.978 252.571,145.311 253.5,146.5C 255.111,145.68 255.778,144.346 255.5,142.5C 254.5,142.5 253.5,142.5 252.5,142.5 Z"/></g>
<g><path style="opacity:1" fill="#3771a2" d="M 245.5,103.5 C 249.619,103.488 253.452,104.488 257,106.5C 258.563,111.718 258.896,117.051 258,122.5C 257.5,124.333 256.333,125.5 254.5,126C 249.447,126.217 244.447,126.717 239.5,127.5C 238.808,128.025 238.308,128.692 238,129.5C 237.502,132.482 237.335,135.482 237.5,138.5C 234.635,138.945 232.135,138.278 230,136.5C 226.638,129.903 226.804,123.403 230.5,117C 236.419,115.804 242.419,115.138 248.5,115C 245.183,114.502 241.85,114.335 238.5,114.5C 238.336,111.813 238.503,109.146 239,106.5C 241.166,105.269 243.333,104.269 245.5,103.5 Z M 241.5,107.5 C 241.238,108.978 241.571,110.311 242.5,111.5C 245.194,109.537 244.861,108.203 241.5,107.5 Z"/></g>
<g><path style="opacity:0.355" fill="#000000" d="M 197.5,105.5 C 198.289,105.783 198.956,106.283 199.5,107C 195.364,110.545 194.697,110.045 197.5,105.5 Z"/></g>
<g><path style="opacity:0.461" fill="#000000" d="M 200.5,109.5 C 202.028,109.517 202.528,110.184 202,111.5C 200.333,112.833 198.667,114.167 197,115.5C 196.5,115 196,114.5 195.5,114C 197.24,112.483 198.906,110.983 200.5,109.5 Z"/></g>
<g><path style="opacity:0.559" fill="#000000" d="M 91.5,110.5 C 95.717,110.447 100.05,110.947 104.5,112C 108.277,119.115 106.277,123.782 98.5,126C 87.2522,127.947 83.7522,123.781 88,113.5C 89.1451,112.364 90.3117,111.364 91.5,110.5 Z M 96.5,112.5 C 94.9087,113.219 93.4087,114.219 92,115.5C 91,114.167 90,114.167 89,115.5C 86.7091,118.835 87.2091,121.668 90.5,124C 94.2739,125.183 97.4406,124.349 100,121.5C 102.898,116.702 101.732,113.702 96.5,112.5 Z"/></g>
<g><path style="opacity:0.994" fill="#fdd041" d="M 259.5,115.5 C 262.157,115.162 264.49,115.829 266.5,117.5C 272.893,134.625 266.893,141.792 248.5,139C 251.817,139.498 255.15,139.665 258.5,139.5C 259.411,146.925 256.078,150.592 248.5,150.5C 240.385,150.39 237.052,146.39 238.5,138.5C 238.667,135.833 238.833,133.167 239,130.5C 239.833,129.667 240.667,128.833 241.5,128C 246.5,127.667 251.5,127.333 256.5,127C 257.333,126.167 258.167,125.333 259,124.5C 259.498,121.518 259.665,118.518 259.5,115.5 Z M 252.5,142.5 C 252.238,143.978 252.571,145.311 253.5,146.5C 255.111,145.68 255.778,144.346 255.5,142.5C 254.5,142.5 253.5,142.5 252.5,142.5 Z"/></g>
<g><path style="opacity:0.53" fill="#000000" d="M 195.5,194.5 C 226.578,195.56 257.578,197.727 288.5,201C 290.329,201.273 291.829,202.107 293,203.5C 293.695,206.385 294.528,209.218 295.5,212C 291.492,219.977 285.825,226.644 278.5,232C 264.495,231.833 250.495,231.167 236.5,230C 219.234,227.676 201.9,226.01 184.5,225C 181.058,224.573 179.558,222.74 180,219.5C 184.203,210.486 189.37,202.153 195.5,194.5 Z M 196.5,196.5 C 227.585,197.464 258.585,199.63 289.5,203C 291.767,204.081 291.934,205.581 290,207.5C 286.167,211.333 282.333,215.167 278.5,219C 279,219.167 279.5,219.333 280,219.5C 283.934,215.566 287.934,211.566 292,207.5C 292.5,209 293,210.5 293.5,212C 289.644,218.865 284.644,224.865 278.5,230C 247.051,229.389 215.718,227.055 184.5,223C 183.09,222.632 182.09,221.799 181.5,220.5C 186.01,212.136 191.01,204.136 196.5,196.5 Z"/></g>
<g><path style="opacity:0.528" fill="#000000" d="M 202.5,200.5 C 207.244,200.038 208.244,201.538 205.5,205C 203.866,205.494 202.199,205.66 200.5,205.5C 200.365,203.446 201.032,201.779 202.5,200.5 Z"/></g>
<g><path style="opacity:0.501" fill="#000000" d="M 211.5,202.5 C 214.896,202.633 215.229,203.633 212.5,205.5C 213.5,206.167 214.5,206.833 215.5,207.5C 213.136,208.82 211.469,208.154 210.5,205.5C 210.685,204.416 211.018,203.416 211.5,202.5 Z"/></g>
<g><path style="opacity:0.38" fill="#000000" d="M 240.5,204.5 C 242.308,204.491 243.975,204.991 245.5,206C 245,206.5 244.5,207 244,207.5C 242.271,207.026 241.105,206.026 240.5,204.5 Z"/></g>
<g><path style="opacity:0.511" fill="#000000" d="M 253.5,205.5 C 255.264,204.288 256.93,204.621 258.5,206.5C 256.603,207.652 254.936,207.319 253.5,205.5 Z"/></g>
<g><path style="opacity:0.47" fill="#000000" d="M 271.5,205.5 C 274.462,205.117 275.462,206.117 274.5,208.5C 272.787,208.121 271.787,207.121 271.5,205.5 Z"/></g>
<g><path style="opacity:0.519" fill="#000000" d="M 249.5,207.5 C 250.675,207.281 251.675,207.614 252.5,208.5C 250.948,209.798 249.948,209.465 249.5,207.5 Z"/></g>
<g><path style="opacity:0.612" fill="#000000" d="M 279.5,207.5 C 281.167,207.5 282.833,207.5 284.5,207.5C 284.5,208.5 284.5,209.5 284.5,210.5C 282.396,210.799 280.396,210.466 278.5,209.5C 278.863,208.817 279.196,208.15 279.5,207.5 Z"/></g>
<g><path style="opacity:0.561" fill="#000000" d="M 199.5,209.5 C 202.68,209.176 203.847,210.51 203,213.5C 201.301,214.406 199.467,214.739 197.5,214.5C 197.392,212.486 198.058,210.82 199.5,209.5 Z"/></g>
<g><path style="opacity:0.414" fill="#000000" d="M 266.5,209.5 C 267.675,209.281 268.675,209.614 269.5,210.5C 267.948,211.798 266.948,211.465 266.5,209.5 Z"/></g>
<g><path style="opacity:0.57" fill="#000000" d="M 207.5,210.5 C 208.833,210.5 210.167,210.5 211.5,210.5C 211.143,214.395 209.143,215.395 205.5,213.5C 206.193,212.482 206.859,211.482 207.5,210.5 Z"/></g>
<g><path style="opacity:0.482" fill="#000000" d="M 236.5,211.5 C 241.645,212.482 241.812,214.149 237,216.5C 235.941,216.37 235.108,215.87 234.5,215C 235.823,214.184 236.489,213.017 236.5,211.5 Z"/></g>
<g><path style="opacity:0.513" fill="#000000" d="M 108.5,212.5 C 120.3,230.076 130.633,248.743 139.5,268.5C 139.167,268.833 138.833,269.167 138.5,269.5C 128.246,250.659 118.246,231.659 108.5,212.5 Z"/></g>
<g><path style="opacity:0.39" fill="#000000" d="M 219.5,212.5 C 221.549,212.706 221.883,213.539 220.5,215C 219.056,215.781 217.723,215.614 216.5,214.5C 217.602,213.824 218.602,213.158 219.5,212.5 Z"/></g>
<g><path style="opacity:0.435" fill="#000000" d="M 224.5,212.5 C 226.337,212.639 226.67,213.306 225.5,214.5C 224.702,214.043 224.369,213.376 224.5,212.5 Z"/></g>
<g><path style="opacity:0.602" fill="#000000" d="M 193.5,216.5 C 194.833,216.5 196.167,216.5 197.5,216.5C 197.5,217.833 197.5,219.167 197.5,220.5C 195.396,220.799 193.396,220.466 191.5,219.5C 192.193,218.482 192.859,217.482 193.5,216.5 Z"/></g>
<g><path style="opacity:0.453" fill="#000000" d="M 271.5,216.5 C 276.368,217.09 276.034,218.09 270.5,219.5C 269.833,219.167 269.167,218.833 268.5,218.5C 269.602,217.824 270.602,217.158 271.5,216.5 Z"/></g>
<g><path style="opacity:0.505" fill="#000000" d="M 213.5,218.5 C 216.022,218.128 218.022,218.961 219.5,221C 219.167,221.333 218.833,221.667 218.5,222C 214.129,222.828 209.795,222.661 205.5,221.5C 207.766,220.686 210.1,220.186 212.5,220C 213.056,219.617 213.389,219.117 213.5,218.5 Z"/></g>
<g><path style="opacity:0.373" fill="#000000" d="M 223.5,220.5 C 224.978,220.238 226.311,220.571 227.5,221.5C 226.833,221.833 226.167,222.167 225.5,222.5C 224.287,222.253 223.62,221.586 223.5,220.5 Z"/></g>
<g><path style="opacity:0.606" fill="#000000" d="M 255.5,220.5 C 257.288,220.215 258.955,220.548 260.5,221.5C 258.796,223.849 256.463,224.849 253.5,224.5C 253.527,222.801 254.194,221.467 255.5,220.5 Z"/></g>
<g><path style="opacity:0.498" fill="#000000" d="M 244.5,221.5 C 245.675,221.281 246.675,221.614 247.5,222.5C 244.272,225.259 243.272,224.926 244.5,221.5 Z"/></g>
<g><path style="opacity:0.373" fill="#000000" d="M 233.5,222.5 C 234.675,222.281 235.675,222.614 236.5,223.5C 234.948,224.798 233.948,224.465 233.5,222.5 Z"/></g>
<g><path style="opacity:0.512" fill="#000000" d="M 269.5,222.5 C 271.337,222.639 271.67,223.306 270.5,224.5C 265.586,225.869 265.253,225.203 269.5,222.5 Z"/></g>
<g><path style="opacity:0.652" fill="#000000" d="M 296.5,236.5 C 297.978,236.238 299.311,236.571 300.5,237.5C 299.68,239.111 298.346,239.778 296.5,239.5C 296.5,238.5 296.5,237.5 296.5,236.5 Z"/></g>
<g><path style="opacity:0.476" fill="#000000" d="M 309.5,236.5 C 310.289,236.783 310.956,237.283 311.5,238C 306.628,240.039 303.294,243.539 301.5,248.5C 300.686,246.048 301.186,243.715 303,241.5C 305.326,239.934 307.492,238.268 309.5,236.5 Z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

38
images/logo_dark_theme.svg vendored Executable file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400px" height="300px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
<g><path style="opacity:0.534" fill="#fefffe" d="M 93.5,49.5 C 106.479,48.4209 118.479,51.2543 129.5,58C 151.339,72.4912 157.172,91.9912 147,116.5C 137.557,132.756 123.391,141.423 104.5,142.5C 104.669,147.181 105.002,151.848 105.5,156.5C 109.607,156.925 113.274,158.425 116.5,161C 121.053,166.43 126.053,171.43 131.5,176C 138.937,179.109 146.604,181.442 154.5,183C 145.628,183.366 137.294,181.366 129.5,177C 124.5,172 119.5,167 114.5,162C 111.852,159.95 108.852,158.784 105.5,158.5C 105.714,175.884 104.881,193.217 103,210.5C 88.7522,229.986 75.7522,250.319 64,271.5C 63.1072,272.711 62.2739,272.711 61.5,271.5C 73.4183,249.987 86.585,229.32 101,209.5C 102.454,195.86 103.62,182.193 104.5,168.5C 103.868,164.183 103.368,159.85 103,155.5C 92.0497,160.785 81.8831,167.285 72.5,175C 67.7905,182.253 62.9572,189.42 58,196.5C 57.5,196 57,195.5 56.5,195C 61.2528,187.493 66.2528,180.16 71.5,173C 80.7973,165.048 91.1306,158.715 102.5,154C 103.803,150.532 103.803,147.032 102.5,143.5C 69.2933,139.465 53.7933,120.798 56,87.5C 60.0825,66.2519 72.5825,53.5853 93.5,49.5 Z M 87.5,53.5 C 82.3351,57.5863 76.6685,60.9196 70.5,63.5C 74.752,57.8701 80.4187,54.5368 87.5,53.5 Z M 92.5,54.5 C 135.035,52.8481 151.202,72.5148 141,113.5C 134.7,128.967 123.2,136.634 106.5,136.5C 64.7957,133.711 50.629,112.711 64,73.5C 65.4578,71.04 67.2911,68.8734 69.5,67C 77.2602,62.7905 84.9269,58.6238 92.5,54.5 Z M 92.5,64.5 C 106.636,61.5508 114.969,67.0508 117.5,81C 115.943,91.5504 109.776,96.7171 99,96.5C 97.8468,99.7111 97.1802,103.044 97,106.5C 94.6194,105.565 92.1194,105.232 89.5,105.5C 85.8309,91.9324 90.8309,85.4324 104.5,86C 108.876,72.8768 104.543,68.7101 91.5,73.5C 87.2971,69.7273 87.6304,66.7273 92.5,64.5 Z M 111.5,65.5 C 112.077,64.2267 112.743,64.2267 113.5,65.5C 113.03,66.463 112.363,66.463 111.5,65.5 Z M 114.5,68.5 C 115.497,67.2875 116.497,67.4542 117.5,69C 116.423,69.4696 115.423,69.3029 114.5,68.5 Z M 117.5,70.5 C 119.852,71.5426 120.019,72.8759 118,74.5C 116.666,73.1221 116.499,71.7887 117.5,70.5 Z M 119.5,75.5 C 120.773,76.0768 120.773,76.7435 119.5,77.5C 118.537,77.0302 118.537,76.3635 119.5,75.5 Z M 144.5,75.5 C 146.856,78.7145 148.356,82.3812 149,86.5C 150.768,98.9946 148.434,110.661 142,121.5C 139.91,124.428 137.41,126.761 134.5,128.5C 145.662,112.482 148.995,94.8151 144.5,75.5 Z M 118.5,79.5 C 120.337,79.6395 120.67,80.3061 119.5,81.5C 118.702,81.0431 118.369,80.3764 118.5,79.5 Z M 100.5,101.5 C 100.783,100.711 101.283,100.044 102,99.5C 102.528,100.816 102.028,101.483 100.5,101.5 Z M 101.5,104.5 C 100.923,105.773 100.257,105.773 99.5,104.5C 99.9698,103.537 100.637,103.537 101.5,104.5 Z M 96.5,112.5 C 101.732,113.702 102.898,116.702 100,121.5C 97.4406,124.349 94.2739,125.183 90.5,124C 87.2091,121.668 86.7091,118.835 89,115.5C 90,114.167 91,114.167 92,115.5C 93.4087,114.219 94.9087,113.219 96.5,112.5 Z M 73.5,130.5 C 87.7227,137.443 102.723,139.943 118.5,138C 105.586,141.789 92.9193,141.123 80.5,136C 77.7339,134.629 75.4006,132.796 73.5,130.5 Z"/></g>
<g><path style="opacity:0.547" fill="#fefffe" d="M 99.5,59.5 C 118.613,60.4501 125.446,70.1167 120,88.5C 116.128,93.0516 111.295,95.885 105.5,97C 104.851,100.195 104.018,103.361 103,106.5C 101.806,107.43 100.473,108.097 99,108.5C 95.2825,107.904 91.6158,107.238 88,106.5C 85.4312,99.218 86.2645,92.3846 90.5,86C 94.7594,84.958 99.0928,84.1246 103.5,83.5C 105.947,77.3939 103.947,73.7272 97.5,72.5C 94.9272,73.2525 92.7605,74.5859 91,76.5C 88.6764,73.8629 86.843,70.8629 85.5,67.5C 86.3128,66.1861 87.3128,65.0195 88.5,64C 92.2618,62.5834 95.9285,61.0834 99.5,59.5 Z M 92.5,64.5 C 87.6304,66.7273 87.2971,69.7273 91.5,73.5C 104.543,68.7101 108.876,72.8768 104.5,86C 90.8309,85.4324 85.8309,91.9324 89.5,105.5C 92.1194,105.232 94.6194,105.565 97,106.5C 97.1802,103.044 97.8468,99.7111 99,96.5C 109.776,96.7171 115.943,91.5504 117.5,81C 114.969,67.0508 106.636,61.5508 92.5,64.5 Z M 111.5,65.5 C 112.363,66.463 113.03,66.463 113.5,65.5C 112.743,64.2267 112.077,64.2267 111.5,65.5 Z M 114.5,68.5 C 115.423,69.3029 116.423,69.4696 117.5,69C 116.497,67.4542 115.497,67.2875 114.5,68.5 Z M 117.5,70.5 C 116.499,71.7887 116.666,73.1221 118,74.5C 120.019,72.8759 119.852,71.5426 117.5,70.5 Z M 119.5,75.5 C 118.537,76.3635 118.537,77.0302 119.5,77.5C 120.773,76.7435 120.773,76.0768 119.5,75.5 Z M 118.5,79.5 C 118.369,80.3764 118.702,81.0431 119.5,81.5C 120.67,80.3061 120.337,79.6395 118.5,79.5 Z M 100.5,101.5 C 102.028,101.483 102.528,100.816 102,99.5C 101.283,100.044 100.783,100.711 100.5,101.5 Z M 101.5,104.5 C 100.637,103.537 99.9698,103.537 99.5,104.5C 100.257,105.773 100.923,105.773 101.5,104.5 Z"/></g>
<g><path style="opacity:0.565" fill="#fefffe" d="M 201.5,84.5 C 230.503,85.6463 259.503,85.6463 288.5,84.5C 294.507,84.9098 300.507,85.4098 306.5,86C 306.887,100.522 307.554,115.189 308.5,130C 308.109,140.236 307.109,150.403 305.5,160.5C 321.506,157.534 335.006,161.867 346,173.5C 354.246,186.356 352.08,197.19 339.5,206C 331.632,208.547 324.799,212.714 319,218.5C 318,221.167 317,223.833 316,226.5C 313.343,227.573 311.177,229.24 309.5,231.5C 311.422,232.711 313.255,234.044 315,235.5C 315.667,237.167 315.667,238.833 315,240.5C 310.425,245.746 305.258,250.246 299.5,254C 294.97,254.947 290.636,254.447 286.5,252.5C 284.605,250.133 284.105,247.466 285,244.5C 289.21,235.31 296.376,231.143 306.5,232C 308.392,228.442 311.225,225.942 315,224.5C 315.389,219.102 317.889,214.935 322.5,212C 331.254,208.545 339.088,203.712 346,197.5C 351.72,185.315 348.886,175.482 337.5,168C 327.484,162.386 316.818,160.553 305.5,162.5C 306.834,169.656 304.5,175.156 298.5,179C 285.181,180.07 271.847,180.904 258.5,181.5C 242.793,180.438 227.127,178.938 211.5,177C 200.505,176.5 189.505,176.333 178.5,176.5C 177.393,148.181 177.227,119.848 178,91.5C 178.374,90.5838 178.874,89.7504 179.5,89C 186.877,87.0251 194.211,85.5251 201.5,84.5 Z M 199.5,86.5 C 212.855,86.4009 226.188,86.9009 239.5,88C 223.48,89.8508 207.48,89.8508 191.5,88C 194.365,87.8171 197.031,87.3171 199.5,86.5 Z M 276.5,86.5 C 285.884,86.1841 295.218,86.6841 304.5,88C 302.541,89.0963 300.375,89.5963 298,89.5C 288.51,88.8265 279.01,88.3265 269.5,88C 272.036,87.8138 274.369,87.3138 276.5,86.5 Z M 184.5,89.5 C 193.572,90.7076 202.738,91.3742 212,91.5C 241.518,88.8408 271.018,88.8408 300.5,91.5C 301.659,118.76 301.492,146.426 300,174.5C 299.5,175 299,175.5 298.5,176C 273.182,180.597 247.849,180.597 222.5,176C 208.516,175.001 194.516,174.501 180.5,174.5C 178.703,149.358 178.037,124.191 178.5,99C 178.762,96.4528 179.262,93.9528 180,91.5C 181.622,90.9011 183.122,90.2344 184.5,89.5 Z M 303.5,91.5 C 304.465,92.7211 304.298,94.0544 303,95.5C 302.421,94.0715 302.588,92.7382 303.5,91.5 Z M 240.5,100.5 C 251.838,100.333 263.172,100.5 274.5,101C 277.226,101.182 279.893,101.682 282.5,102.5C 282.754,120.447 283.421,138.447 284.5,156.5C 284.441,158.891 284.107,161.225 283.5,163.5C 273.451,163.351 263.284,163.684 253,164.5C 233.502,163.71 214.002,163.043 194.5,162.5C 193.29,143.18 192.29,123.847 191.5,104.5C 208.032,103.86 224.365,102.527 240.5,100.5 Z M 241.5,107.5 C 244.861,108.203 245.194,109.537 242.5,111.5C 241.571,110.311 241.238,108.978 241.5,107.5 Z M 304.5,111.5 C 305.097,111.735 305.43,112.235 305.5,113C 304.683,114.49 303.85,115.99 303,117.5C 302.591,115.305 303.091,113.305 304.5,111.5 Z M 305.5,116.5 C 306.598,117.601 306.765,118.934 306,120.5C 305,122.167 304,123.833 303,125.5C 303.206,122.394 304.039,119.394 305.5,116.5 Z M 305.5,129.5 C 306.27,132.383 305.437,135.05 303,137.5C 302.333,136.167 302.333,134.833 303,133.5C 304.095,132.307 304.928,130.973 305.5,129.5 Z M 252.5,142.5 C 253.5,142.5 254.5,142.5 255.5,142.5C 255.778,144.346 255.111,145.68 253.5,146.5C 252.571,145.311 252.238,143.978 252.5,142.5 Z M 304.5,147.5 C 305.629,149.666 305.129,151.666 303,153.5C 303.15,151.494 303.65,149.494 304.5,147.5 Z M 296.5,234.5 C 301.511,234.334 306.511,234.501 311.5,235C 313.211,236.133 313.711,237.633 313,239.5C 307.764,248.865 299.93,253.032 289.5,252C 286.797,250.18 285.964,247.68 287,244.5C 289.056,240.008 292.223,236.675 296.5,234.5 Z"/></g>
<g><path style="opacity:0.581" fill="#fefffe" d="M 258.5,98.5 C 267.212,98.7261 275.879,99.3928 284.5,100.5C 284.977,122.497 285.311,144.497 285.5,166.5C 254.603,165.98 223.77,164.98 193,163.5C 191.215,143.28 190.382,123.114 190.5,103C 213.274,100.85 235.941,99.3501 258.5,98.5 Z M 240.5,100.5 C 224.365,102.527 208.032,103.86 191.5,104.5C 192.29,123.847 193.29,143.18 194.5,162.5C 214.002,163.043 233.502,163.71 253,164.5C 263.284,163.684 273.451,163.351 283.5,163.5C 284.107,161.225 284.441,158.891 284.5,156.5C 283.421,138.447 282.754,120.447 282.5,102.5C 279.893,101.682 277.226,101.182 274.5,101C 263.172,100.5 251.838,100.333 240.5,100.5 Z M 241.5,107.5 C 241.238,108.978 241.571,110.311 242.5,111.5C 245.194,109.537 244.861,108.203 241.5,107.5 Z M 252.5,142.5 C 252.238,143.978 252.571,145.311 253.5,146.5C 255.111,145.68 255.778,144.346 255.5,142.5C 254.5,142.5 253.5,142.5 252.5,142.5 Z"/></g>
<g><path style="opacity:1" fill="#3771a2" d="M 245.5,103.5 C 249.619,103.488 253.452,104.488 257,106.5C 258.563,111.718 258.896,117.051 258,122.5C 257.5,124.333 256.333,125.5 254.5,126C 249.447,126.217 244.447,126.717 239.5,127.5C 238.808,128.025 238.308,128.692 238,129.5C 237.502,132.482 237.335,135.482 237.5,138.5C 234.635,138.945 232.135,138.278 230,136.5C 226.638,129.903 226.804,123.403 230.5,117C 236.419,115.804 242.419,115.138 248.5,115C 245.183,114.502 241.85,114.335 238.5,114.5C 238.336,111.813 238.503,109.146 239,106.5C 241.166,105.269 243.333,104.269 245.5,103.5 Z M 241.5,107.5 C 241.238,108.978 241.571,110.311 242.5,111.5C 245.194,109.537 244.861,108.203 241.5,107.5 Z"/></g>
<g><path style="opacity:0.355" fill="#fefffe" d="M 197.5,105.5 C 198.289,105.783 198.956,106.283 199.5,107C 195.364,110.545 194.697,110.045 197.5,105.5 Z"/></g>
<g><path style="opacity:0.461" fill="#fefffe" d="M 200.5,109.5 C 202.028,109.517 202.528,110.184 202,111.5C 200.333,112.833 198.667,114.167 197,115.5C 196.5,115 196,114.5 195.5,114C 197.24,112.483 198.906,110.983 200.5,109.5 Z"/></g>
<g><path style="opacity:0.559" fill="#fefffe" d="M 91.5,110.5 C 95.717,110.447 100.05,110.947 104.5,112C 108.277,119.115 106.277,123.782 98.5,126C 87.2522,127.947 83.7522,123.781 88,113.5C 89.1451,112.364 90.3117,111.364 91.5,110.5 Z M 96.5,112.5 C 94.9087,113.219 93.4087,114.219 92,115.5C 91,114.167 90,114.167 89,115.5C 86.7091,118.835 87.2091,121.668 90.5,124C 94.2739,125.183 97.4406,124.349 100,121.5C 102.898,116.702 101.732,113.702 96.5,112.5 Z"/></g>
<g><path style="opacity:0.994" fill="#fdd041" d="M 259.5,115.5 C 262.157,115.162 264.49,115.829 266.5,117.5C 272.893,134.625 266.893,141.792 248.5,139C 251.817,139.498 255.15,139.665 258.5,139.5C 259.411,146.925 256.078,150.592 248.5,150.5C 240.385,150.39 237.052,146.39 238.5,138.5C 238.667,135.833 238.833,133.167 239,130.5C 239.833,129.667 240.667,128.833 241.5,128C 246.5,127.667 251.5,127.333 256.5,127C 257.333,126.167 258.167,125.333 259,124.5C 259.498,121.518 259.665,118.518 259.5,115.5 Z M 252.5,142.5 C 252.238,143.978 252.571,145.311 253.5,146.5C 255.111,145.68 255.778,144.346 255.5,142.5C 254.5,142.5 253.5,142.5 252.5,142.5 Z"/></g>
<g><path style="opacity:0.53" fill="#fefffe" d="M 195.5,194.5 C 226.578,195.56 257.578,197.727 288.5,201C 290.329,201.273 291.829,202.107 293,203.5C 293.695,206.385 294.528,209.218 295.5,212C 291.492,219.977 285.825,226.644 278.5,232C 264.495,231.833 250.495,231.167 236.5,230C 219.234,227.676 201.9,226.01 184.5,225C 181.058,224.573 179.558,222.74 180,219.5C 184.203,210.486 189.37,202.153 195.5,194.5 Z M 196.5,196.5 C 227.585,197.464 258.585,199.63 289.5,203C 291.767,204.081 291.934,205.581 290,207.5C 286.167,211.333 282.333,215.167 278.5,219C 279,219.167 279.5,219.333 280,219.5C 283.934,215.566 287.934,211.566 292,207.5C 292.5,209 293,210.5 293.5,212C 289.644,218.865 284.644,224.865 278.5,230C 247.051,229.389 215.718,227.055 184.5,223C 183.09,222.632 182.09,221.799 181.5,220.5C 186.01,212.136 191.01,204.136 196.5,196.5 Z"/></g>
<g><path style="opacity:0.528" fill="#fefffe" d="M 202.5,200.5 C 207.244,200.038 208.244,201.538 205.5,205C 203.866,205.494 202.199,205.66 200.5,205.5C 200.365,203.446 201.032,201.779 202.5,200.5 Z"/></g>
<g><path style="opacity:0.501" fill="#fefffe" d="M 211.5,202.5 C 214.896,202.633 215.229,203.633 212.5,205.5C 213.5,206.167 214.5,206.833 215.5,207.5C 213.136,208.82 211.469,208.154 210.5,205.5C 210.685,204.416 211.018,203.416 211.5,202.5 Z"/></g>
<g><path style="opacity:0.38" fill="#fefffe" d="M 240.5,204.5 C 242.308,204.491 243.975,204.991 245.5,206C 245,206.5 244.5,207 244,207.5C 242.271,207.026 241.105,206.026 240.5,204.5 Z"/></g>
<g><path style="opacity:0.511" fill="#fefffe" d="M 253.5,205.5 C 255.264,204.288 256.93,204.621 258.5,206.5C 256.603,207.652 254.936,207.319 253.5,205.5 Z"/></g>
<g><path style="opacity:0.47" fill="#fefffe" d="M 271.5,205.5 C 274.462,205.117 275.462,206.117 274.5,208.5C 272.787,208.121 271.787,207.121 271.5,205.5 Z"/></g>
<g><path style="opacity:0.519" fill="#fefffe" d="M 249.5,207.5 C 250.675,207.281 251.675,207.614 252.5,208.5C 250.948,209.798 249.948,209.465 249.5,207.5 Z"/></g>
<g><path style="opacity:0.612" fill="#fefffe" d="M 279.5,207.5 C 281.167,207.5 282.833,207.5 284.5,207.5C 284.5,208.5 284.5,209.5 284.5,210.5C 282.396,210.799 280.396,210.466 278.5,209.5C 278.863,208.817 279.196,208.15 279.5,207.5 Z"/></g>
<g><path style="opacity:0.561" fill="#fefffe" d="M 199.5,209.5 C 202.68,209.176 203.847,210.51 203,213.5C 201.301,214.406 199.467,214.739 197.5,214.5C 197.392,212.486 198.058,210.82 199.5,209.5 Z"/></g>
<g><path style="opacity:0.414" fill="#fefffe" d="M 266.5,209.5 C 267.675,209.281 268.675,209.614 269.5,210.5C 267.948,211.798 266.948,211.465 266.5,209.5 Z"/></g>
<g><path style="opacity:0.57" fill="#fefffe" d="M 207.5,210.5 C 208.833,210.5 210.167,210.5 211.5,210.5C 211.143,214.395 209.143,215.395 205.5,213.5C 206.193,212.482 206.859,211.482 207.5,210.5 Z"/></g>
<g><path style="opacity:0.482" fill="#fefffe" d="M 236.5,211.5 C 241.645,212.482 241.812,214.149 237,216.5C 235.941,216.37 235.108,215.87 234.5,215C 235.823,214.184 236.489,213.017 236.5,211.5 Z"/></g>
<g><path style="opacity:0.513" fill="#fefffe" d="M 108.5,212.5 C 120.3,230.076 130.633,248.743 139.5,268.5C 139.167,268.833 138.833,269.167 138.5,269.5C 128.246,250.659 118.246,231.659 108.5,212.5 Z"/></g>
<g><path style="opacity:0.39" fill="#fefffe" d="M 219.5,212.5 C 221.549,212.706 221.883,213.539 220.5,215C 219.056,215.781 217.723,215.614 216.5,214.5C 217.602,213.824 218.602,213.158 219.5,212.5 Z"/></g>
<g><path style="opacity:0.435" fill="#fefffe" d="M 224.5,212.5 C 226.337,212.639 226.67,213.306 225.5,214.5C 224.702,214.043 224.369,213.376 224.5,212.5 Z"/></g>
<g><path style="opacity:0.602" fill="#fefffe" d="M 193.5,216.5 C 194.833,216.5 196.167,216.5 197.5,216.5C 197.5,217.833 197.5,219.167 197.5,220.5C 195.396,220.799 193.396,220.466 191.5,219.5C 192.193,218.482 192.859,217.482 193.5,216.5 Z"/></g>
<g><path style="opacity:0.453" fill="#fefffe" d="M 271.5,216.5 C 276.368,217.09 276.034,218.09 270.5,219.5C 269.833,219.167 269.167,218.833 268.5,218.5C 269.602,217.824 270.602,217.158 271.5,216.5 Z"/></g>
<g><path style="opacity:0.505" fill="#fefffe" d="M 213.5,218.5 C 216.022,218.128 218.022,218.961 219.5,221C 219.167,221.333 218.833,221.667 218.5,222C 214.129,222.828 209.795,222.661 205.5,221.5C 207.766,220.686 210.1,220.186 212.5,220C 213.056,219.617 213.389,219.117 213.5,218.5 Z"/></g>
<g><path style="opacity:0.373" fill="#fefffe" d="M 223.5,220.5 C 224.978,220.238 226.311,220.571 227.5,221.5C 226.833,221.833 226.167,222.167 225.5,222.5C 224.287,222.253 223.62,221.586 223.5,220.5 Z"/></g>
<g><path style="opacity:0.606" fill="#fefffe" d="M 255.5,220.5 C 257.288,220.215 258.955,220.548 260.5,221.5C 258.796,223.849 256.463,224.849 253.5,224.5C 253.527,222.801 254.194,221.467 255.5,220.5 Z"/></g>
<g><path style="opacity:0.498" fill="#fefffe" d="M 244.5,221.5 C 245.675,221.281 246.675,221.614 247.5,222.5C 244.272,225.259 243.272,224.926 244.5,221.5 Z"/></g>
<g><path style="opacity:0.373" fill="#fefffe" d="M 233.5,222.5 C 234.675,222.281 235.675,222.614 236.5,223.5C 234.948,224.798 233.948,224.465 233.5,222.5 Z"/></g>
<g><path style="opacity:0.512" fill="#fefffe" d="M 269.5,222.5 C 271.337,222.639 271.67,223.306 270.5,224.5C 265.586,225.869 265.253,225.203 269.5,222.5 Z"/></g>
<g><path style="opacity:0.652" fill="#fefffe" d="M 296.5,236.5 C 297.978,236.238 299.311,236.571 300.5,237.5C 299.68,239.111 298.346,239.778 296.5,239.5C 296.5,238.5 296.5,237.5 296.5,236.5 Z"/></g>
<g><path style="opacity:0.476" fill="#fefffe" d="M 309.5,236.5 C 310.289,236.783 310.956,237.283 311.5,238C 306.628,240.039 303.294,243.539 301.5,248.5C 300.686,246.048 301.186,243.715 303,241.5C 305.326,239.934 307.492,238.268 309.5,236.5 Z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

4
images/string-intern/string_interning.svg vendored Executable file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

BIN
images/tic-tac-toe.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -55,6 +55,12 @@ That being said, most of the examples do work as expected. If you face any troub
def generate_code_block(statements, output):
"""
Generates a code block that executes the given statements.
:param statements: The list of statements to execute.
:type statements: list(str)
"""
global sequence_num
result = {
"type": "code",
@ -67,6 +73,9 @@ def generate_code_block(statements, output):
def generate_markdown_block(lines):
"""
Generates a markdown block from a list of lines.
"""
global sequence_num
result = {
"type": "markdown",
@ -85,6 +94,12 @@ def is_interactive_statement(line):
def parse_example_parts(lines, title, current_line):
"""
Parse the given lines and return a dictionary with two keys:
build_up, which contains all the text before an H4 (explanation) is encountered,
and
explanation, which contains all the text after build_up until --- or another H3 is encountered.
"""
parts = {
"build_up": [],
"explanation": []
@ -191,6 +206,14 @@ def remove_from_beginning(tokens, line):
def inspect_and_sanitize_code_lines(lines):
"""
Remove lines from the beginning of a code block that are not statements.
:param lines: A list of strings, each representing a line in the code block.
:returns is_print_present, sanitized_lines: A boolean indicating whether print was present in the original code and a list of strings representing
sanitized lines. The latter may be an empty list if all input lines were removed as comments or whitespace (and thus did not contain any statements).
This function does not remove blank lines at the end of `lines`.
"""
tokens_to_remove = STATEMENT_PREFIXES
result = []
is_print_present = False
@ -203,6 +226,23 @@ def inspect_and_sanitize_code_lines(lines):
def convert_to_cells(cell_contents, read_only):
"""
Converts a list of dictionaries containing markdown and code cells into a Jupyter notebook.
:param cell_contents: A list of dictionaries, each
dictionary representing either a markdown or code cell. Each dictionary should have the following keys: "type", which is either "markdown" or "code",
and "value". The value for type = 'markdown' is the content as string, whereas the value for type = 'code' is another dictionary with two keys,
statements and output. The statements key contains all lines in between ```py\n``` (including) until ```\n```, while output contains all lines after
```.output py\n```.
:type cell_contents: List[Dict]
:param read_only (optional): If True then only print outputs are included in converted
cells. Default False
:type read_only (optional): bool
:returns A Jupyter notebook containing all cells from input parameter `cell_contents`.
Each converted cell has metadata attribute collapsed set to true if it's code-cell otherwise None if it's markdow-cell.
"""
cells = []
for stuff in cell_contents:
if stuff["type"] == "markdown":
@ -269,6 +309,9 @@ def convert_to_cells(cell_contents, read_only):
def convert_to_notebook(pre_examples_content, parsed_json, post_examples_content):
"""
Convert a JSON file containing the examples to a Jupyter Notebook.
"""
result = {
"cells": [],
"metadata": {},

4728
irrelevant/wtf.ipynb vendored

File diff suppressed because it is too large Load diff

63
translations/ru-russian/CONTRIBUTING.md vendored Normal file
View file

@ -0,0 +1,63 @@
Приветствуются все виды изменений. Не стесняйтесь предлагать броские и смешные названия для существующих примеров. Цель - сделать эту коллекцию как можно более интересной для чтения. Вот несколько способов, с помощью которых вы можете внести свой вклад,
- Если вы заинтересованы в переводе проекта на другой язык (некоторые люди уже делали это в прошлом), пожалуйста, не стесняйтесь открыть тему и дайте мне знать, если вам нужна какая-либо помощь.
- Если изменения, которые вы предлагаете, значительны, то создание issue перед внесением изменений будет оценено по достоинству. Если вы хотите поработать над issue (это очень рекомендуется), выразите свою заинтересованность и вы будете назначены исполнителем.
- Если вы добавляете новый пример, настоятельно рекомендуется создать issue, чтобы обсудить ее перед отправкой изменений. Для добавления нового примера вы можете использовать следующий шаблон:
<pre>
### ▶ Какое-то причудливое название. *
* в конце названия означает, что пример был добавлен недавно.
```py
# Подготовка кода.
# Подготовка к волшебству...
```
**Вывод (версия Python):**
```py
>>> triggering_statement
Вероятно, неожиданный вывод
```
(Необязательно): Одна строка, описывающая неожиданный вывод.
#### 💡 Объяснение:
* Краткое объяснение того, что происходит и почему это происходит.
```py
Подготовка примеров для пояснения (при необходимости)
```
**Вывод:**
```py
>>> trigger # пример, облегчающий понимание магии
# обоснованный вывод
```
</pre>
Несколько моментов, которые стоит учитывать при написании примера,
- Если вы решили отправить новый пример без создания issue и обсуждения, пожалуйста, проверьте проект, чтобы убедиться, что в нем уже нет похожих примеров.
- Старайтесь быть последовательными в именах и значениях, которые вы используете для переменных. Например, большинство имен переменных в проекте имеют вид `some_string`, `some_list`, `some_dict` и т.д. Вы увидите много `x` для однобуквенных имен переменных, и `"wtf"` в качестве значений для строк. В проекте нет строгой схемы, как таковой, но вы можете взглянуть на другие примеры, чтобы понять суть.
- Старайтесь быть как можно более креативными, чтобы добавить элемент "сюрприза" во время подготовки примеров. Иногда это может означать написание фрагмента, который здравомыслящий программист никогда бы не написал.
- Также не стесняйтесь добавлять свое имя в список [контрибьюторов](/CONTRIBUTORS.md).
**Некоторые часто задаваемые вопросы**
Что это такое после каждого заголовка сниппета (###) в README: <!-- ID примера: 30f1d3fc-e267-4b30-84ef-4d9e7091ac1a --->? Нужно ли его добавлять вручную или можно игнорировать при создании новых сниппетов?
Это случайный UUID, он используется для идентификации примеров в нескольких переводах проекта. Как контрибьютор, вы не должны беспокоиться о том, как он используется, вы просто должны добавлять новый случайный UUID к новым примерам в этом формате.
Куда следует добавлять новые сниппеты? В начало/в конец раздела?
При определении порядка учитывается множество факторов (зависимость от других примеров, уровень сложности, категория и т.д.). Я бы предложил просто добавить новый пример в конец раздела, который вы считаете более подходящим (или просто добавить его в раздел "Разное"). О его порядке можно будет позаботиться в будущих редакциях.
В чем разница между разделами (первые два очень похожи)?
Раздел "Напрягите мозг" содержит более надуманные примеры, с которыми вы не столкнетесь в реальной жизни, в то время как раздел "Скользкие склоны" содержит примеры, с которыми можно чаще сталкиваться при программировании.
Перед оглавлением написано, что для его создания использовался markdown-toc -i README.md --maxdepth 3. Пакет pip markdown-toc не содержит ни флагов -i, ни --maxdepth. Какой пакет имеется в виду, или какая версия этого пакета?
Должна ли новая запись в оглавлении для фрагмента быть создана с помощью вышеуказанной команды или вручную (в случае, если вышеуказанная команда делает больше, чем просто добавляет запись)?
Мы используем пакет [markdown-toc](https://www.npmjs.com/package/markdown-toc) npm для создания ToC (содержание). Однако у него есть некоторые проблемы со специальными символами (не уверен, что они уже исправлены). Чаще всего я просто вставляю ссылку toc вручную в нужное место. Инструмент удобен, когда мне нужно сделать большую перестановку, в остальных случаях просто обновлять toc вручную удобнее.
Если у вас есть вопросы, не стесняйтесь спрашивать в [issue](https://github.com/satwikkansal/wtfpython/issues/269) (спасибо [@LiquidFun](https://github.com/LiquidFun) за ее создание).

42
translations/ru-russian/CONTRIBUTORS.md vendored Normal file
View file

@ -0,0 +1,42 @@
Ниже перечислены (без определенного порядка) замечательные люди, которые внесли вклад в развитие wtfpython.
| Автор | Github | Issues |
|-------------|--------|--------|
| Lucas-C | [Lucas-C](https://github.com/Lucas-C) | [#36](https://github.com/satwikkansal/wtfpython/issues/36) |
| MittalAshok | [MittalAshok](https://github.com/MittalAshok) | [#23](https://github.com/satwikkansal/wtfpython/issues/23) |
| asottile | [asottile](https://github.com/asottile) | [#40](https://github.com/satwikkansal/wtfpython/issues/40) |
| MostAwesomeDude | [MostAwesomeDude](https://github.com/MostAwesomeDude) | [#1](https://github.com/satwikkansal/wtfpython/issues/1) |
| tukkek | [tukkek](https://github.com/tukkek) | [#11](https://github.com/satwikkansal/wtfpython/issues/11), [#26](https://github.com/satwikkansal/wtfpython/issues/26) |
| PiaFraus | [PiaFraus](https://github.com/PiaFraus) | [#9](https://github.com/satwikkansal/wtfpython/issues/9) |
| chris-rands | [chris-rands](https://github.com/chris-rands) | [#32](https://github.com/satwikkansal/wtfpython/issues/32) |
| sohaibfarooqi | [sohaibfarooqi](https://github.com/sohaibfarooqi) | [#63](https://github.com/satwikkansal/wtfpython/issues/63) |
| ipid | [ipid](https://github.com/ipid) | [#145](https://github.com/satwikkansal/wtfpython/issues/145) |
| roshnet | [roshnet](https://github.com/roshnet) | [#140](https://github.com/satwikkansal/wtfpython/issues/140) |
| daidai21 | [daidai21](https://github.com/daidai21) | [#137](https://github.com/satwikkansal/wtfpython/issues/137) |
| scidam | [scidam](https://github.com/scidam) | [#136](https://github.com/satwikkansal/wtfpython/issues/136) |
| pmjpawelec | [pmjpawelec](https://github.com/pmjpawelec) | [#121](https://github.com/satwikkansal/wtfpython/issues/121) |
| leisurelicht | [leisurelicht](https://github.com/leisurelicht) | [#112](https://github.com/satwikkansal/wtfpython/issues/112) |
| mishaturnbull | [mishaturnbull](https://github.com/mishaturnbull) | [#108](https://github.com/satwikkansal/wtfpython/issues/108) |
| MuseBoy | [MuseBoy](https://github.com/MuseBoy) | [#101](https://github.com/satwikkansal/wtfpython/issues/101) |
| Ghost account | N/A | [#96](https://github.com/satwikkansal/wtfpython/issues/96) |
| koddo | [koddo](https://github.com/koddo) | [#80](https://github.com/satwikkansal/wtfpython/issues/80), [#73](https://github.com/satwikkansal/wtfpython/issues/73) |
| jab | [jab](https://github.com/jab) | [#77](https://github.com/satwikkansal/wtfpython/issues/77) |
| Jongy | [Jongy](https://github.com/Jongy) | [#208](https://github.com/satwikkansal/wtfpython/issues/208), [#210](https://github.com/satwikkansal/wtfpython/issues/210), [#233](https://github.com/satwikkansal/wtfpython/issues/233) |
| Diptangsu Goswami | [diptangsu](https://github.com/diptangsu) | [#193](https://github.com/satwikkansal/wtfpython/issues/193) |
| Charles | [charles-l](https://github.com/charles-l) | [#245](https://github.com/satwikkansal/wtfpython/issues/245) |
| LiquidFun | [LiquidFun](https://github.com/LiquidFun) | [#267](https://github.com/satwikkansal/wtfpython/issues/267) |
---
**Переводчики**
| Переводчик | Github | Язык |
|-------------|--------|--------|
| leisurelicht | [leisurelicht](https://github.com/leisurelicht) | [Chinese](https://github.com/leisurelicht/wtfpython-cn) |
| vuduclyunitn | [vuduclyunitn](https://github.com/vuduclyunitn) | [Vietnamese](https://github.com/vuduclyunitn/wtfptyhon-vi) |
| José De Freitas | [JoseDeFreitas](https://github.com/JoseDeFreitas) | [Spanish](https://github.com/JoseDeFreitas/wtfpython-es) |
| Vadim Nifadev | [nifadyev](https://github.com/nifadyev) | [Russian](https://github.com/satwikkansal/wtfpython/tree/master/translations/ru-russian) |
Спасибо всем за ваше время и за то, что делаете wtfpython еще более потрясающим! :smile:
PS: Этот список обновляется после каждого крупного релиза, если я забыл добавить сюда ваш вклад, пожалуйста, не стесняйтесь сделать Pull request.

3965
translations/ru-russian/README.md vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,70 @@
# Кодекс Поведения участника
## Наши обязательства
Мы, как участники, авторы и лидеры обязуемся сделать участие в сообществе
свободным от притеснений для всех, независимо от возраста, телосложения,
видимых или невидимых ограничений способности, этнической принадлежности,
половых признаков, гендерной идентичности и выражения, уровня опыта,
образования, социально-экономического статуса, национальности, внешности,
расы, религии, или сексуальной идентичности и ориентации.
Мы обещаем действовать и взаимодействовать таким образом, чтобы вносить вклад в открытое,
дружелюбное, многообразное, инклюзивное и здоровое сообщество.
## Наши стандарты
Примеры поведения, создающие условия для благоприятных взаимоотношений включают в себя:
* Проявление доброты и эмпатии к другим участникам проекта
* Уважение к чужой точке зрения и опыту
* Конструктивная критика и принятие конструктивной критики
* Принятие ответственности, принесение извинений тем, кто пострадал от наших ошибок
и извлечение уроков из опыта
* Ориентирование на то, что лучше подходит для сообщества, а не только для нас лично
Примеры неприемлемого поведения участников включают в себя:
* Использование выражений или изображений сексуального характера и нежелательное сексуальное внимание или домогательство в любой форме
* Троллинг, оскорбительные или уничижительные комментарии, переход на личности или затрагивание политических убеждений
* Публичное или приватное домогательство
* Публикация личной информации других лиц, например, физического или электронного адреса, без явного разрешения
* Иное поведение, которое обоснованно считать неуместным в профессиональной обстановке
## Обязанности
Лидеры сообщества отвечают за разъяснение и применение наших стандартов приемлемого
поведения и будут предпринимать соответствующие и честные меры по исправлению положения
в ответ на любое поведение, которое они сочтут неприемлемым, угрожающим, оскорбительным или вредным.
Лидеры сообщества обладают правом и обязанностью удалять, редактировать или отклонять
комментарии, коммиты, код, изменения в вики, вопросы и другой вклад, который не совпадает
с Кодексом Поведения, и предоставят причины принятого решения, когда сочтут нужным.
## Область применения
Данный Кодекс Поведения применим во всех публичных физических и цифровых пространства сообщества,
а также когда человек официально представляет сообщество в публичных местах.
Примеры представления проекта или сообщества включают использование официальной электронной почты,
публикации в официальном аккаунте в социальных сетях,
или упоминания как представителя в онлайн или офлайн мероприятии.
## Приведение в исполнение
О случаях домогательства, а так же оскорбительного или иного другого неприемлемого
поведения можно сообщить ответственным лидерам сообщества с помощью email.
Все жалобы будут рассмотрены и расследованы оперативно и беспристрастно.
Все лидеры сообщества обязаны уважать неприкосновенность частной жизни и личную
неприкосновенность автора сообщения.
## Атрибуция
Данный Кодекс Поведения основан на [Кодекс Поведения участника][homepage],
версии 2.0, доступной по адресу
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Принципы Воздействия в Сообществе были вдохновлены [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org

File diff suppressed because it is too large Load diff

View file

@ -1,41 +0,0 @@
from setuptools import setup, find_packages
if __name__ == "__main__":
setup(name='wtfpython',
version='0.2',
description='What the f*ck Python!',
author="Satwik Kansal",
maintainer="Satwik Kansal",
maintainer_email='satwikkansal@gmail.com',
url='https://github.com/satwikkansal/wtfpython',
platforms='any',
license="WTFPL 2.0",
long_description="An interesting collection of subtle & tricky Python Snippets"
" and features.",
keywords="wtfpython gotchas snippets tricky",
packages=find_packages(),
entry_points = {
'console_scripts': ['wtfpython = wtf_python.main:load_and_read']
},
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Console',
'Environment :: MacOS X',
'Environment :: Win32 (MS Windows)',
'Intended Audience :: Science/Research',
'Intended Audience :: Developers',
'Intended Audience :: Education',
'Intended Audience :: End Users/Desktop',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 2',
'Topic :: Documentation',
'Topic :: Education',
'Topic :: Scientific/Engineering',
'Topic :: Software Development'],
)

View file

@ -1,38 +0,0 @@
from os.path import dirname, join, realpath
import pydoc
try:
from urllib.request import urlretrieve
except ImportError:
from urllib import urlretrieve
url = ("http://raw.githubusercontent.com/satwikkansal/"
"wtfpython/master/README.md")
file_path = join(dirname(dirname(realpath(__file__))), "content.md")
def fetch_updated_doc():
try:
print("Fetching the latest version...")
urlretrieve(url, file_path)
print("Done!")
except Exception as e:
print(e)
print("Uh oh, failed to check for the latest version, "
"using the local version for now.")
def render_doc():
with open(file_path, 'r', encoding="utf-8") as f:
content = f.read()
pydoc.pager(content)
def load_and_read():
fetch_updated_doc()
render_doc()
if __name__== "__main__":
load_and_read()

View file

@ -1,8 +0,0 @@
#!/usr/bin/env python3
import sys
from wtf_python.main import load_and_read
if __name__ == "__main__":
sys.exit(load_and_read())