Skip to content

Instantly share code, notes, and snippets.

@RobertAKARobin
Last active November 17, 2024 21:07
Show Gist options
  • Save RobertAKARobin/a1cba47d62c009a378121398cc5477ea to your computer and use it in GitHub Desktop.
Save RobertAKARobin/a1cba47d62c009a378121398cc5477ea to your computer and use it in GitHub Desktop.
Python Is Not A Great Programming Language

Python is not a great programming language.

It's great for beginners. Then it turns into a mess.

What's good

  • A huge ecosystem of good third-party libraries.
  • Named arguments.
  • Multiple inheritance.

What should be good

  • It's easy to learn and read. However, it's only easy to learn and read at the start. Once you get past "Hello world" Python can get really ugly and counterintuitive.
  • The Pythonic philosophy that "There should be one -- and preferably only one -- obvious way to do it." As someone who loves working within rules and rigid frameworks, I love this philosophy! As someone who writes Python, I really wish Python actually stuck to this philosophy. See below.

What's "meh"

  • Forced indentation. Some love it because it enforces consistency and a degree of readability. Some hate it because they think it enforces the wrong consistency. To each their own.
  • Dynamic typing. There are lots of dynamically-typed languages and lots of statically-typed languages. Which kind of typing is better isn't a Python debate, it's a general programming debate.

What's bad

  • 400 ways (more or less) to interpolate strings. This prints "Hello Robin!" 3 times:

    user = {'name': "Robin"}
    print(f"Hello {user['name']}!")
    print("Hello {name}!".format(**user))
    print("Hello %(name)s!" % user)
    

    If there was a unique and obvious use-case for each of these then that would be one thing, but there's not.

  • 69 top-level functions that you have to just memorize. GvR's explanation sounds nice, but in reality it makes things confusing.

  • map doesn't return a list, even though the whole point of a mapping function is to create one list from another. Instead it returns a map object, which is pretty much useless since it's missing append, reverse, etc. So, you always have to wrap it in list(), or use a list comprehension, which, speaking of...

  • List comprehensions are held up as an excellent recent-ish addition to Python. People say they're readable. That's true for simple examples (e.g. [x**2 for x in range(10)]) but horribly untrue for slightly more complex examples (e.g. [[row[i] for row in matrix] for i in range(4)]). I chalk this up to...

  • Weird ordering in ternary/one-line expressions. Most languages follow a consistent order where first you declare conditions, then you do stuff based the on those conditions:

    if user.isSignedIn then user.greet else error
    
    for user in signedInUsers do user.greet
    

    Python does this in the opposite order:

    user.greet if user.isSignedIn else error
    
    [user.greet for user in signedInUsers]
    

    This is fine for simple examples. It's bad for more complex logic because you have to first find the middle of the expression before you can really understand what you're reading.

  • Syntax for tuples. If you write a single-item tuple (tuple,) but forget the trailing comma, it's no longer a tuple but an expression. This is a really easy mistake to make. Considering the only difference between tuples and lists is mutability, it would make much more sense to use the same syntax [syntax] as lists, which does not require a trailing comma, and add a freeze or immutable method. Speaking of...

  • There's no way to make dicts or complex objects immutable.

  • Regular expressions require a lot of boilerplate:

    re.compile(r"regex", re.I | re.M)
    

    Compared to JavaScript or Ruby:

    /regex/ig
    
  • The goofy string literal syntaxes: f'', u'', b'', r''.

  • The many "magic" __double-underscore__ attributes that you just have to memorize.

  • You can't reliably catch all errors and their messages in one statement. Instead you have to use something like sys.exc_info()[0]. You shouldn't have a catch-all in production of course, but in development it's very useful, so this unintuitive extra step is annoying.

  • Dev environments. Setting up an environment is a problem in any langauge, but other languages have solved the problem better than Python. For example, while npm has its warts, it is widely accepted that a fresh environment should be set up with npm i && npm run [script]. Meanwhile each Python project seems to require a unique mish-mash of pip and pipenv and venv and other shell commands.

