[HN Gopher] The Pythonic Emptiness
___________________________________________________________________
The Pythonic Emptiness
Author : todsacerdoti
Score : 32 points
Date : 2024-11-10 11:23 UTC (4 days ago)
(HTM) web link (blog.codingconfessions.com)
(TXT) w3m dump (blog.codingconfessions.com)
| JackSlateur wrote:
| tldr: do not use 'if len(list) == 0', use 'if not list' !
|
| You just have to not write any bug in your code. Also, use type
| checking everywhere. And rewrite your mind, too.
|
| The benefits are worth it .. ! Oh well;
| bogwog wrote:
| > Also, use type checking everywhere
|
| I can't think of anything more Pythonic than that!
| ReflectedImage wrote:
| Use the simplest syntax and check the code works via unit testing
| like you should be doing. Don't statically type your code as it
| increases the bugs by a factor of 3x typically.
| wiml wrote:
| How does statically typing your code "increase[] your bugs by a
| factor of 3x" when it has no runtime effect? What orifice are
| you getting the 3x from?
| ReflectedImage wrote:
| Typically, software developers write 3x the number of lines
| of code when using static typing compared to duck typing.
| It's just the nature of the static typing code style. Write
| 3x the lines, get 3x the bugs.
|
| The programming language that has the least measured bug in
| practice is Clojure because it is duck typed and because it
| doesn't use OOP. Both static typing and OOP have a
| significant measurable negative effect on code correctness.
| stnmtn wrote:
| Clojure has the least measured bugs in practice? Where does
| that statistic come from?
| xen0 wrote:
| I too can invent numbers.
|
| My invented numbers say there's no meaningful difference in
| line counts between statically typed and dynamically typed
| languages.
|
| So how will we prove any of us wrong?
| sjsdaiuasgdia wrote:
| I'm mostly annoyed that 'if len(items) == 0' / 'if len(items) >
| 0' aren't presented as options.
|
| If we're talking about readability, they're far clearer than
| either of the options in the article and require no pre-knowledge
| of truthiness rules.
| warkdarrior wrote:
| They are presented as options, it's just that their performance
| sucks. From the article: if not mylist:
| # 1.061 if len(mylist) == 0: # 1.924
| James_K wrote:
| I feel like, if you care about performance, using Python at
| all is a mistake.
| tantalor wrote:
| For most applications, the choice of algorithms and data
| structures has more impact on performance than programming
| language.
| LegionMammal978 wrote:
| The one big exception to this I've found is working with
| image data. When you have over a million pixels, you'll
| have a slow time transforming them unless you can process
| each one within nanoseconds. Even a compiled language
| like Rust will struggle with image data if you build it
| in debug mode. So there's really always going to be a
| place for optimized implementations of those sorts of
| things.
| chikere232 wrote:
| Then caring about a microptimisation over readability
| would still be the wrong call
| bogwog wrote:
| When you profile your code and find that all you gotta do is
| change a few if statements for a 2x perf boost, that will be
| a happy day.
| jasperry wrote:
| I agree that `len(seq) == 0` is more readable. I don't mind the
| recommended truth test of the sequence itself, but I have no
| idea who would use their "wrong" option with the length as a
| truth value. Or maybe POSIX exit codes (0 is success) have made
| me shy about using integers as truth values.
| James_K wrote:
| Isn't this just a Perl feature (arrays are also their length and
| zero values are falsy)? I can't help but feel Python is getting
| closer to Perl as time goes on. Ironic, since their original goal
| was to be simple and make themselves distinct from Perl. What was
| the saying again? "There should be one-- and preferably only one
| --obvious way to do it." Honestly, I think it was all this "Zen"
| stuff that lead Python down the path to weirdness. This article
| reads like a monk interpreting sacred text. I can think of no
| good reason for all this malarkey.
| jerf wrote:
| This can't be Python "getting closer" to Perl, since it's been
| this way in Python since inception, and I'm pretty sure, Perl
| as well. Both languages have always been exactly where they are
| now on the topic, with no motion, probably since the beginning,
| and certainly for multiple decades.
| James_K wrote:
| I'm not particularly well versed in the history of either
| language. I just know that Python was supposed to be "simple
| and intuitive", but I've had quite a different experience of
| it and this has often been down to Perl-like things going on.
| jerf wrote:
| My personal opinion is that Python gave up on "simple and
| intuitive" a long time ago and people still citing that as
| a guiding principle of the language really need to sit down
| and just read the Python documentation again from start to
| finish, and then ponder for a moment. If they still need a
| clue, they are invited to the same thing to, say, Python
| 2.1, and ponder for a few more moments. It clearly isn't
| and hasn't been for a while. That is not, on its own, a bad
| thing necessarily. It just means it isn't a guiding
| principle anymore, or at the very least, it has moved way
| down the priority list. Plenty of languages have changed
| their guiding principles over time.
|
| However, this is not an example of that. "if list:" has
| been the idiomatic Python since inception, and "if
| len(list):" has been an unnecessary complication for the
| same period of time. Python's "preferably one way to do it"
| has never been about "there is literally only one
| syntactically valid way to do it", for fairly obvious
| reasons if you think about it.
| fphhotchips wrote:
| Certainly "there should be one, and preferably only one,
| obvious way to solve a problem" hasn't been the case for
| a while, or maybe ever. See: tfa.
|
| Perhaps it's just because I'm not Dutch.
| James_K wrote:
| > "if list:" has been the idiomatic Python since
| inception
|
| I would argue the reverse. It was a bad idea to begin
| with and the start of something worse.
|
| > Plenty of languages have changed their guiding
| principles over time.
|
| What would you say is the guiding principal of Python now
| then?
| jerf wrote:
| "Idiomatic" doesn't mean "good". It means the normal way
| within the language. Personally after using both
| languages like Python with "truthiness" and languages
| that rigidly require all if clauses to evaluate to a
| boolean, rigidly and directly, I say the latter is
| unambiguously superior in practice. The former leads to
| surprises, sometimes even creating security
| vulnerabilities when a user can wedge an unexpected value
| into an if statement somehow.
|
| It has unambiguously been idiomatic Python since the
| beginning. My opinion is that it is bad, but that's much
| more an opinion than the fact it has been idiomatic. And
| to Python's credit, part of the reason why I am so sure
| it's bad is precisely the experience I gained in Python
| using it. At the time Python was implementing the
| principle, I don't think the general experience of the
| programming language community was strong enough to know
| that it was a bad idea.
|
| Python's guiding principle right now seems to be the same
| guiding principle as almost every other language, "let's
| solve as many problems as possible by adding features to
| the language". If a year goes by without at least one
| major new feature, the language must be "dead" or
| "failing". As the years wear on and so many languages
| have piled up so many features, I wonder when people will
| finally look around and realize that all these features,
| for all their superficial appeal in the small scale, are
| not generally helping them write better programs, or
| write programs they couldn't have written before, and
| often harm their programs on larger scales. There are
| exceptions. I have a hard time imagining any modern
| language without some concept of closures, for instance.
| I could name a few more; some sort of easy polymorphism
| (there's a few ways to get there but you need to take at
| least one of them... but preferably not _all_ of
| them...), some sort of concurrency solution in this era,
| solutions for memory safety (again, multiple solutions,
| but you need at least _one_ of them). But so many of
| these features are, in my opinion, not a net positive,
| their benefits far smaller than meets the eye and the
| costs so much greater.
| Joker_vD wrote:
| Well, lists in Python are _not_ their length. They are
| convertible to a boolean via __bool__(), however, which is how
| the "if" tests them (or any other object that has this method)
| for "truthiness".
| int_19h wrote:
| I don't find any of the arguments here particularly convincing.
| This claim in particular is weird:
|
| > Similarly, when you use len() to check a sequence for
| emptiness, you are reaching out for a more powerful tool than
| necessary. As a result it may make the reader question the intent
| behind it, e.g. if there is a possibility of handling objects
| other than a built-in sequence type here?
|
| Given that checking for truthiness is less strict than a length
| test, by the same token, whenever you use it, you're reaching for
| an _even more_ powerful tool than necessary. And, if anything,
| seeing `not items` is what makes me question the intent - did the
| author _mean_ to also check for None etc here, or are they just
| assuming that it 's never going to be that? And sure, well-
| written code will have other checks and asserts about it - but
| when I'm reading your code, I don't know if it's missing an
| assert like that because you intended it, or because you couldn't
| be bothered to write it.
|
| OTOH len() is very explicit about what is actually checked, and
| will fail fast and loudly if the argument is not actually a
| sequence.
|
| Also note that it's not, strictly speaking, an either-or - you
| can use `not len(x)` instead of `len(x) == 0` if you want a
| distinctive pattern specifically for empty collection checks.
| adamc wrote:
| I don't agree with this at all, and I wonder if it reflects
| what other languages you use that may have shaped your
| assumptions. `if mylist` feels very much like Common Lisp to
| me. In much of the code I've seen, the value would never be
| none because an empty list was definitely created.
| Joker_vD wrote:
| Ah yes, reusing an empty list NIL as _the_ false value
| because having a separate #f atom is bad for whatever reason.
| wenc wrote:
| For me, len() is much less ambiguous.
|
| Also in Pandas if you try to check the truth value of a
| dataframe to see if it's empty, it will fail. It will say "the
| truth value of a dataframe is ambiguous".
|
| df.empty is less ambiguous but you have to remember it
| specifically for dataframes.
|
| But len(df) > 0 almost always works for any type of collection.
| tromp wrote:
| I would prefer a standard list method/function to test for
| emptiness, which would be both readable and efficient.
| chikere232 wrote:
| It won't be efficient as it's python, but it could be readable
| mulmboy wrote:
| `if x: foo()` is a cancer on the Python community. Devs often use
| it with the intention of handling x being None, and carelessly
| lump in zero and empty lists/strings at the same time. Endless
| bugs.
| smetj wrote:
| Yup!
| morkalork wrote:
| Holy moly, that meme about type checkers and variable names,
| someone is arguing for hungarian notation in 2024?!
| lihaoyi wrote:
| Python's truthiness behavior was the trigger for one of my worst
| ever bugs early in my career, which not only pulled in senior
| engineering but also marketing/comms _and_ legal to help sort out
| the mess. Not a fan!
| adamc wrote:
| I think this needs more explanation to know if this is a good
| argument or not.
| aguaviva wrote:
| You know you're going to need to provide us with a little
| snippet demonstrating this behavior now, right?
| FridgeSeal wrote:
| Python's "truthiness" is a cutesy feature that is just an excuse
| for bugs in your code. It's opaque/ too magic, exhibits poor
| readability and endless confusion.
|
| Just use a normal check, like everyone is expecting to see.
|
| "Oh but what if it's not a sequence", well then you have bigger
| problems. Why are you emptiness testing something that may-or-
| may-not-be-a-sequence? Maybe solve that problem first.
___________________________________________________________________
(page generated 2024-11-14 23:01 UTC)