I don't want to use Python for a software more than a few dozen lines or involving multiple developers. This language was designed to unintentionally shoot your foot so many times.
I don't want to use Python for a software more than a few dozen lines or involving multiple developers. This language was designed to unintentionally shoot your foot so many times.
The "worst" that I can remember was actually a Django quirk - ORM result sets (or QuerySets as they call them) execute their query at object evaluation time rather than at instantiation, so unless you cast your resultset to a list it won't actually talk to the DB just yet. Now attach a GUI debugger such as PyCharm/IntelliJ - it will internally evaluate every expression immediately (to populate its GUI) and cause the behavior to diverge (it will "fix" the code and behave as you'd expect when ran under the debugger).
I guess there could be certain contexts (system programming? low-level libraries? etc) where these are going to be an issue but when it comes to web/API or business logic development I haven't encountered these.
"Where is this called from?", "Where is x being set/modified/read?" - such questions are hard to answer with a large Python code base and I'm not even talking of code that abuses the dynamic nature of Python.
But yes, the moment someone tries to be too clever (metaclasses, dynamic *kwargs parsing...), all of that falls apart and you're back to reading the docs.
However, I do think that the pythonic way leads people to write terse clever code that's needlessly more complex.
This is based on 3 different companies, of which all had decent developers who did follow good practices.
This is 100% true for medium to large codebases. Also because of the dynamic typing just looking at the codebase, it is very hard to understand the "shape" of variables and data. Of course this is improving now because of the type hints, but still it is comparatively hard.
And is it in, let's say Java, with several inheritance levels and very opaque types? It's one thing I struggle with
Sure you know a TypeA has method do_stuff() and returns a TypeB but what actually is happening, beats me. Then you chase down TypeA and find out the actual implementation is spread across TypeA0, TypeBaseA and you can't make sense of anything
That was about plain Java. Where it stops working is some "dependency injection" frameworks which jumped the shark and stopped being about dependency injection (cough Guice cough). A fracking argument to a method comes from god-knows-where because The Framework injects it based on a combination of its class and and annotation? Yes, now it is as bad as Python or maybe even worse :)
All that being said, the by far most common cause of bugs in Python is None in my experience, not any of the shenanigans the language allows you to do.
Mid-sized (5k < loc < 100k?) can absolutely survive a complete "hostile takeover" from new developers, with all the same potential (but not mandatory) issues and pitfalls that pretty much any such codebase invites, in particular in dynamically typed languages.
Also, being boring to write means you seek ways not to write so much, which is also good :)
At least now the easy_install vs pip contention is dead.
About 75% of the bugs I write seem to be about mutable state, and python has nothing but mutable state.
It doesn't even get scoping right.