What's bad about the culture

Most programmers will acknowledge criticisms of their favorite language. Instead, Pythonists will say, "You just don't understand Python."

Most programmers will say a piece of code is bad if it's inefficient or hard to read. Pythonists will say a piece of code is bad if "it isn't Pythonic enough." This is about as helpful as someone saying your taste in music is bad because "it isn't cultured enough."

Pythonists have a bit of a superiority complex.

@movy
Copy link

movy commented Feb 19, 2023

Python came to prominence when other alternatives were Perl, PHP or Ruby (or C++ hehe). It was a sane choice at the moment, but nowadays only a person who's whole coding experience consists of Scratch Jr, can pick Python as a starting point for their project. Which is a real bummer, as it truly feels like going backwards in time when you switch from literally anything modern to Python, and some of the brightest coders waste their (and ours, users') time on this mess.
I guess this thread includes people who used only Python and pray on Ven. Guido's portrait before bedtime and other people, who, you know, have experienced anything else in this world. It's a stupid idea trying to convince fanatics to walk away from their outdated beliefs, but it's fun to see them justifying their terrible life choices.

p.s. Community Service Announcement: JS/TS never required semicolons (apart from veeeeery rare edge cases, which can and should be rewritten anyway), and (IMHO) it looks way cleaner without them. So whoever brings up this point ("omg, ; at every line, yuck!") just displays his/hers level of (un)awareness about other languages.

@AkashicSeer
Copy link

AkashicSeer commented Feb 20, 2023 via email

@nslay
Copy link

nslay commented Feb 20, 2023

I do love C, but C has a lot of similar problems as C++. On top of that, a lot of the conveniences C++ offers, you have to roll yourself in C or use external libraries (e.g. C lacks STL). I didn't mean to scare you about C++ and I think you should prefer it over C. Not only do you get all of the powerful features of C++ and STL, it's mostly a superset of C and plays nicely with C!

If C/C++ are languages you are learning for practical reasons, I think C++ will land you more jobs than C. Otherwise, I'd just go straight to something like Rust... I know it's hyped a lot, but that one seems to have real potential. You get all the benefits and powers of C/C++ and some memory and thread safety C/C++ lacks. Heck, you can even write operating systems in Rust like RedoxOS! Although, memory safety in C++ is a lot better these days since you can generally use STL for all your data structure and memory management needs. You won't really be playing games with arrays and copies when STL is doing all of this for you under the covers.

@AkashicSeer
Copy link

I do love C, but C has a lot of similar problems as C++. On top of that, a lot of the conveniences C++ offers, you have to roll yourself in C or use external libraries (e.g. C lacks STL). I didn't mean to scare you about C++ and I think you should prefer it over C. Not only do you get all of the powerful features of C++ and STL, it's mostly a superset of C and plays nicely with C!

If C/C++ are languages you are learning for practical reasons, I think C++ will land you more jobs than C. Otherwise, I'd just go straight to something like Rust... I know it's hyped a lot, but that one seems to have real potential. You get all the benefits and powers of C/C++ and some memory and thread safety C/C++ lacks. Heck, you can even write operating systems in Rust like RedoxOS! Although, memory safety in C++ is a lot better these days since you can generally use STL for all your data structure and memory management needs. You won't really be playing games with arrays and copies when STL is doing all of this for you under the covers.

I'm working on software that interacts with 3d printers. I'll also be working on the firmware for the printer which is C++ So again I am not learning them for fun or for jobs, I am learning them to create software I need and will probably sell to others. I also do lots of microcontroller coding since I invent lots of things. So pretty much everything I am doing and will do will require C and C++. I'd like to know plain C because it leads into C++. I already know OOP so many of the C++ concepts should come pretty easily once I move to C++, actually I am learning both at the same time. One reason I want to know C is as you say, many libraries are in C and if I need to edit or create my own I need to know it.

