wtfpython

repository·master·Indexed 12 days ago

https://github.com/satwikkansal/wtfpython

An educational project that explores and explains counter-intuitive, surprising, or lesser-known behaviors in Python through concise code snippets. It covers internal mechanisms such as string interning, object identity (is vs ==), dictionary key equivalence, the walrus operator, and the behavior of try...finally blocks.

Tokens
48.3K
Snippets
221
Records
237
Agent score
96%

What's inside wtfpython

  1. Overview of wtfpython

    master

    wtfpython is a project designed to help developers explore and understand Python by examining non-intuitive code snippets and lesser-known language features. It aims to reveal what happens 'under the hood' of Python's behavior.

    Experienced Python developers can use the examples as a mental challenge, attempting to predict the output of each snippet before reading the explanation. The project is available in several formats:

    • Interactive Website: For a web-based exploration experience.
    • Interactive Notebook: Via Google Colab for running the code snippets directly in a notebook environment.
  2. Avoid shared references when initializing nested lists

    master

    When creating a list of lists using the multiplication operator (e.g., [row] * 3), Python creates multiple references to the same list object in memory. Modifying one element in one sub-list will modify that same index in all other sub-lists because they all point to the same memory address.

    To create a grid where each row is a distinct object, use a list comprehension instead.

    # INCORRECT: All rows point to the same object
    row = [""] * 3
    board = [row] * 3
    board[0][0] = "X"  # This changes ALL rows!
    
    # CORRECT: Each row is a unique object
    board = [['']*3 for _ in range(3)]
    board[0][0] = "X"  # Only changes the first row
  3. Subclass relationships can be non-transitive

    master

    While we expect subclass relationships to be transitive (if A < B and B < C, then A < C), Python allows metaclasses to define custom __subclasscheck__ logic. This can break transitivity. For example, object is a subclass of Hashable, and list is a subclass of object, but list is NOT a subclass of Hashable because list implements a non-hashable __hash__ method.

    >>> from collections.abc import Hashable
    >>> issubclass(list, object)
    True
    >>> issubclass(object, Hashable)
    True
    >>> issubclass(list, Hashable)
    False
  4. Handle `UnboundLocalError` when modifying outer scope variables

    master

    If you attempt to modify a variable in an outer scope using assignment (e.g., a += 1) inside a function, Python treats a as a local variable. Because it hasn't been initialized within that local scope yet, it raises an UnboundLocalError.

    To modify a variable defined in the global scope, use the global keyword.

    a = 1
    
    def another_func():
        global a
        a += 1
        return a
  5. Accessing name-mangled attributes

    master

    Python uses Name Mangling to avoid naming collisions in namespaces. When a class member starts with __ (double underscore) and does not end with more than one trailing underscore, the interpreter modifies the name by prefixing it with _ClassName. To access these attributes from outside the class, you must use the mangled name.

    Example: For a class Yo with an attribute __honey, the mangled name is _Yo__honey.

    class Yo:
        def __init__(self):
            self.__honey = True
    
    yo = Yo()
    print(yo._Yo__honey)  # Accesses the mangled attribute
  6. Understanding deceptive character appearances (Homoglyphs)

    master

    Python code can behave unexpectedly if non-Western characters (homoglyphs) that look identical to Latin characters are used. For example, a Cyrillic 'е' (Unicode code point 1077) is distinct from a Latin 'e' (Unicode code point 101). This can lead to situations where two variables appear to have the same name but are actually different, or where a variable name is defined using a character that looks like a standard letter but is not.

    >>> ord('е') # cyrillic 'e' (Ye)
    1077
    >>> ord('e') # latin 'e'
    101
    >>> 'е' == 'e'
    False
    
    >>> value = 42 # latin e
    >>> valuе = 23 # cyrillic 'e'
    >>> value
    42
  7. Handle float infinity and NaN

    master

    In Python, you can represent mathematical infinity and 'not a number' (NaN) by casting specific case-insensitive strings to the float type. Note that float('nan') is not equal to itself (nan != nan), which is standard IEEE 754 behavior.

    a = float('inf')
    b = float('nan')
    c = float('-iNf')
    
    # Behavior:
    # a == -c is True
    # b == b is False
    # 50/a is 0.0
    # a/a is nan
  8. Truthiness of datetime.time at midnight (Python < 3.5)

    master

    In Python versions older than 3.5, a datetime.time object representing midnight (00:00:00) was considered falsy. This means if midnight_time: would fail for midnight, even though the object exists.

    from datetime import datetime
    
    # In Python < 3.5, this evaluates to False
    midnight = datetime(2018, 1, 1, 0, 0).time()
    if midnight:
        print("This won't print in Python < 3.5")
  9. Behavior of backslashes in raw strings

    master

    In standard Python strings, backslashes \ are used to escape characters. In raw strings (prefixed with r), backslashes are treated as literal characters but still participate in escaping the character immediately following them.

    Critical Limitation: A raw string cannot end with an odd number of backslashes because the backslash will escape the closing quote, leaving the string unclosed and causing a SyntaxError: EOL while scanning string literal.

    >>> print("\"")
    "
    >>> print(r"\"")
    \"
    >>> print(r"\")
    File "<stdin>", line 1
        print(r"\\")
                  ^
    SyntaxError: EOL while scanning string literal
    >>> r'\'' == "\\'
    True
  10. Safe ways to delete items from a list while iterating

    master

    Changing a list while iterating over it causes elements to be skipped because the index shifts as items are removed.

    To safely remove items, iterate over a copy of the list using slicing ([:]).

    Comparison of removal methods:

    • del var_name: Removes the binding from the namespace (does not affect the list content).
    • list.remove(value): Removes the first occurrence of a specific value; raises ValueError if not found.
    • list.pop(index): Removes and returns the element at a specific index; raises IndexError if the index is invalid.
    # UNSAFE: skips elements
    list_2 = [1, 2, 3, 4]
    for idx, item in enumerate(list_2):
        list_2.remove(item)
    # list_2 is [2, 4]
    
    # SAFE: iterates over a copy
    list_3 = [1, 2, 3, 4]
    for idx, item in enumerate(list_3[:]):
        list_3.remove(item)
    # list_3 is []
  11. Booleans as Integers in Python

    master

    In Python, bool is a subclass of int. This has several implications:

    • isinstance(True, int) is True.
    • True has a numerical value of 1, and False has a numerical value of 0.
    • Because bool is a subclass of int, isinstance(item, int) will return True for boolean values. To specifically check for booleans, use isinstance(item, bool).
    • In Python 3.x, True and False are keywords and cannot be reassigned, preventing the behavior seen in Python 2.x where True = False was possible.
    >>> issubclass(bool, int)
    True
    >>> isinstance(True, int)
    True
    >>> int(True)
    1
    >>> int(False)
    0
  12. Structure of an example in wtfpython

    master

    Each example in the repository follows a consistent format to help you learn:

    • ▶ Title: A heading describing the scenario.
    • Code Block: The non-obvious code snippet that triggers the behavior.
    • Вывод (Python версия) / Output: The actual result seen in a Python interactive interpreter.
    • 💡 Объяснение / Explanation: A brief breakdown of what is happening and the technical reason behind the unexpected result.
    • Additional Code/Output: Further code snippets or examples to reinforce the concept.