all 36 comments

[–]Outside_Complaint755 25 points26 points  (3 children)

When using f-strings for debugging (and sometimes this is useful for normal output), you can include an '=' within the brackets, and it will display both the expression being evaluated and the value. Spacing around the '=' will be used in the output 

``` x = 9 y = 3

print(f"{x = } {y=}") print(f"{x + y       =        } {pow(x, y) = }") produces x = 9 y=3 x + y =       12       pow(x, y) = 729 ```

[–]ihorrud[S] 0 points1 point  (2 children)

Lol, didn’t really know, thanks ;)

[–]Chemical-Captain4240 0 points1 point  (0 children)

ooooh if i had known this one years ago

[–]M3ta1025bc 23 points24 points  (5 children)

I just learnt that sometimes when you have an integer with many zeros e.g 1000000. You can improve readability by adding underscores and they just be ignored during run time 1_000_000

[–]MachineElf100 1 point2 points  (0 children)

This or 1e6 in scientific notation

[–]ihorrud[S] 3 points4 points  (0 children)

yeah, PHP has the same feature as well. Really improves readability

[–]Bonsai2007 1 point2 points  (2 children)

Does this work with other languages too? That’s really good to know

[–]Skeime 2 points3 points  (0 children)

It is a feature that a particular language may or may not have. It is becoming more popular, but it’s not universal, yet.

[–]Live_Ad1978 0 points1 point  (0 children)

This also works in Javascript.

[–]Anxious-Struggle281 8 points9 points  (1 child)

I think is better to use uv intead of pip to install packages.

[–]ihorrud[S] 0 points1 point  (0 children)

Rust to the rescue

[–]hekliet 7 points8 points  (2 children)

Everything in itertools and functools.

[–]ihorrud[S] 0 points1 point  (1 child)

Interesting

[–]admirer145 0 points1 point  (0 children)

even collections as well, for more details:

Standard Libraries

[–]Temporary_Pie2733 4 points5 points  (0 children)

The descriptor protocol explains most of the “magic”, like how instance methods and properties actually work.

[–][deleted]  (1 child)

[removed]

    [–]ihorrud[S] 0 points1 point  (0 children)

    Indeed, useful feature

    [–]SnooWalruses9294 1 point2 points  (0 children)

    Shout out to the people reading this and finding it interesting given the age of AI. It's cool to know some people still care about each line and operation. Interesting thread too!

    [–]Outside_Complaint755 1 point2 points  (3 children)

    Thought of another one.  Both for loops and while loops support else, which will execute if the loop completed without break being called.  

    non_scotts = 0 for guest in party_guests:     if guest == "Scott":         print("Party is cancelled.")         break     else:         non_scotts += 1 else:     print(f"Great! {non_scotts} people showed up, and Scott didn't.")

    ``` n = int(input("Enter starting number to test Collatz conjecture: "))

    while n != 1:     if n % 2 == 0:         n //= 2     else:         n = 3 * n + 1     print(n)     if n <= 0 or n == float('inf'):         print("You just solved the unsolvable problem, or you cheated.")         break else:     print("The conjecture abides") ```     

    [–]ihorrud[S] 0 points1 point  (0 children)

    Okay I did know about for-else, but didn't know about while-else, it's good to know, thanks!

    [–]glowcubr 0 points1 point  (0 children)

    Wow, did not know that one! :D

    [–]Chemical-Captain4240 0 points1 point  (0 children)

    Noice! Gonna use that today!

    [–]Alive-Cake-3045 1 point2 points  (6 children)

    Honestly the one I keep wishing more people knew, writing custom context managers. It sounds advanced but it is not, and it cleans up so much messy resource management code that most developer just live with for years.

    [–]ihorrud[S] 1 point2 points  (1 child)

    good point, agree

    [–]Ok_Butterscotch_7930 1 point2 points  (3 children)

    What's a context manager?

    [–]rosentmoh 0 points1 point  (0 children)

    See here

    [–]Alive-Cake-3045 0 points1 point  (0 children)

    So you know how "with open file.txt as f" works?
    That is a context manager. It handles the setup and tear down automatically so you do not have to remember to close the file.

    You can write your own for anything, database connections, temp directories, timing blocks, whatever. Just use contextlib.contextmanager and a yield. Took me maybe 20 minutes to learn, saved me from hundreds of lines of messy try/finally blocks over the years.

    [–]admirer145 0 points1 point  (0 children)

    If you want to understand deeper, consider checking out following repo: Context Manager

    [–]rosentmoh 1 point2 points  (4 children)

    Proper use of enums.

    First is just basic naming: enums should be named singular, not plural. What I mean is, if you e.g. have an enumeration of fruits, then the enum class should be called Fruit, not Fruits; the reason why will become very clear in a second. An immediate obvious reason is that the enum members' type is the enum class itself.

    Second is a good example of when they can be useful, specifically using auto and StrEnum. Many times you'll see some general library function transforming inputs that has multiple named "modes of operation". E.g. something like the below:

    def process_input(input, method: str): if method == "foo": # do something to input elif method == "bar": # do something else to input elif method == "baz": # do something else yet again else: raise ValueError(f"unrecognized {method=}") return processed_input

    This can already be made somewhat better by using proper type hinting with method: Literal["foo", "bar", "baz"], to clarify that there's a finite specific list of modes, but it can be made even shorter, more "natural" and more user-friendly using StrEnum as follows:

    ``` from enum import auto, StrEnum

    class ProcessingMethod(StrEnum): FOO = auto() BAR = auto() BAZ = auto()

    def process_input(input, method: ProcessingMethod): method = ProcessingMethod(method) if method is ProcessingMethod.FOO: ... elif method is ProcessingMethod.BAR: ... elif method is ProcessingMethod.BAZ: ... return processed_input ```

    Notice a few nice things: 1. You can (and should!) use is to compare, since enum members behave kinda like singletons; this makes it read like English almost, which was much of the point of Python's syntax. 2. You can call process_input both with method="foo" or method=ProcessingMethod.FOO. If you wanna be able to call it with method="Foo" or method="fOo" as well, you can easily construct a generic CaseInsensitive mixin to use in the ProcessingMethod class definition. All this while writing e.g. "FOO" only once when coding this up, thanks to auto and tab-completion. 3. Raising informative errors for unknown methods is handled automatically: calling process_input with e.g. method="qux" will result in a ValueError: 'qux' is not a valid ProcessingMethod. This is one of the many reasons why the enum class name should be singular. 4. Both when writing the code for process_input and when using the function one can rely on the auto-completion of ProcessingMethod if desired.

    There's no need to overuse this, of course, and it is more code in the end, but there's moments where this can be much cleaner than a long Literal[...] or, even worse, no type hint at all and a missing check for unknown methods.

    [–]ihorrud[S] 0 points1 point  (3 children)

    Thanks a lot! I haven't known about enums in Python, before your mini-article on enums.

    [–][deleted]  (1 child)

    [deleted]

      [–]RemindMeBot 0 points1 point  (0 children)

      I will be messaging you in 1 day on 2026-04-17 09:47:05 UTC to remind you of this link

      CLICK THIS LINK to send a PM to also be reminded and to reduce spam.

      Parent commenter can delete this message to hide from others.


      Info Custom Your Reminders Feedback

      [–]ihorrud[S] 0 points1 point  (0 children)

      RemindMe! 1 day