Golang sounded very promising, but it just isn't. I don't want to deal with Golang and C while compiling or trying to cross compile. I'll check back with Golang in another 5 years to see if so many of the modules still need C.

@RobertAKARobin
Copy link
Author

RobertAKARobin commented Feb 20, 2023

Please move conversations unrelated to this article to a different platform. You might try r/cscareerquestions or r/experienceddevs, for example. Thanks!

@AkashicSeer
Copy link

Please move conversations unrelated to this article to a different platform. You might try r/cscareerquestions or r/experienceddevs, for example. Thanks!

Sorry I have severe ADHD and little things get me off on a wild tangent.

@valsteen
Copy link

List comprehensions are held up as an excellent recent-ish addition to Python

PEP 202 – List Comprehensions
https://peps.python.org/pep-0202/
Created: 13-Jul-2000

@djared999
Copy link

It's easy to learn and read.

There are two types of coding in Python, procedural code (wihout using classes or methods), which is so similar to BASIC it could be considered a version of BASIC (although an odd one without arrays), and object code, which is completely different in operation. Most textbooks barely mention the latter.

Dynamic typing.

It has both, variables are typed but objects are not. For instance :

a=1

  • is always a float unless specified in Python 3.

400 ways (more or less) to interpolate strings.

Who bothers formatting the teletype output anymore ? Is is still 1973 ?

There's no way to make dicts or complex objects immutable.
map doesn't return a list, even though the whole point of a mapping function is to create one list from another. Instead it returns a map object, [which is pretty much useless] since it's missing append, reverse,

Objects are always mutable. They must be because of the way object code works.
By mutable I mean they accumulate the output of an operation (method).

An object is assigned to a class and then a method is called. The output of the method is used by the class function, so it must always accumulate in the object.

Since append, reverse and other dot methods are object code, the object will alter, so you need to put the output into another object or variable.

Everything in Python is a reference, not the actual memory space itself : "The name of a thing is not the same as a thing".

If you want immutability, you use a variable. Confusingly, the interpreter will happily use a variable as an object and vice versa. So you have to be very clear about whether something is an object or a variable.

For instance, above -

b= a.double

  • will produce a single namespace with a value of 2, which has two names, a and b.

Python does this in the opposite order:

Only in object code, because of the way that objects are put into classes. If Then is used in procedural code.

@masonova1
Copy link

masonova1 commented Apr 6, 2023

Objects are always mutable. They must be because of the way object code works.
By mutable I mean they accumulate the output of an operation (method).

I fail to see how this is a good assumption of a programmer's intent in a lot of cases. For example, it practically means that I can't have a container that is indexable by non-integer types and is also immutable. Creating a properly "immutable dict" requires me to first construct a dictionary, and then use a MappingProxyType and make sure I have no references to the underlying dictionary, which is just a wholly inadequate solution IMO. There's a reason frozendict frequently makes the rounds in PEPs and forums well after it was rejected. Even in the rejection notice, it couldn't avoid saying "even though it might lead to performance benefits, we just think it's too hard":

The potential of optimizing code using frozendict in PyPy is unsure; a lot of other things would have to change first. The same holds for compile-time lookups in general.

PEP 416, https://peps.python.org/pep-0416/#rejection-notice

(I have issues with a couple other claims on the rejection as well, particularly the "secure sandboxing" complaint -- that's not a problem with frozendict, it's a problem with using frozendict to harden Python or package guts, which was just one of the use cases presented.)

@michellebowerhz4
Copy link

and I was just going to teach him, disappointment

@helmetwearer
Copy link

It's funny to watch someone whine about readability of expressions, and then also whine about features that force readability.

The author here is pushing their own opinions as facts, typical of someone with a superiority complex.

@ZehMatt
Copy link

ZehMatt commented Jun 22, 2023

It's funny to watch someone whine about readability of expressions, and then also whine about features that force readability.

The author here is pushing their own opinions as facts, typical of someone with a superiority complex.

