▲ | brap 4 days ago | ||||||||||||||||||||||||||||||||||||||||||||||
I’m far from being an experienced Pythonista, but one thing that really bugs me in Python (and other dynamic languages) is that when I accept an input of some type, like User, I have to wonder if it’s really a User. This is annoying throughout the codebase, not just the API layer. Especially when there are multiple contributors. The argument against using API models internally is something I agree with but it’s a separate question. | |||||||||||||||||||||||||||||||||||||||||||||||
▲ | 3eb7988a1663 4 days ago | parent | next [-] | ||||||||||||||||||||||||||||||||||||||||||||||
Do you mean like is the User object is a well formed User, or did someone actually give you an int? As to the first problem, I recommend the Parse don't validate post[0]. The essential idea is stop using god objects that do it all, but use specific types to make contracts on what is known. Separate out concerns so there is an UnvalidatedUser (not serialized and lacking a primary key) and a ValidatedUser (committed to the database, has unique username, etc). Basic type hinting should get you the rest of the way to cleaning up code paths where you get some type certainty. [0] https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... | |||||||||||||||||||||||||||||||||||||||||||||||
▲ | padjo 4 days ago | parent | prev | next [-] | ||||||||||||||||||||||||||||||||||||||||||||||
Python has reasonably good types these days. If you were to use pydantic to Marshall stuff from the API and then put type annotations on every method below that it would be pretty bulletproof. | |||||||||||||||||||||||||||||||||||||||||||||||
▲ | ac130kz 4 days ago | parent | prev | next [-] | ||||||||||||||||||||||||||||||||||||||||||||||
Somewhat solved by type annotations + a good static type checker, such as pyright (it's 2025, there must be type annotations everywhere), and dynamic cases (very rare, probably due to poor or unfortunate design decisions) can be solved with validators, e.g. the aforementioned Pydantic. This isn't a silver bullet, but it works really well. | |||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||
▲ | derriz 4 days ago | parent | prev | next [-] | ||||||||||||||||||||||||||||||||||||||||||||||
I've been using Python on and off for a few decades and agree. I don't know why you're being downvoted. I've authored tens of thousands of lines of Python code in that time - both for research tools and for "production". I use type hints everywhere in the Python I write but it's simply not enough. This issue is political and not so much technical as Typescript demonstrates how you can add a beautifully orthogonal and comprehensive type system to a dynamic language, thus improving the language's ergonomics and scaleability. The political aspect is the fact that early Python promoters decided that sanity checking arguments was not "pythonic" and this dogma/ideology has persisted to this day. The only philosophical basis for this position was that that Python offered no support for simple type checking. And apparently if you didn't/don't "appreciate" this philosophy, it reflected poorly on your software engineering abilities or skill with Python. To be fair, Python isn't the only language of that era, where promoters went to great lengths to invent alternate-reality bubbles to avoid facing the fact that their pet language had some deep flaws - and actually Perl and C++ circles were even worse and more inward facing. So the "pythonic" approach suggests having functions just accepting anything, whether it makes sense or not, and allowing your code to blow up somewhere deep in some library somewhere - that you probably didn't even know you're using. So instead of an error like "illegal create_user(name: str) call: name should be a str but was a float", it's apparently better (more "pythonic") to not provide such feed-back to users of your functions and instead allow them to have to deal with an exception in a 40 line stack trace with something like "illegal indexing of float by dict object" in some source file library your users haven't even heard of. | |||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||
▲ | jon-wood 4 days ago | parent | prev [-] | ||||||||||||||||||||||||||||||||||||||||||||||
I’m curious, what do you mean by having to wonder if it’s really a User? It’s optional in Python but you can use type annotations and then the type checker will shout at you for passing something that’s not a User instance to things that expect one. | |||||||||||||||||||||||||||||||||||||||||||||||
|