Python is a mistake - my hate letter to Rossum
Strong words to start off my first post on this webpage, but I hope that by the end of this post, you will understand why I believe python turned out to be a bigger mistake than I am (ha-ha). Honestly, I am dying to see all the Python skids and fanboys defending this irredeemable language, but whatever.
First of all, I usually give the benefit of the doubt to languages, and usually manage to find the charm, aka the good parts of any language. After all, the language isn't about writing the exact code you envisioned, but instead is about writing a piece of software that will serve the world. Some examples:
- Java - although plagued by enterprise BS and the utter lack of a good build system (I will be making a post on gradle, and it won't be praising it), as a language is OK. It is not winning any contests, but it gets the job done, and when not using enterprise libraries, is actually somewhat enjoyable
- C# - my first language, but I no longer use it. However, it is really nice to throw a medium-sized project together, and I would recommend it if you didn't hate Microsoft and everything about them. The language has good intentions, it has really ergonomic syntax, but is just bloatware and reeks of Microsoft
- C - honestly, you just can't go wrong with C. It is verbose, it is manual, dependency management is a joke, but it is really the best language if you want control. It has a very consistent syntax and semantics, which is also nice
- Lua - the language is honestly great. At first sight it seems to be a "mistake language", but honestly, the absolutely rock-solid semantics of the language are worth overlooking the utterly retarded decision to index arrays from 1 (don't even try to start the topic). Also
luarocks
may do anything, but it sure as hell doesn't fucking rock, but I believe lua shouldn't be used like that anyways - C++ - a much worse language than C, I would say it is even objectively bad and would NOT recommend it to anyone for anything, but it still has some nice stuff. RAII is a really powerful concept which I wish more languages utilized. References are a nice idea too, albeit a bit janky at times (especially when you have reference fields, yikes). Overall bloatware with some nice stuff sprinkled in
- JavaScript - my current go-to language (of course I use typescript, but that is just JS in fancy clothes) for any hobby project of mine. It has a very solid, albeit a bit bloated semantics. It is definitely plagued by some mistakes (var is objectively bad, inline regex makes the syntax 10 times more complex, forcing any engine to basically implement two languages, there is no way in Javascript to create a function in an isolated context, like lua's
load
). However, these kinks don't actually get in your way when you use the language, and it actually, unlike the elephant (or python) in the room, isn't very opinionated - you can use semicolons, you can omit them, you can use OOP, you can use FP, you can use procedural, you can literally do whatever the hell you want, which is something I value in a language - Scala - the language is not very flexible in terms of the paradigm you can use in it, it is strictly a FP language, despite what they want you to believe, but regardless of that, it is actually very nice to use it, especially after a straight year of dealing with Java's bs. I love the parameterless functions, they are a good idea for faking properties, the overall syntax is extremely flexible and overall just nice. Only gripe I have with it is that it doesn't have a very nice control flow, and I like my code procedural.
Almost all languages have a redeeming quality, something that makes them worthwhile. Now, lets talk about FUCKING PYTHON.
Python is irredeemable. It is pure evil. I cannot think of one redeeming quality, NOT A SINGLE ONE, that would make this piece of crap excuse for a language even worth anything. Now, pulling such a bold statement out of my ass without substantiating it would make me just a hater. And I may be an asshole, but I'm no hater.
First, we need to take a look at the goals of the language. From a quick search in Wikipedia, it is revealed that they are as follows, in the "Computer Programming for Everybody" proposal section:
- An easy and intuitive language just as powerful as major competitors
- Open source, so anyone can contribute to its development
- Code that is as understandable as plain English
- Suitability for everyday tasks, allowing for short development times
In the following points, I will deconstruct 1, 3 and 4 as being barely applicable (Python is FOSS and that is an undeniable fact, which cannot redeem it soul).
1. What do you have against semicolons?
Some might defend Python's syntax for being concise, ergonomic and readable. Although that might be true for them, I find it very unpleasant to use this syntax, coming from a background of C-like languages. Now, I wouldn't mind if python just didn't allow semicolons and didn't have braces, but for some fucking reason, python ALLOWS semicolons, BUT ONLY when there is a statement after it on the SAME FUCKING LINE. Now, I have my fair share of experience with writing lexers, and I can tell you that you would have to go out of your way to track if a newline has appeared after the semicolon, just to then scream at the user "erm, actually, you didn't need that semicolon here, because we have a newline, stupid". This is honestly just batshit insane. Again, I wouldn't mind if they had outright removed semicolons, but they had to settle for this patchwork of a solution that doesn't even need to exist. A much cleaner way to do it would be, oh, I don't know, just ALLOW ME TO USE MY FUCKING SEMICOLONS??? You will notice this being a very concerning trend with the way Python does stuff, of them just going out of their way to force you to do things THEIR way.
This "feature" makes writing code for people who are used to or prefer the semicolon just alien and introduces too much friction with them, which is in direct violation with the 0th point (the name of the proposal itself) ironically.
2. Space-sensitive languages are just bad
There are many ways to do nested code blocks in languages - C does it with braces, Lua and other Pascal-like languages does it with begin-end, which are all perfectly fine and most of all - flexible. However, at Python inc., they have decided that writing one additional token for the end of a block is unnecessary and makes the code longer and unreadable. That is true in a sense, although that is not an issue that I've really had, but I can see where they'd be coming from. However, python, yet again, has managed to implement this feature in one of the most deranged and horrid ways possible. First of all, you must ALWAYS use a colon before the new body. After that, you have two options: either follow the colon with the statement immediately on the same line, or on the next line, indented one level deeper. In truth, the second option produces very parsable code, but the one-liners are just unreadable (and undebuggable, too!). Still, I would not have issue with this syntax, if there wasn't a gaping plot hole in it: what if you wanted your statement to be empty? In such case, you are quite literally fucked. But don't worry, Python's got your back with the all-new "pass", which is just a NOP statement. The python guys quite literally wrote the main characters straight into a brick wall and just said "fuck it" and just gave him a fucking teleporter and superpowers just in case.
But you will say "well the pass
statement is quite ergonomic and I...". No, it is not. Example: when I try to write a new class, but don't have a body for it yet (which is a part of my style of writing code), I have to explicitly tell python, this little fucking shitlet, that no, this is empty, see, I do jackshit nothing here. I feel I'm going to fucking pass
out at this point. You know, this has a very fucking simple solution, utilizing a mechanism that the Python monke... I mean developers have already implemented - the FUCKING newline check for the semicolons. Here, instead of using it to complain that the next line is on the wrong indentation, just let it be. Just allow it to be there, and consider the body of the above statement empty. Or better yet, if the above statement has a nested list of statements, don't require a colon (this would conflict with the if statement's condition, but this would be easily solvable if newlines in the condition were allowed only in pares). Looking at the list of goals for the language, this makes writing code less ergonomic, for the tradeoff that it is now readable for the people that can't spell their name without a dictionary as well (hooray, we did it, team).
3. Try-except and raise, and the "I'm not like the other girls" syndrome
I feel that this point has been talked to death, but I still want to raise id for completeness sake - why in the LIVID HELL does fucking python need to use "raise" and "except", when the common consensus is for "catch" and "throw". Honestly, I cannot find a better reason for this online, except for some influences from Pascal-like languages (looking at you, ABC), which are also overly restrictive and opiated mistake languages.
Now, we have another issue, which is the catching, oh excuse me, excepting errors (see how weird this sounds?). At the time, the try-catch construct was not unheard of, and C++ even (I believe, I might be getting the history entirely wrong here) had catching exceptions by types. Of course, the Python creators didn't want their language to feel dated even before its inception, so they decided to implement the same feature. The way they created the syntax thou was utterly disastrous. By default, you can only specify the type you want to catch (except MyType:
), by that just tells you "oh yeah, an exception of type A was caught". Now, sometimes you want to actually inspect the value of the error for whatever reason. And here we are, the Python creators having written themselves into a brick wall yet again, because using the except a: MyType
syntax would be ambiguous with the body syntax. But instead of the python creators admitting defeat and taking accountability for the consequences of the god awful decision to use such an awful syntax for bodies, they doubled down, and brought upon this world, to date, the worst syntax for catching exceptions I am yet to witness: except MyType as var_name:
. Words cannot even begin to describe how bad, inconsistent and batshit insane this syntax is. I could propose a plethora of examples of better syntax:
# Use parens
except (a: Type):
...
# Use the arrow (we'll get to that as well)
except a -> Type:
...
# While parsing, track if after the colon, on the same line, we have just a type, followed by another colon
# Although this is obscenely complex syntax, python doesn't seem to take issue with that, so I believe
# this solution to be valid in this domain
except a: Type:
Also, it'd be really nice if python allowed for you to just try
stuff, completely ignoring any errors. Although in most cases it is advisable to not do so, sometimes it is actually useful, but I cannot blame it because virtually no other language does it (at least that I know of).
4. Type annotations - a good idea, poor and incomplete execution
Usually, type annotations are a good idea. In fact, the only good thing that Microsoft has shat out in the past 20 years has been TypeScript, which in essence is just a more complex type annotation toolkit for JS. The python team, of course, felt very generous, and decided to build it right into the darn language. This wouldn't be so bad, albeit a little bloaty, if it weren't for the awful execution. The main places where you'd expect for type annotations to appear are there - parameters, variables and return types. However, in some more subtle places, you are, to put it simply, shit outta luck. One main example I can think of is the variable in the for-in loop. Now, there is really no good reason for this variable to not be annotatable. When you try to write the code for a: int in [1,2,3]: print(a)
, Python will just tell you "Invalid syntax" at the colon. VSCode, and in proxy Microsoft with their PyRight language server is a little bit more descriptive and tells you that it expected "in". This leads me to believe that in fact, python has no other construct that starts with for identifier
, other than the for-in loop. I think that a simple check if the next token after the identifier is a colon wouldn't hurt anybody, but I guess the python guys just thought this was too heavy on the parser, never mind the check for the semicolon (yes, I am dying on this hill).
Other than that, the return type annotation is again batshit insane, but the only option, considering that... BULLSHIT! HAHA, thought that the python gods were capable of reasoning and logical thinking. Try again, bitch. As we can see, they take absolutely no issue with making their language as syntactically complex as humanly possible, so it would make sense that they wouldn't mind if they utilized the idea from the except
example (check if after the parameter list, there was a colon with a type after it and another colon), but NO, HERE IT WAS TOO MUCH. You know, I wouldn't mind if they rolled with the highly opinionated and restrictive syntax, if at least they had a fucking opinion in the first place.
Another gripe I have with Python is that, unlike lterally all other type checking syntax, which acts more or less like glorified comments, Python of course evaluates your type hints. Now, any sane person would ask "WHY IN THE
LIVID HELL are you wasting time calculating FUCKING TYPE HINTS". To that, I respond, of course, with inspect.signature()
. Yes, you heard it right. The only reason the internet had to give me for Python evaluating type hints is
for some obscure reflection no sane person has ever used. I am sure some obscure application uses this, but c'mon, is this really helping anybody? Furthermore, this FORCES the syntax to include the |
operator alongside or
and and
, which is just plain bad. Additionally, if you try to use an invalid expression as a type, the interpreter fails. Now, can you tell me, why the hell the interpreter should care what I put in a literal fucking comment.
5. Lambda expressions - verbose and useless
As a scripting language, you would expect to have some sort of ergonomic way to pass short functions as values to other functions. The python deities of course didn't forget about that. Of course though, they had to choose, yet again, the most BATSHIT INSANE (take a shot every time I say it) syntax for it: lambda arg1, arg2, arg3: expression
. Now, this would be bearable, even somewhat ergonomic, if it weren't for the fact that, believe it or not, there is no way you can have a multiline body, annotate the parameters or annotate the return type. For those reasons, you will most likely just fallback to defining an inner function and passing its name as an argument to wherever you needed it. This is just plain bad design. There is no sane reason why they wouldn't allow for multiline lambdas or type annotations. Also, it is overly verbose, which again shows the inconsistency in Python's philosophy.
6. Import syntax - weird and unergonomic
Here, I'm not going to talk about the module system, which is just another cesspool of acid. The raw syntax of the import statement is just downright insane. If you want to import the module a.b.c.d
, you would, of course, use
the import a.b.c.d
statement. This however will just put a.b.c.d
in your namespace and will force you to write it every time you want to access something from this module. If you want to (like any sane person) just expose a
few classes from this module in your namespace, you would have to do import a.b.c.d
and MyClass = a.b.c.d.MyClass
. Of course, this is not ergonomic, so the all-mighty python gods have given us the "amazing" syntax of from a.b.c.d import ClassA, ClassB, ...
. Now, this is unergonomic for several reasons. Let's say you wrote the import a.b.c.d
syntax and now you want to actually rework it so that it imports just a few stuff from there. You would
have to basically erase the whole line and rewrite it to the mess that is the from .. import ..
statement (it isn't even all that readable, nor ergonomic). Even despite that, you will still get a mix of import
and from
on
the top file, which, I sincerely hope, we can all agree looks like your grandma after here annual dose of falling down the stairs. A much better syntax here would be import name1, name2, name3 from a.b.c.d
. The amazing thing
here is that this syntax: 1. is simpler, 2. is more readable, 3. is more consistent, 4. takes NO effort to implement, and yet python doesn't use it. At times, it almost seems that the Python guys, fueled by some sadistic urge to
see the world burn, on each turn along the road to making the language, have decided to just 180 into a fucking pit of horse shit mixed with sulfiric acid. Now, about the namespace of the file being the exports of the module is
a topic of another point, let me get there.
7. Variables - WHO THOUGHT THIS WAS A GOOD IDEA
Honestly, WHO DID? Also, JavaScript is not innocent of this crime, but at least they somewhat rectified their mistake by implementing let
and const
. Python however doesn't have dedicated variable declarations, but instead just puts all variable assignments in one big bucket in the function. THIS IS BAD! VERY BAD! A lot of times you just lose track of which variable is where, and you basically have to do the mental gymnastics of keeping track of all the variable scopes. Why shouldn't the language do that? Oh right, we shouldn't over-complicate stuff. We of course can introduce complexities for small things that don't matter in the grand scheme of things, but for such a crucial and base feature as variables, of course we can afford to half ass it. Oh python, never change.
8. List comprehensions (same applies for conditional expressions)
The idea is OK, any good language should have a good framework for working with collections and iterations. Of course, Python has its own filter
and map
(which are unergonomic as hell, too, in Python spirit), but at some
point (I believe Python 1.6), they decided that wasn't "ergonomic", "readable" and "fast", which is true. However, the solution they presented us with is honestly 10 times worse than what existed - an obscure syntax that nobody
should ever use - expression for var in list if condition
. I cannot begin to explain how confusing and esoteric this syntax feels. It is not ergonomic, it is not readable - what are you iterating, what is the list? It is just
a soup of keywords and honestly, the pole long enough for me to want to touch this degrading heap of corpses with is yet to be willed into existence. A much more cleaner syntax would be something like Java's streams:
my_list = [1,2,3,4]
my_pipe = pipe(my_list) # an iterable wrapper with the filter, map and other helper functions
print(my_pipe.filter(lambda x: x is not None).map(lambda x: x + 1))
Or JavaScript's IteratorObject which nobody (sadly) uses.
In truth, you aren't forced to use list comprehensions, aka this isn't the only way of doing it (which just defeats one of the goals of python, but what did you expect), but I believe list comprehensions don't have any place in python. Also, if the feature exists, it is inevitably going to be used, so of course, you will have to deal with it when you read trough other people's code (yikes!).
9. The absolute state of operators (its a mess)
Since python finds its roots in the ABC language (another unholy mistake), it has decided that instead of using the well-established ||
, &&
and !
operators, it will use or
, and
an not
instead. This is OK, although I
personally am not a big fan of such syntax, but it gets the job done. However, what gets on my fucking nerves is that they (unsurprisingly) don't fucking stick to it. In python 3.0, when they finally got to implementing type
annotations. This was a good idea, but of course, they didn't use the or
keyword, but instead used |
. WHY PYTHON??? WHY DO YOU HAVE TO BE SO INCONSISTENT. This has no justifiable reason to be like that, unless the python
authors have a lack of long-term memory or any ability to design a fucking language. Now some smartass might say "well actually, this is because or
is an expression operator, and that would confuse python,
because of course a type annotation is an expression", but to that I say, why the hell is a type annotation an expression?
Now, we have the ==
operator, which is just a proxy for the __eq__
method, which compares the two expressions by value. However, this means that you lose the ability to compare by reference. Yet again, Guido has written
himself into a brick wall. Of course, he devised the is
operator, which is honestly an OK idea (hey, that's a first). Of course, you would ask the reasonable question "how can I check if an object is NOT the same instance as
another". Well, the genius syntax of a is not b
is in the language too (you're welcome!). Then, we have the operator a in b
. Of course, the same question would arise for this operator too. Applying the same logic would yield
a in not b
, which sounds like what a 2 year old martian child would blurt out. As you can see, the python language has been written into a brick wall yet again. Of course, we couldn't let that happen, so the python guys
decided to do the a not in b
syntax. Oh how delightful! Now you can write absolute award-worthy pieces of code like val is None or "text" not in val or "text2" in val or ~((a & 1 - (1 << mask) >> 2) != a << (5 ^ xor_key)
. Oh
how delightful. Mixing verbose keywords and C-like operators!
10. PICK A FUCKING CAPITALIZATION
What I'm talking about is True
, False
and None
, but is
, and
, or
, def
, break
, etc. (in fact, True, False and None are the only capitalized keywords). Honestly, I have just one, singular question. Why? You maybe could argue that true, false and none are values of sorts, while the others have more syntactic meaning. However, this is still BS and completely unjustified, as this capitalization is used only for class names (sometimes). Are we led to believe that True
and False
are class names? Well, actually, the python builtins can't even agree on THAT. It seems that sometimes, they will use lowercase for class names (str
, object
) and other times will use capitals (Callable
). Just... Just fucking pick one. The way you started with the snake_case
was great, why did you have to ruin it like everything else?
11. Classes - is this a fucking joke?
Now, at this point, I will be talking about the cornerstone of the python language - the python class. Now, such a base feature should be rock-solid, have good and sound semantics, that make some sense, and be simple and elegant, preferably. Examples of that are the C concepts for structures and functions, javascript's prototype chains, java's type system and lua's metatables. However, Python is just a fucking mess. It has __init__
, __new__
, the ABC
abomination and multiple inheritance. Now, C++ has multiple inheritance, and Guido (my beloved) probably took some inspiration from there, and honestly, that was THE LAST feature he needed to take from C++. He could've picked any other feature BLINDFOLDED from C++ and it would've been better. The fact that no other modern language really does multiple inheritance is a good sign that it is probably more hassle than it's worth.
Another thing that the python classes get absolutely wrong is that they do not differentiate between static and instance members (this differentiation is only made if the method takes a magic parameter self
). This is honestly not too bad, it relieves the core of yet another thing to keep track of, but the execution is just so fucking poor. I mean, you have the instance methods which take self
, you have the @staticmethod
decorator which is literally just for decoration, and you have the @classmethod
, which now makes the method take the instance of the class as a first parameter, which is just batshit insane, I could think of at least one better solution of, oh, I don't know, just making the reference to the class available inside the class itself?? Honestly I don't even know at this point.
This brings me to my next point: you can't reference the class from the body, because. This makes type annotations inside the class that reference the class itself impossible, but don't worry, python has got your back, because you can use strings as type annotations just fine (are you noticing a trend of the python creators just writing themselves into a corner and then pulling something out of their ass to just make an unergonomic and overall shitty syntax?).
Now, the fucking fields. Python, like Javascript (but 5 years earlier), usually assigns the values of the fields directly to the self
object. This is not bad, although at times a little unreadable. This is why the generous python god has given us the ability to just define the fields in the class body itself. This is a nice feature to have, but the way it works is just AWFUL. Instead of initializing the field per instance, it initializes it as a "static field", which means that object fields have to be initialized in the __init__
magic method. This is a mistake that is easy to make, and just a gotcha of a complex OOP system that doesn't need to be this way. Honestly, if Python, like Javascript, had separation between its static and instance methods in some capacity, would be a 10 times better language.
But wait, there's more! Since you can just write self.i_pulled_this_out_of_my_ass = 10
in the class body, this will just create the field for you. This is OK, if combined with the field declaration and annotation (thank god that declaring a field doesn't require a default value or I would've gone insane). However, trying to do the same outside the class body just results in the dreaded AttributeError
. This in theory sounds fine, but honestly, it just disallows you to do something that the interpreter clearly has no issue doing (declaring a new field in the runtime). Honestly it seems like yet another case of Python going out of its way to make my life more miserable.
Now, about the magic methods. Honestly, they... aren't... too bad?? Honestly, I'm very conflicted about them. They would be a perfect fit for a operator-heavy Rust-like language, but for python? Really?? For a language that has set out to be as english-readable as possible, just casually telling your users "yeah, constructors are defined with __init__
BTW" seems misguided at best and just idiotic at worst. Honestly, making a syntax for defining these special methods wouldn't bee too bad of an idea, for example:
class MyClass:
def special add(self, other): pass
def special subtract(self, other): pass
def special constructor(self, a, b, c):
self.a = a
self.b = b
# You get the idea
Honestly, this isn't the best idea, but you can definitely make the argument that it is FAR more readable.
Finally, I just want to say that having your language's most core feature be so messy, not thought trough and esoteric just makes your language reek of the same stuff.
12. The use (and mostly abuse) of underscore methods
In python we have a few well-understood underscore methods (__str__
, __len__
, __iter__
, __next__
, etc.). However, to access them, you will need the str
, len
, iter
and next
global functions. Why not just define the methods without underscores and call them directly is beyond me, but hey, why use a member call, an established feature of the language, when you can just len(elements)
. Gosh I hate python.
13. The module system - is this the best you came up with
In a module based language, as we all know, we should have two base capabilities: importing other modules and exporting stuff from ours, so they're visible to other modules. In that vain, in python, a language that has the import
statement, it would be fair to assume that an export
statement of kinds wouldn't be too out of place. However, our favorite, universally praised and beloved Rossum decided that this is too much bloat and syntax. Instead, he had the genius idea of the exports of the module being literally ALL THE FUCKING VARIABLES declared in global scope. This is just a bad idea on multiple levels, and I hope I don't have to explain why. This means that you never can really encapsulate logic, but the python developers say "we expect the programmer to be responsible and bla-bla". Then, if you think the programmers are smart and reasonable individuals, WHY IN THE LIVID HELL DID YOU DISALLOW THE USAGE OF A SEMICOLON (YES I AM DYING ON THIS HILL).
But wait, it gets even better. Because the python lord felt oh so generous, he decided to give us relative imports. This would be a welcomed addition to the languages, IF IT WORKED HALF OF THE FUCKING TIME. I swear to god, I had a homework assignment which, of course, because I'm a good and tidy programmer, wrote in about 4-5 files. Of course, trying to import one of them was a monumental task on its own, thanks to the amazing job team Microsoft has done with PyLance. Regardless, I wrote my import
statements on my own, and they seemed to work. VSCode was providing me with the appropriate type hints, everything worked, until, of course, I decided to actually run the darn thing. Lo and behold, the python interpreter was screaming at me (does it ever get tired of doing that?) for some unresolved imports. Of course, the files were quite obviously there, so I dug deeper. Importing them with their absolute paths seemed to work just fine with python, but screwed over the IDE (because of course it did). Turns out you just MUST have these empty __init__.py
files in each folder you want to make a "module". This is such a bad design that solves a problem that didn't exist to begin with. Just make it like JS for crying out loud. If you make JS' shitty module system look good, you know you have a fuck-up of mythical proportions on your hands.
14. The (lack of) sandbox-ability and the stiffness of the python environment
Now, the only reason you would want to use a scripting language is to inject into other programs and extend their functionality a little, maybe to glue it together with another program. personally I don't have anything against this type of programming, as long as you get the job done it is fine. However, python is nearly impossible to be sandboxed, period. This means that any python code can just casually delete your home folder or grab your browser credentials and send them off to матушка Россия (mother Russia). This is not bad, but it should be toggleable, or at least controllable, to what degree or how python communicates with the outside world. However, the python authors decided that they would NOT provide an easy way to run python in a sandboxed environment (see this), but instead would force you to either A. just write your own darn python interpreter or B. suck it up.
Of course if you were nuts enough to create your own python interpreter (I may only pray for your long-gone soul), you would still have to implement the literal MILLIONS of internal objects that make python tick (int
, float
, string
, bytes
, bytearray
and many more). This is not terribly bad, but the amount of stuff that is just baked into python and is required to be implemented by any interpreter is honestly mind boggling (JS is not innocent of this crime either, like, WTF is Intl
and Date.toLocaleDateString
, and why should any sane interpreter care about this shit).
If the feat of creating a custom python interpreter was a hard task, now it is impossible.
15. The python ecosystem - a circlejerk of retards that think they can code
We've talked about python as a language. Now let's talk about the rest of the shitshow. Python is often praised for having a lot of things build-in, but I'm not sure if the people that praise it have actually used any of the build-ins, because they STINK. The datetime API is truly a sight to behold (although it is indeed better than JS's truly awful Date
object), we have two objects that work with byte arrays (bytes
and bytearray
), the asyncio
library is just a fucking joke, the build-in mechanisms for working with collections are truly awful on another level, and I can go on. Python IS batteries-included, but the batteries in question had went bad about 2 weeks before they were placed in.
The circlejerk of libraries that surrounds the python build-ins also follow the design principle of being as awful as possible. It seems that pretty much everybody uses the language in the most deranged ways imaginable (although it is nearly impossible to use python in a "correct" way). Libraries, most of the times, work by pure weakly-typed magic, never return what you'd expect, and if you get even decent type stubs or documentations you'd be over the fucking moon. The only two decent libraries that exist are numpy
and pandas
. Thats all, folks. The rest of it, for all I care, can go to hell.
16. Django.
This is the single worst framework I've had the displeasure of working with. Honestly, if an ORM makes SQL look like an attractive option, it has no right to call itself an ORM. The syntax is clunky, relying on pure magic and the dreaded magic class Meta
to do anything useful, like, ever???. The ORM is awfully limited in what kinds of requests it can perform and the new DJango version breaks UUID primary keys (because of course it does).
The whole thing relies on some files being somewhere and the django framework picking up on that and executing them. The whole framework just seems to be running on pure magic and prayers. For the love of everything sacred to you, NEVER touch this shit with a 10 feet pole.
17. PIP is awful
We can joke all day about how terrible NPM is (it truly is awful) and how bloated the node_modules is, but at the end of the day, at least it works (most of the times™) and does what you'd expect (except for when it mines bitcoins on your server, too (EEK!)). PIP however doesn't. It is finicky, I never know where/what it is going to download, and requirements.txt is just a joke. The CLI is just so terrible, and god forbid you have to download a package that has C code. At this point you might as well just take your laptop and bash it into your scull (it will be a far more pleasant experience, and you will save some money on therapy bills, too!).
18. Python is a virus - a critique of the community
As I mentioned above, python takes the liberty to let itself in into every corner of my system, despite my best wishes. I wish I could erase this shit from my PC, but I can't, because, of course, idojackalld
uses python, and I can't delete said program, because, apparently, it is the only service that will manage the jingleflop of my taragust of my sacrobus or something, and apparently, if I delete it, half of Italy would dissapear (and we all want pizza don't we). Why everybody uses python everywhere? I genuinely don't know. It is slow as hell, unintuitive, clunky, inconsistent and hard to use. You have to be as a lost cause as python is to actually genuinely enjoy this language. It is literally a computer AND a mind virus. Everybody tells you "yeah python is a good beginner language" but that couldn't be further from the truth. Still some poor souls will fall for the "python is goated" meme and will actually become python shills themselves, never having tried other languages, because why would you want to write anything else than python. I am honestly amazed by how little flak it gets online, compared to other bad languages (Java, C++, PHP, JS - the bad parts).
The other thing is, because everybody uses python nowadays, when you want to install the only obscure tool that makes some even more obscure piece of hardware work, it of course is written in python (because why not™). This means that now, instead of the operation being a simple sudo pacman -S this-bs-tool
or sudo apt-get install this-bs-tool
, it is a multi-step process of ensuring the PIP package versions are correct, because, of course, why would we make PIP intuitive. Of course you have to know what the fuck a venv
and requirements.txt
Thank god the Arch guys saw this problems, said one massive "Fuck you" to PIP and just did the whole module management themselves, to spare their users the pain and misery (see python, see what you've done).
Conclusion
With all of that said, I'm sure my e-mail will be blown to shreds by loyal python fanboys coming to the defense of their beloved language. This is true for any language, but more so for python. Honestly, I said this above and I'll say it again: I am shocked by how many avid supporters this joke of a language has. Do you people not even use the fucking language? What the hell is wrong with y'all? Even thou typescript is my favorite language, I am well-aware of its pitfalls and don't try to defend them. After all, a language is just a tool, and if a better tool comes along, you ditch the old, because it just doesn't serve you any purpose. In the case of Typescript, it is that old knife that has an awkward curvature to its blade, but still can cut just about anything you want it to. Python on the other hand is one those shitty plastic knives they give you at fast food restaurants because fuck you, and you wouldn't use it unless it was the only option (by that analogy, PHP is a teapot with two handles, absolutely useless at pouring any liquid out of it unless you want to get 3rd degree burns on your hands).
Unfortunately, by the grace of god, probably billions of dreadful Python™-branded lines of code have been written, which means that it is here to stay. As a final plea to anybody still reading, please, for the love of god, never write anything in python, let this mistake die a slow, deserved and uneventful death. This language is truly despicable, so is Rossum, and remember: you might have a new phone, but you don't have my phone number. CYA.
Addendum
In this whole document, "Rossum" is being underlined by my editor, but I'm NOT adding his name to my user dictionary, because he does NOT deserve any more bytes from my PC than his awful programming language has already taken up.