Forced readability? Who are you kidding, its pretty subjective.

@helmetwearer
Copy link

It's funny to watch someone whine about readability of expressions, and then also whine about features that force readability.
The author here is pushing their own opinions as facts, typical of someone with a superiority complex.

Forced readability? Who are you kidding, its pretty subjective.

Everything covered here is subjective, hence the next line. Go back to programming games in not Python

@ZehMatt
Copy link

ZehMatt commented Jun 23, 2023

It's funny to watch someone whine about readability of expressions, and then also whine about features that force readability.
The author here is pushing their own opinions as facts, typical of someone with a superiority complex.

Forced readability? Who are you kidding, its pretty subjective.

Go back to programming games in not Python

What?

@openbakk
Copy link

openbakk commented Jul 1, 2023

great

@Draugr-official
Copy link

It's funny to watch someone whine about readability of expressions, and then also whine about features that force readability.

The author here is pushing their own opinions as facts, typical of someone with a superiority complex.

Unsure why you are on about ad hominem all of a sudden.
You are a grown man with the capability of staying formal when discussing topics, especially one that you favor.

I see you're not only throwing passive aggressive insults at the OP, but also at other commentors.
Typical of someone with insecurity issues.

@RaphGL
Copy link

RaphGL commented Sep 4, 2023

I found this thread and wanted to contribute to it. I've been using python for years now, it was my second language after javascript but since then I've used many more languages, probably over 10 at this point, so I've grown to dislike the language thought I still use it as the ecosystem and wide availability means that for some constrained use cases python is still the most optimal language.

I agree with a lot of what was said in the original gist and the subsequent comments, but to add more reasons to it, here are mine.

Why Python sucks

  • Has a bad type checking (mypy is not good enough), this should be obvious as type hinting was retrofitted into the language and mypy is not integrated into the language itself, being a sort of "official" not official type checker that sometimes won't even be able to properly type check a simple variable = get_value()

  • Lacks basic stuff like visibility modifiers, enums, constants, resulting in the abuse of the object system to get these features and through runtimes like pydantic and inheriting classes (Enum, Dataclass, etc)

  • Performance is pretty bad, to the point that "avoiding for loops" is considered an optimization in the language and people spend copious amounts of hours extracting stuff into C FFIs even in situations where it's unnecessary in other languages

  • Bad packaging standards (all the virtual environments and multiple standards for dependency management which all suck since pip itself is very basic, poetry kinda "fixes" it by wrapping the insanity but it's not part of any standards so you won't be able to shoehorn it into every project)

  • No good way to bundle things, there's Pyinstaller which has very cold starts, there's Wheel which is just another way to bundle stuff to be installed by pip so still too basic

  • Dunders are almost too powerful, they can have a lot of hidden stuff running behind your back. They also allow overloading a lot of behavior which can potentially be used in ways that would be hard to debug or figure out. Just look at all the dunders you can define on this table. You can even overload the await keyword...

  • All implementations of the language besides CPython are "incomplete", they do not work with the entire ecosystem the way you can with other languages with multiple implementations (say C, Go, C++, etc), one of the reasons for this is because of how much CPython relies on C to work and usually other implementations focus on compatibility with specific libraries

@jtint24
Copy link

jtint24 commented Oct 12, 2023

I'm not the biggest fan of Python but I think this is more of a miscellany of small issues than real serious problems with Python. Like sure, sometimes writing tuples with one element can be a little annoying but syntactically, there's no way to unambiguously distinguish single-element tuples from expressions in parentheses. Single-element tuples are pretty rare anyways. The double-underscore methods aren't the most elegant way to have operator-overloading like features but I don't think it's fair to say that you have to "memorize" all of them, nor all the builtin functions; if I happen to forget what memoryview does, I can just google it. The whole "you have to just memorize the top-level functions" bit sticks out to me particularly because 69 isn't a tremendously great number of top-level functions? Like PHP has 5,000. I'll add that never in my experience writing Python have I been hamstrung by forgetting what abs is for. Also, some of these just aren't correct: MappingProxyType functions as an immutable dict even if "frozendict" isn't in the language (though I do agree lack of serious mutability is an issue with the language).

