Mama told me not to come.

She said, that ain’t the way to have fun.

  • 0 Posts
  • 57 Comments
Joined 2 years ago
cake
Cake day: June 11th, 2023

help-circle








  • you necessarily provide the reader with fewer hints as to what is actually in that variable

    Then make it explicit. I much prefer this:

    def do_foo(bar: list | None):
        if not bar:
            return
        ...
    

    This one communicates to me that the function only makes sense with a non-empty list.

    To this:

    def do_foo(bar):
        if len(bar) == 0:
            return
    

    This just tells me bar is something that has a length (list, dict, str, etc).

    And this is way worse:

    def do_foo(bar: list | None):
        if len(bar) == 0:
            return
    

    This tells me we want an exception if bar is None, which I think is bad style, given that we’re explicitly allowing None here. If we remove the | None and get an exception, than the code is broken because I shouldn’t be able to get that value in that context.

    If I care about the difference between None and empty, then I’ll make that explicit:

    if bar is None:
        ...
    if not bar:
        ...
    

    In any case, I just do not like if len(bar) == 0 because that looks like a mistake (i.e. did the dev know it could throw an error if it’s not a list? Was that intentional?).






  • It’s only vague if coming from a language where it’s invalid or vague semantically. For example:

    • Javascript - [] is truthy for whatever reason
    • C - int x[] = {}; evaluates to true because it’s a pointer; C only evaluates to false if something is 0
    • Rust - invalid because you cannot convert a vec -> bool directly, and there’s no concept of null (same w/ Go, but Go has nil, but requires explicit checks)
    • Lua - empty tables, zero, and empty strings are truthy; basically, it’s truthy unless it’s nil or false

    The only surprising one here is Javascript. I argue Lua and Python make sense for the same reason, Lua just decided to evaluate truthiness based on whether the variable is set, whereas Python decided to evaluate it based on the contents of the variable. I prefer the Python approach here, but I prefer Lua as a language generally (love the simplicity).






  • The notion of truthiness is defined by the language.

    Here are most of the built-in objects considered false:

    • constants defined to be false: None and False
    • zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
    • empty sequences and collections: ‘’, (), [], {}, set(), range(0)

    It’s not something that happens to work, it’s literally defined that way.

    if not x is the common way to tell if you have data or not, and in most cases, the difference between None and empty data ([], {}, etc) isn’t important.

    len(x) == 0 will raise an exception if you give it None, and that’s usually not what you want. So I guess the verbose way to do that is if x is None or len(x) == 0:, but that’s exactly equivalent to if not x, with the small caveat that it doesn’t check if the value has __len__ implemented. If you’re getting wonky types thrown around (i.e. getting a class instance when expecting a list), you have bigger problems.

    I use type hinting on pretty much all “public” methods and functions, and many of my “private” methods and functions as well. As such, sending the wrong types is incredibly unlikely, so not x is more than sufficient and clearly indicates intent (do I have data?).


  • len(mylist) tells me it’s definitely a list and not null or whatever

    Do you know what else can tell you it’s a list? Type hinting.

    If I care about the distinction between None and an empty list, I’ll make separate checks. len(None) raises an exception, and most of the time that’s not what I want when checking whether there’s something in the list, so not x is generally preferred, especially when type hinting is used consistently enough to be reasonably sure I’m actually getting a list or None. If I get something else, that means things got really broken and they’ll likely get an exception alter (i.e. when doing anything list-like).

    For sequence type objects, such as lists, their truth value is False if they are empty.

    That’s generally exactly what I want. len(x) == 0 doesn’t tell you it’s a list, it just tells you it has __len__. So that could be a dict, list, or a number of other types that have a length, but aren’t lists.

    Don’t rely on checks like that to tell you what type a thing is.