Hacker News new | ask | show | jobs
by js2 950 days ago
The most important thing about writing code is that you write it idiomatically for the language it is in. With Python, idiomatic code is known as Pythonic.

  def rename_user(user_id: str, name: str) -> User | Exception:
    # Consume the function
    user = get_user(user_id)
    if isinstance(user, Exception):
        return user
    user.name = name
    return user
This is not Pythonic. Don't do it. Like it or not, Python uses exceptions. How do I know that some other code that get_user calls isn't going to raise an exception? What if the program receives an interrupt signal during the get_user call? When I'm writing Python code, I have to think about exception handling, and now when I use this library, I have to add a bunch of isinstance calls too?

Perspective: I've written primarily in Python for over 20 years, as well as coded extensively in many other languages (C, Objective-C, JavaScript, Java, Bash) and have familiarity with a bunch more (Go, Ruby, Gradle, TCL, Lua, Kotlin, C++).

In practice, exception handling, declared exceptions or not, just isn't that big of a problem. When I'm writing code, I have to reason about it, and exceptions and return/error values are just one aspect of that reasoning.

4 comments

Errors/Exceptions by value isn't that important in isolation, but it makes functional programming styles work a lot better (monads).

I think there's still an argument here that this is just a symptom of trying to force functional paradigms on python, which is happening more and more, which I like but am sometimes worried about how pythonic it is... For a one odd script it works well, but when I want to maintain something and have to manage many dependencies and onboard new devs it becomes quite challenging.

> What if the program receives an interrupt signal during the get_user call?

You shouldn't catch interrupt signals regardless of whether you're throwing or returning errors. This is why your error classes should extend Exception and not BaseException. The interrupt errors (e.g. KeyboardInterrupt) extend BaseException

When writing multi-threaded code, you might want to catch KeyboardInterrupt to cleanly shutdown worker threads. In any case, my point is that you always need to be aware of exceptions in Python. You can't just return them as values and pretend they don't otherwise exist.
This topic is explicitly about considering alternatives to the current Pythonic way.
The topic is explicitly about writing an SDK for the company's product, which is presumably intended to be imported in customers' code and used alongside hundreds of other libraries.

As such, writing idiomatic code for the language of the SDK really should be a concern, rather than implementing some idiosyncratic half-baked version of Go or Rust error handling in Python.

And GP is pointing out (correctly) that most of the time being idiomatic has more net gain than any putative advantage of the non-idiomatic proposal. Exceptions to this are extremely rare.
lol the most important thing about writing code is that it works, and works well enough that it puts shekels in my pocket. I'll start worrying about Pythonic code when my accountant does. Until then, we'll keep counting shekels.
yeah, this guy gets it. idiomatic-ness is based on p̵o̵p̵u̵l̵a̵r̵i̵t̵y̵ consensus and only indirectly by technical merit. if someone throws shade at code for being nonpythonic, the code probably isn't bad. if it was they'd have focused on that first.

on the other hand, if someone's writing non-pythonic python because pythonic code doesn't work well for their program, it might be a program they shouldn't be writing in python, which in my experience happens way more often than it should.