But I agree with most of your points, my problem with this summary is just that basically every language has problems on that scale. Regexes are clunky? Some of the syntax is weird? Basically every programmer will say that (or something equivalently minor) about even their favorite language. I certainly don't think these are the issues holding Python back from being a "great" language. Frankly, they'd all be pretty easy to fix if the python team thought they were important enough to do so (and perhaps were willing to break some backwards compatibility). The outdated and messy packaging system, underdeveloped database tools, and lack of some more modern features (like multiline lambdas or more powerful Rust/Swift-esque enums) are bigger and harder-to-fix challenges for it.

@ifeelagood
Copy link

Learning to read list comprehensions and memorising dunder functions is the same as learning the nuances of any languages. one can argue that of any language.

you also have a complex

@KDean-Dolphin
Copy link

KDean-Dolphin commented Dec 18, 2023

I've been running across Python enough in my work that I thought it best to learn the language well enough to understand what I'm reading. As I always do when learning a new language, I took a recent (small) project and rewrote it in the new language as I went along.

For reference, I'm old enough that yelling "Get off my lawn!" is totally appropriate but not old enough that my belt buckle is hiked up to my belly button. I grew up on BASIC in various flavours as a teenager, then Turbo Pascal in first year university, followed by C, Fortran, APL (a language invented on 1970s-grade psychedelics if there ever was one), Prolog (1980s-grade psychedelics), and assembly. I was an early adopter of C++ and later Java. I've dabbled in various custom programming languages for databases, I know my way around VBA for Excel automation, I've developed applications solo for Fortune 500 companies that have measurably saved millions of dollars a year, and I've led teams developing applications for broad commercial use.

Oh. Dear. God.

No intrinsic support for constants. White space (indentation and line breaks) as mandatory syntax. Class instance attributes declared in constructors. Class static attributes declared outside constructors. Private names (methods, classes, attributes) managed by the underscore convention. Static class initializers through custom annotations. Typing declared as "x: int" for variables and "x() -> int" for methods. Required use of "self" because scope detection is too hard. Duck typing, so that a variable can end up as a type other than the type declared for it, leaving error detection to runtime. Wrapper types around everything so that even basic integer manipulation is tens to hundreds of times slower, and a numerical library (NumPy) that is mysteriously even slower when trying to do something with those same integers.

I understand the need for simple languages to do simple tasks (VBA is a case in point). And if that's all Python was confined to, I wouldn't be having to learn it unless I found myself in an environment where it was the only choice. But, if a language is going to be used for something mission-critical, it had better be good enough to protect me from myself. I will make mistakes; any programmer who tells you they don't (I've worked with a few) is just not good enough to recognize their own limitations and is not someone you want on your team. Many mistakes are easy and boil down to simple coding errors (highlighted by a good IDE before the code is even compiled) or misuse of a complex library (RTFM, assuming there is one). Logic errors are, of course, harder, and require comprehensive testing, and what I don't want is to go through logic testing and get sidetracked by a duck typing bug that a sane language would have caught at compile time with a syntax error or at assignment time with a typecast exception.

Python is what you get when someone looks at the landscape of languages and says to themselves, "You know what? We need a simpler language for simpler tasks." and watches in horror as the language gets adopted in ways for which it is totally unsuitable and never intended. And then, to address the problems that invariably come with languages that don't protect programmers from themselves, a whole community rises up to address the shortcomings and we end up with a language that is neither as simple as intended nor as fit for purpose as far more mature languages. It's the cripple and the tailor joke come to life.

Get off my lawn.

@dtonhofer
Copy link

dtonhofer commented Mar 27, 2024

Python is just a worse Perl. And you cannot even retcon use strict into it.

How much worse? I can't say (full disclosure: I like Perl - for some tasks. If code has been written in reasonable ways. With all warnings and strict, i.e. "must declare variable" and related gobbledygook, switched on. And files kept small and everything properly organized into modules.)

Plus the forced indent syntax makes it so that you cannot write one-liners in Stack Overflow comments. Or Coursera exercises. Hah! 😞

But at least it's well documented. That's something that is indeed very important.

Many people say it's somehow uniquely "readable". But "readability" (for reasons of maintainability, or so it is said) should be a concern after "do you have proper static typing". Any-typed mutable stuff rather negates the effort and good intentions.

Plus the forced indentation seems to generate bad feature interactions with the rest of the language design. As in, you want to add something to the language but your indentation requirements block you from adding clean syntax; now what?. And I just found out that it interferes with experimentation, i.e. the "change-and-modify, comment-uncomment loop" that seems to be a necessary ingredient of getting something to work in Python (or, if one is learning, any other language really, try Clojure...)

Python for scripting the odd task, sure. It's much better than bash. But as someone on the Internet (rightly) said, it's very ill-advised, for economic or reliability issues, to try to build large software systems in Python.

And then can anyone rationally explain this:

my_list = ['foo', 'bar', 'baz']

def f():
    my_list = ['qux', 'quux'] # my_list is local to f()!
    my_list[0] = 'ggg'

f()

assert my_list[0] == 'foo'
assert my_list[1] == 'bar'
assert my_list[2] == 'baz'

def g():
    my_list[0] = 'texx' # this accesses the global my_list!

g()

assert my_list[0] == 'texx'
assert my_list[1] == 'bar'
assert my_list[2] == 'baz'

# But the interpreter / (bytecode compiler?) does not like this
# 
# def h():
#     my_list[0] = 'aloha'  # "cannot access local variable 'my_list'"
#     my_list = ['qux', 'quux']
#
# h()

def h():
    global my_list # now we can modify the global list
    my_list[0] = 'aloha'
    my_list = ['qux', 'quux']

h()

assert my_list[0] == 'qux'
assert my_list[1] == 'quux'

I just had to get this off my chest. Enough of this, I have an exercise in NumPy to do 😓 . And then it's over to Dart.

@dtonhofer
Copy link

@KDean-Dolphin

Prolog (1980s-grade psychedelics),

Hah! No, Prolog is absolute genius once you understand how it even works (i had to reset my assumptions).

If there were some serious investment in Logic Programming instead of everyone throwing money at trying to reinvent a square wheel with the whole JavaScript ecosystem (a practical joke, shurely?) one might see some progress in computer science. There are a lot of excellent ideas out there.

Meanwhile, I guess there is Mercury (underappreciated too, needs a proper IDE)

@KDean-Dolphin
Copy link

@dtonhofer

Prolog (1980s-grade psychedelics),

Hah! No, Prolog is absolute genius once you understand how it even works (i had to reset my assumptions).

I’m happy to be wrong. I’ll give it another look, with the benefit of a few decades’ experience.

If there were some serious investment in Logic Programming instead of everyone throwing money at trying to reinvent a square wheel with the whole JavaScript ecosystem (a practical joke, shurely?) one might see some progress in computer science. There are a lot of excellent ideas out there.

I’m with you on JavaScript; it suffers from the many of the same issues as Python, but the language appears to be better managed, and there are some things in TypeScript that I really like. The build system is horrible, though.

Meanwhile, I guess there is Mercury (underappreciated too, needs a proper IDE)

I’ll take a look.

@RobertAKARobin
Copy link
Author

Added a bullet for setting up dev environments.

@iharob
Copy link

iharob commented Jun 11, 2024

What have you tried with C++ when creating a UI? What didn't work? How can C++ development be any slower than using a shitty language that forces you to stare at a screen to make sure you indent properly? I'm looking at GTK, C++, Eclipse, Cmake. I'll never in my life touch Python, it sucks ass that bad. I'm mostly looking to create something that takes minimal space and works as fast as possible so even my old phones can run it. I want to be able to point my old phone at the printer and use it's camera and broadcast it via Wifi so I can view it on other computers and phones while being able to also control the printer.

For C++ GUIs, I have written a wxWidgets GUI for graphically designing power system survivability simulations. It's been a while, but wxWidgets is like Microsoft Foundation Classes, but cross platform. It uses lots of preprocessing macros! And more recently I've used Qt to design a plugin for MITK. I made a mesh editor plugin for fast 3D segmentation annotation for blob-like organs in medical images.

C++ GUI development is slower mostly because it involves having to compile every attempt. Every change you make requires compiling to test! And that's very slow for large projects. When you have a compilation error, you have to compile again after fixing the error! You also have to spend the time to setup the build system to pull in all the dependencies (include paths/library paths) to even build the thing in the first place! GUI toolkits like Qt are massive with hundreds of include files and dozens of libraries... you need to use something like CMake that can navigate the numerous includes/libraries of a GUI toolkit like Qt. On top of CMake, knowledge of library dependencies in Qt really helps!

For the end users, you have to do something like ship the Qt libraries and make sure those users have the proper dependencies or redistributables installed. Versions of dependencies is also an important consideration as different versions can break ABI! That's when you get dreaded symbol errors in Linux. Or you'll have to use something like Dependency Walker to figure out which symbols are missing on Windows.

Now in Python... you just import some Qt module and can instantly start making windows, buttons, text boxes, combo boxes, etc.... I had a colleague make a fancy network topology editor with PyQt in just a matter of hours! This time frame would be nearly impossible in C++! The key here is that you don't need build systems or compiling to make changes and test GUI changes or functionality. It just works out of the box with scripting languages like Python!

What do you get out of C++? Your program is probably going to run faster and it's likely more correct owing to all the compile-time type checks! What do you get out of Python, or other scripting languages? You'll be able to try things faster and with no project bootstrapping overhead.

Seriously?

More frequently than I wish. Python can break backward compatibility even if you "freeze" the packages. One outstanding case: PyYAML-5.4.1 for python 2. Yes, Python 2 is deprecated, but some project I know is still using it. It shouldn't be that hard to use the same versions used originally and it should run smoothly.

Another one: The advanced build systems like CMake/Qmake and the more recent ones for Qt/C++ are simply awesome. They allow you to do all sorts of things. The project I am working on right now uses a bunch of vagrant machines to run simple python programs. Not only that, but it needs a lot of scripts python/bash to setup the environment. It is simply extremely hard to setup the development environment. With CMake you can write elegant and simple "bootstrap" scripts that produces ready to run binaries, configuration included.

Want to use docker? Ok, just try on a new mac with Apple Silicon chip in it and this setup.

Next: Slow because you need to recompile. Well, you probably don't know it but, if you set it up properly you only need to compile the unit you're working on. With my current python setup it not only takes several minutes to run the startup script (which is generating configuration files and other crazy things pythonists think are cool), but you have to actually do it because you MUST restart uwsgi every time you change a character in the code.

@bakoontz2
Copy link

bakoontz2 commented Aug 9, 2024

@dtonhofer Python is just a worse Perl.

Amen. For grins, I spent 6 hours today writing a "simple" python script that parses a file, selects some matching lines using regex, categorizes them into two lists, combines them under certain conditions, then greps another list generated from another file for matches.

And then I wrote it in perl. In under 30 minutes.

Sure, I've been using perl since the pink camel book. But even if I subtract out the time spent doing Google searches for silly stuff like "how to create a class instance variable in python" (in a constructor, silly!) and setting many, many print statements to figure out why a two-nested-group regex match is returned as a list of tuples (never mind the fact that the list itself is mutable), and that python "re" doesn't support multiple group matches (but python "regex" does, but good luck Googling that, because you get all the regex hits for "re"), I still spent about 3 hours on it. It shouldn't be this difficult and arcane.

And call me old-school, but I'm pretty certain that data encapsulation is a necessary component of any language that claims to be object-oriented. Which makes python not an object-oriented language, despite what Pythonists want you to believe (I believe this quote sums up the iron-clad reason why python doesn't include encapsulation: "After all, we're all consenting adults here." )

@nilslindemann
Copy link

nilslindemann commented Nov 17, 2024

What's Good

I agree to these points and could add many more.

What should be good

That's a bit blurry, so I can not criticize or agree.

What's "meh"*

Forced Indentation
Okay, that can create problems, like indentation getting lost when copying from the Internet. That happened once to me since I use Python. In practice, it is no problem.

Dynamic typing.
What are you missing in today's Python type system?

To the above I would add:

Verbose syntax for dataclasses

One needs to write "class" four times before using the first data. Python needs a data keyword to create data (structs in C, I guess), which would be close to JS expressiveness.

No let block defining space for temp variables

Python does not have that:

let foo, bar:
    baz = 3
    foo = baz * 2
    bar = baz * 5
# foo is 6, bar is 15, baz is not known.

in JS, I can write:

let foo, bar; {
    let baz = 3;
    foo = baz * 2;
    bar = baz * 5;
}
// foo is 6, bar is 15, baz is not known.

No section blocks

"A description of what follows. You can fold this in your editor":
    # here code

What's bad

400 ways (more or less) to interpolate strings
I also dislike using "%" for string interpolation. I use f-strings, if possible. The .format(...) syntax is needed when the format string is inside a variable. That makes one obvious way to do it for every use case and one way, probably kept for backwards compatibility. Not too bad.

69 top-level functions
Why do you need to memorize them? Your IDE has autocomplete, you can print out a cheat sheet, or keep that site open as a pinned tab. Also, your brain has memorized thousands of words in your mother tongue and other languages. When you use Python daily, you will soon have memorized these little lib function names too. I never have to search for them, working is very productive. list, set, dict, print, try to memorize their equivalents and their usage in Java or other languages.

map doesn't return a list
And that makes sense. If you want to map thirty functions over the list you don't want to create a new list in memory each time. And is wrapping in list(...) really so ugly? It is explicit and short. I not just got used to it, I started to like it. Same with generators, iterators, context managers, ...

[[row[i] for row in matrix] for i in range(4)])
Whatever you are trying to do here, you can and probably should write

for i in range(4):
    for row in matrix:
        mylist.append(row[i]) 

The next point is the same, these shortcuts should not be used when the task is complex. Use a normal if / for block statement.

Syntax for tuples
It is a short syntax, but I find it intuitive. I have never run into that error in practice, as far as I remember. How often did you use a one element tuple? And how often have you run into that specific error and were not able to quickly find its cause? Some things just have a short syntax, and it does not hurt. Would you complain about string literals being wrapped in just " and "? I guess no, because you are used to it. (for the records, you don't even need the brackets, you can write mytuple = 1, and I like this!)

Frozen dict, frozen objects
For a frozen dict, create a subclass and overwrite __setitem__. There are libs for other frozen objects. But for what do you need frozen things? I never did.

Regular expressions have a verbose syntax.
Accepted, JavaScript is better in object access syntax and simple regexes. But try to write a complex regex in JS and you will experience pain, while in Python you have re.VERBOSE. Ok, I once figured out a smart workaround for Javascript.

Goofy string syntax
Same as with the tuple syntax, it is often used, and I like that it is short. What would be a non-goofy syntax in your opinion?

Magic underscore syntax
I think it is very expressive. I also just have __init__ __name__, __main__, __slots__ and __pycache__ in my memory. For everything else a Google search or print(dir(<thing>)) or print(help(<thing>)). 90% of these I have never used. You do not need to memorize them.

No Exception catch-all

I do not understand.

try:
    ...
except:
    ...  # Voila, nearly all errors catched - including those you never intended to.

More info.

Many dev environments

Yeah, I did not like that too. But today everybody seems to use venv or no virtual environment, it has gotten better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment