
Reasons Python Sucks - BerislavLopac
https://www.hackerfactor.com/blog/index.php?/archives/825-8-Reasons-Python-Sucks.html
======
notacoward
Most of the points in this article fall on a continuum between irrelevant to
dead wrong.

1 (versions) and 2 (installation) have to do with the ecosystem, not the
language. Unsigned packages are a real problem, but hating on community-
maintained software is just weird. Most software in your local Linux distro's
repository is maintained by a "community" that might just be one person
working in their spare time.

3 (syntax) seems to be about not supporting the author's _own_ highly
idiosyncratic habits, which include deep nesting and putting debug code in the
first column (ugh). The result actually seems better for maintainability than
the author's own unconstrained code would be.

4 (includes) is in the "exactly wrong" category. Includes as in C/C++ are a
_horrible_ way to handle module interfaces. Really, just about the worst
option available. Modules are far better, and if the author hates the fact
that importing a module might run initialization code wait until s/he finds
out about constructors (including __init__ and __attribute__((constructor))
even in C).

5 (nomenclature) is also a bit insane. Lists aren't called arrays in Python
because they're _not_ arrays. Next!

6 (quirks) criticizes quote handling in Python, but mentions bash's quote
handling without a word of comment about how that's even worse. Different
languages have different quoting conventions. Python's might not be perfect,
but many are far worse. Get over it.

7 (pass by reference) is another totally-wrong one. Passing by value is _not_
the universal norm in other languages, and it's not even clear what it means
sometimes because of deep vs. shallow copies. Passing by reference is almost
certainly better for efficiency, and often for correctness as well when copies
becoming inconsistent with each other is a concern. I'd rather have pass-by-
reference as the default, and have to work to make copies, than the other way
around.

8 (local names) barely even make sense. Shadowing names, whether of variables
or of modules/libraries, is a bad idea anyway. If you want the library and the
program not to have the same name, use a prefix for each role. Expecting the
language to handle this for you is just asking for trouble.

~~~
fhood
It's funny how far off the author was, because there _are_ genuine things to
complain about with python, though they may not be exclusive to python.

I regularly wish python required some sort type indication for function
parameters, because dealing with libraries that take complex objects as
function parameters can be an absolute nightmare.

I wish python had some equivalent to the switch statement that didn't involve
workarounds with dictionaries, because sometimes you just want a clean way to
deal with a value that can take 7 different forms.

I regularly find myself wanting to write something of the form do_x() if a.y()
This is stupid, but I still kind of want it since do_x() if a.y() else do_y()
is valid

Edit: Also fuck this whole "it's so cool to shit on Java" thing. Grow up. You
aren't in college anymore. You should recognize that Java fills its niche
effectively, and does a decent job of being semi-fast, portable, easy to read
and maintain, and safe.

~~~
dkarl
_Edit: Also fuck this whole "it's so cool to shit on Java" thing. Grow up. You
aren't in college anymore. You should recognize that Java fills its niche
effectively, and does a decent job of being semi-fast, portable, easy to read
and maintain, and safe._

The "it's so cool to shit on Java" thing served an important purpose and is
probably close to being retired, but it's easy not to understand if you
weren't a Java programmer some time in Java's heyday. There was a culture and
a set of assumptions around Java that today you could probably only find in
the most stodgy and insular corporate programming environments. I helped
_introduce_ Java into a development group and ended up hating the people and
practices it infected us with. The hatred is not completely unrelated to the
language (which runs on a great platform and is not a horrible language) but
it would never have attached itself to the language without some of the
pathological culture surrounding it.

~~~
geezerjay
> The "it's so cool to shit on Java" thing served an important purpose and is
> probably close to being retired

I don't know in which world you live in, but in the real world Java is by far
the dominant platform for web services.

~~~
johnr2
> I don't know in which world you live in, but in the real world Java is by
> far the dominant platform for web services.

I read it as meaning 'the "it's so cool to shit on Java" thing' is close to
retirement, not the language itself.

~~~
geezerjay
You're right. I was quick to assume that the comment was yet another jab at
java. Unfortunately I have to deal with developer who insist in that line of
argument, and it gets really tiring.

------
jMyles
I saw "Reasons Python Sucks" on HN and I thought I was going to finally see an
updated list of well-informed and articulated concerns about Python.

Instead, this list is bizarre, misinformed, and largely incorrect. Other
commenters have already pointed out several specifics. Two things I haven't
seen yet that I'll add:

> And I pity anyone who miscounts spaces and accidentally puts in three spaces
> instead of four somewhere -- this can take hours to debug and track down.

This is just absolutely batshit ridiculous. You'll get an IndentationError
pointing to the exact line in question. In all my years of working with people
at all levels, I've never seen anybody spend more than a few minutes working
out an IndendationError.

> <Pass by reference/object> is one of the big differences between procedural,
> functional, and object-oriented programming languages.

This is a non-sequitur, and it's plain to see. It's possible (in fact common)
to write with all three of these orientations in python, and object transit
has absolutely nothing to do with it.

~~~
heavyset_go
Came to a similar conclusion. I use Python a lot, and it certainly has its
problems. However, the article's analysis doesn't even begin to scratch the
surface of this topic in an informed manner.

Instead, we're presented with paragraphs written by someone who can't read a
stack trace:

    
    
        In [7]: def foo():
           ...:   print('foo')
           ...:     print('bar')
        
          File "<ipython-input-7-47f5b52e9e07>", line 3
            print('bar')
            ^
        IndentationError: unexpected indent

~~~
mangodrunk
Isn't that a strawman? Wouldn't a more apt example be:

    
    
        def foo():
            nums = [...]
            sum = 0
            for x in nums:
                print(x)
            sum += x
            

I don't know python well, but it seems like there could be subtle issues with
indentation that wouldn't cause a compiler error, but would cause the wrong
output.

~~~
jMyles
1) This is not the case that the author presented, though - it was
specifically about 3 spaces instead of 4. This tells me that the author simply
doesn't hang out with python people.

2) On the substance of your concern: I think the evidence is clear (although
I'm aware of no study) that having both syntactical control characters
(typical curlies) _and_ style-only indentation is more likely to lead to the
outcome that you present, because the eye will always gravitate to read by
indentation, whether it's syntactical or not. So have the indentation be the
syntax makes this problem more easily avoided, not less.

IE:

    
    
        def foo() {
            nums = [...]
            sum = 0
            for x in nums {
                print(x)
                }
                sum += x
            }

~~~
maemilius
The difference here is that the former (your example) is automatically
correctable whereas the latter is not.

If I highlighted that entire function in my editor of choice and hit TAB I'd
get exactly the "correct" indentation.

Almost any modern editor can automate this for you. It's one of the benefits
of having a syntax for blocks. Yeah, it's extra typing for something you're
going to do anyways, but now the computer can manage the style for you.

Also, and this is just my personal experience, I've learned to read by those
control characters. I have a really hard time reading python because I'm
subconsciously looking for the control characters!

I really think that part is really down to how you learned to program and what
language you use on a daily basis.

As an aside, I think something like this is much more demonstrative of the
issue you're suggesting:

    
    
        def foo() {
            nums = [...]
            sum = 0
            for x in nums {
                print(x)}
                sum += x
            }
    

It's still automatically fixable, but it's way less immediately apparent that
something is wrong with the indentation.

~~~
jMyles
Right, so you do your automatic fix and you end up with indentation that's the
same as the python example. Isn't this a case _for_ syntactical indentation?

------
CurtHagenlocher
A number of these points seem like reasonable opinions to have. But two which
had me questioning the breadth of the author's experience were "Most
programming languages pass function parameters by value." and "In every other
language, arrays are called 'arrays'. In Python, they are called 'lists'."

To the author:

1\. Java, JavaScript and C# all have types which are passed by reference.
(They also have types which are passed by value.)

2\. Python lists are not arrays, if by arrays you mean a C- or FORTRAN-style
block of non-resizable memory which is indexed by position. Python lists are
much more like the Java List or C# IList interface.

~~~
colanderman
Python (and Java) do not pass anything by reference. They pass by pointer-
value. (If they passed by reference, you could change to which value a
caller's variable was bound, like you can in C++).

~~~
lmm
Those languages use references rather than pointers (that is, their referring-
things do not support arithmetic), so any name for what they do that involves
"pointer" is a poor one.

The distinction between passing the value of a reference being used by the
caller and passing a reference to the caller's stack is so rarely important or
useful that there's no consensus terminology for it. The distinction that's
actually relevant and useful is whether, when we write f(a), f receives the
(thing we would call the) value of a or a reference to the value of a (and in
particular whether f can change the value of a). In Python, f can change the
value of a (that is to say, the thing Python programmers understand to be the
value of a); therefore Python is pass by reference as the term is usually
understood (and certainly any term for its call style that uses "value" is
more misleading than calling it "pass by reference").

~~~
jerf
"The distinction between passing the value of a reference being used by the
caller and passing a reference to the caller's stack is so rarely important or
useful that there's no consensus terminology for it."

And the reason for that is essentially all modern languages make copies of
_something_ when passing argument parameters. The only question is what they
are passing and exactly how hard the language layer works to make it look as
if you are or are not passing something by reference.

I have to reach to something as obscure as Forth to find a language that does
not work that way, and truly does not _copy_ parameters into a function. (I
haven't dug into Factor enough to know if under the hood it still copies
parameters.) It's a very unusual choice to not copy something for a function
call.

(This is one of the ways our CPUs have been optimized for the languages we
run; they make this intuitively expensive operation otherwise cheaper than it
would be on a naively designed CPU.)

~~~
com2kid
> And the reason for that is essentially all modern languages make copies of
> something when passing argument parameters.

Then of course someone turns on whole program optimization for C++, half the
code gets inlined into one terrifying large function, nothing is copied
anywhere, and the code runs 2x faster.

Then some poor SOB has to debug the assembly code for all of this and has
nightmares for years after.

Not like I'd know or anything. :)`

------
mherrmann
> My code for Python 3.5 won't work with the Python 3.7 installation unless I
> intentionally port it to 3.7.

This statement is plain wrong at best and intentionally misleading at worst.
99.99% of Python 3.5 code runs unmodified on 3.7.

> At the official Python web site, their documentation is actively maintained
> and available for Python 2.7, 3.5, 3.6, and 3.7 -- because they can't decide
> to give up on the old code.

No. It's because some people still are on the not-latest version and still
need access to the documentation. It's what every good project should do.

I stopped reading there. Too much wrong in too little text.

~~~
fernandotakai
afaik the only thing on python 3.7 that is backwards incompatible to 3.5 is:

> async and await are now reserved keywords.

so unless the author is using async/await as variable names (and i wonder why
they would), 3.5 code is going to run as expected.

~~~
mahoro
> and i wonder why they would It's easy, actually:
    
    
        import asyncio
    
        @asyncio.async  # SyntaxError in 3.7
        def my_coroutine(...): ...
    

And since asyncio is one of the strongest reason to migrate to python 3.x, I
bet far less than 99.99% of code written for 3.4/3.5 can be run on 3.7 with no
changes.

Luckly, 99% of changes were trivial. Other 1% is a nightmare.

~~~
blattimwind
Using async and await as non-keywords was deprecated since 3.5, while
asyncio.async was deprecated since 3.4.

------
colanderman
A better reason to hate Python: the internal model is _way_ overcomplicated
for what it's meant to be: a beginner-friendly scripting language.
"Everything-is-an-object", duck typing, decorators, bizarre scoping rules,
etc., all make it difficult for experienced programmers to understand, let
along beginners. I've always thought there's a much simpler language
struggling to get out of Python, and I wish it would and would become popular
so I wouldn't have to recommend Python to beginners any more, and be on the
hook for explaining e.g. why default values are mutable, or why nested
generator comprehensions behave differently than nested list conprehensions.
(Think Erlang levels of simplicity.)

The standard library is also haphazard and inconsistent (much like
JavaScript's). Take lists: some operations are methods, some are functions,
some mutate the list, some make a copy, some are global, some are in a module.
There's no rhyme or reason that I can tell. Modern C++ has, in my opinion, a
much more well-thought-out standard library. There are very few
methods/functions which exist due to historical accident (iostreams aside),
and the distinctions between methods/free functions and mutators/copiers is
fairly uniform.

~~~
qntty
Is python really meant to be a beginner-friendly language? I tend to think of
it as lisp-without-parens, and lisp is not very beginner friendly.

~~~
cschmidt
It is usually the "first language" of choice these days, when teaching
programming.

~~~
Already__Taken
This has more to do with who has what teaching resources pre-made to sell than
something any thought about the merits of a programming language.

~~~
milesvp
Sort of. Maybe. When python was gaining momentum in university settings
though, the one main argument I read from a professor more than a decade ago,
is that the python implementation was near identical to their pseudocode. So
they stopped using whatever language they were using in their textbooks, and
started using python, since it made it easier to convey the knowledge they
were trying to convey (and probably greatly decreased the amount of editing
and typos).

Basically, don't discount a text book where every algorithm is executable
code, without first having to translate it into some other language.

------
sytelus
Many of the reasons authors states are quite silly. Personally I don’t like
the huge perf hits everywhere you look. For example, a bool in Python takes
whopping 24 bytes! Multi threading is a giant mess due to GIL that apparently
no one can get rid of. Things like true static variables are missing. Import
behavior differences for programs and modules is baffling. Lambda is
intentionally kept under powered (ex. no group by). Need to create new
environments to avoid conflicting package versions can quickly become annoying
(could have been improved by side by side versions).

Still, I don’t hate it at all. It’s good and beautiful for lot of other stuff.

~~~
cgora
Now this is a good list of things to hate about Python. I would add the
fracturing of build methods for large applications is another frustrating
thing about working with python. Although projects like Pipenv and Poetry seem
to be bringing python up to modern standards in that arena.

~~~
gonational
I have yet to use poetry although I’ve heard great things and I’ve read a blog
post that kind of sold me into it. How would you say it ranks compared to
pipenv? I’ve had frustrating issues with the latter in the past month.

I can’t help but think that the lack of Kenneth Ritz in the commit list since
summer has something to do with this. I don’t recall the exact scenario, but I
think there was some kind of falling out between him and the community.

------
ceronman
"There are only two kinds of languages: the ones people complain about and the
ones nobody uses." \-- Bjarne Stroustrup

------
faizshah
My top 3 criticisms as an intermediate (~5 months of study) python programmer:

1\. Importing behavior is ridiculous:
[https://chrisyeh96.github.io/2017/08/08/definitive-guide-
pyt...](https://chrisyeh96.github.io/2017/08/08/definitive-guide-python-
imports.html)

2\. Python libraries' documentation leave a lot to be desired (compared to
good javadocs). Just because your language is dynamically typed doesn't mean
you don't need to describe what the expected shape of a parameter should be.

3.

    
    
       Static method? @staticmethod
    
       Static variable? declare it outside of your methods but inside your class
    
       Private method/var? name it: __name (but it's not really private just hard to find)
    

I'm sure other Java programmers have had a culture shock coming to python as
well. I appreciate how concise the language is, the great community and module
ecosystem, and how productive it is. But, it feels to me like there's features
missing (I've only been seriously programming python for 5 months though,
before I was basically just scripting and writing java code in python).

Also the most fun part of learning python has been list comprehensions and
itertools, they've really been a revelation. Like when I first learned Ruby
procs, blocks, closures and lambdas.

~~~
laurentl
As a former certified Java programmer, moving to Python was a breath of fresh
air. More concise syntax, no more braces all over the place, much less
boilerplate (think getter, setter, public static void main(String[] args)) and
not everything has to be an object. First-class functions, yay ! (I haven’t
used Java seriously since 1.6 so I don’t know how much the language has
evolved since then). The only reason I’ve had to go back to Java is specific
libraries, and speed.

Python’s philosophy of convention rather than constraint is a nice chance from
Java’s corseted mindset. But I’ve never had to use Python in a large
development team, so I don’t know how well it holds up with a large group of
devs.

As an aside, if you have fun with comprehensions, itertools and lambdas, I
urge you to take a look at functional programming!

~~~
javajosh
Java has changed a great deal since 1.6, and includes something like first-
class functions. But Java's main benefit over python is the JVM itself, which
is extremely well specified and generally a rock-solid piece of kit. Python
doesn't have a specification, or alternative implementations (AFAIK) and I
think that hurts it.

~~~
sinistersnare
Python is not specified but CPython serves as a reference implementation.
Python has _numerous_ alternative implementations. Jython in Java, IronPython
in C#, PyPy in Python (kinda...), and even more lesser-known implementations.

------
t_fatus
I'm quite surprised by some of these reasons:

\- 1 & 2: just use virtualenv, js has its own version manager too (nvm) which
is very useful. This is one of the reason why only python2.7 is included in
OSX, since most of seasoned python devs not use it. usr/include vs
usr/local/include in cpp are not easier to use / understand.

\- 3: my opinion is this forces you to write readable code, in which you don't
have to ask yourself where the scope starts / ends

\- 4: since import use dot notation you just need to follow the path until you
find a file and in this file the corresponding function. Or read the doc. Or
use an IDE with autocompletion. Looking a .h files in c sometimes lead to
using a wrong function judging only by its name.

\- 5: They are called "list" because they are lists, not arrays in a C sense
(size not fixed)

\- 6: multiline strings are a mess indeed, but python3 handles them all in
utf-8 (one of the reasons why it broke backward compatibility)

\- 7: just like js, making them 2 of the 3 most used languages. Understand the
difference between pointers and references is harder to grasp for a beginner
to just remind modifying the arguments of one method is dangerous unless you
know what you're doing

\- 8: there is the from ... import ... which allows you to avoid this while
being explicit

~~~
kemitche
> 3: my opinion is this forces you to write readable code, in which you don't
> have to ask yourself where the scope starts / ends

I agree with this so much. I've never looked at someone's python code and had
a moment's confusion about where a particular function ends. On the flip side,
I see plenty of randomly/confusingly indented C/C++/C# code.

------
cleandreams
I'm a python hater. Yes it is easy, but in exactly the wrong way. Easy for
simple code for middle schoolers. For grownups with large codebases to develop
and maintain, it's not optimal.

Of course I hate the whitespace trickery. I hate the auto formatting that
sometimes doesn't work. Those are fairly minor.

What I really, really hate is the lack of static typechecking. You often have
to read lengthy swathes of code to understand how functions are actually used.
The conventions in the community are terrible. I have used respected libraries
where functions are designed to return a variety of types, just because, so
you need to dynamically typecheck your results. Gawd.

And just as bad the fact it is impossible to encapsulate code. This underscore
nonsense, don't even mention it. Sheesh. I have found that in real life,
internals bleed out over the code base making code more fragile over time and
harder to refactor. It has all these open source scientific libraries because
professional programmers were working on other things, and that is truly
unfortunate.

The lack of seriousness is demonstrated by the fact that it's frozen in time
in terms of runtime data structures because cpython knows and relies on those
internals. Nutso.

And then the GIL!! What the _?_ @.

~~~
coryfklein
While it is technically feasible to write a maintainable and well-organized
large codebase in Python, in practice the lack of static types leads to a
giant mess.

After trying to maintain a legacy system written in Python (where all the
authors had left the company) for a year, I threw my hands up and moved on to
a Scala shop. I vowed to never work again on any major project written in a
language without static typing.

I think this lesson has been learned in the broader community though. Even
most of my colleagues that have used Javascript for years have moved on to
Typescript and never looked back.

I even disagree with the, "well it's good for small projects" line of
thinking. Look - if it works there, it's only because you have net fewer bugs
to catch and lines to read, so the cognitive overhead can be born. But why not
dispense with that cognitive overhead in the first place and just use static
types!

The one exception I make here is for shell scripting. The tight integration
with the command line just makes bash the best choice for some situations. But
even then, I have about a 50% success rate of estimating whether or not this
"little script" will ever grow to become a production application with
multiple modules and components, so today I'm even wary of using shell scripts
in many cases.

~~~
lmm
> Look - if it works there, it's only because you have net fewer bugs to catch
> and lines to read, so the cognitive overhead can be born. But why not
> dispense with that cognitive overhead in the first place and just use static
> types!

I'm not convinced. When a program really is small enough to hold the whole
thing in your head, writing that knowledge down is just overhead. (Of course,
this reverses as soon as the program gets bigger than that).

------
hpcjoe
I agree with a number of the author's points. For me personally, the biggest
single issue is the scope by indentation. I know some folks like this, and
think it is good to restrict single functions/methods to less than a page in
an editor ... but I personally do not like a language imposing such opinions
on me. It makes, IMO, reasoning about the code your reading, even if it fits
in a single editor page, very ... very hard.

As someone who works with multiple languages across multiple environments, the
author's comments on the installation ecosystem are on point. Though, these
critiques are better directed at the packagers of the distribution. I'd given
up on getting current, correctly built versions of Perl, Python, R, Octave,
etc. from packagers/distros, and simply build my own in a separate tree[1].
Most folks now do this in user home directories, but I still personally like
the system level availability.

FWIW, I've found that Julia[2] is a far better Python than Python. You have
all the advantages of a JIT compiled language which does
parallelism/concurrency well, has an awesome FFI to simply use external
libraries, etc.

[1] [https://github.com/joelandman/nlytiq-
base](https://github.com/joelandman/nlytiq-base)

[2] [https://julialang.org/](https://julialang.org/)

------
peterwwillis
This rant would have been exactly the same if he had just discovered Perl5.
It's got _way_ more quirks than Python, but you deal with it, because the
language is super useful.

The one valid gripe that wasn't quite there is why doesn't Python (or any
other language really) manage its modules like CPAN? CPAN is amazing. It's
ancient and dusty and missing obvious modern improvements, but it's still way
more useful than anything else.

Searching through PyPi is pretty awful. Look for "yaml versioning" and get
10,000 projects to wade through. CPAN is hierarchial, so not only can I find
what I'm looking for, it even exists on disk where I expect it.

Because of all that, a few other things happen. The low level modules are
older, exposed to more users, so people find them first, improve them over
time, and this influences and improves new code. Not only are there these
great examples of quality code for comparison, but code reuse and extending is
way more common than entirely new modules.

Testing is also really rigorous. CPAN testers framework tests across all Perl
releases and computing platforms, continuously. Perl module build instructions
are converted easily to Makefiles, making it easier to build and test on other
platforms if you're not familiar with Perl conventions.

Most modules also provide real in-line documentation, not just one line
describing what a function does. Perldoc usually gives you a real man page for
any given module you're looking at, whereas Pydoc gives you a bare list of
method calls and objects that maybe the author added documentation to, but
often not. Which am I supposed to use, for what? Might as well go read all the
code...

...oh, and unrelated, but using regex's in Python is kind of horrifying.

~~~
hpcjoe
I remember the perl4 to perl5 transition. I had some perl4 code I wrote to
automate runs of my code. Porting it to perl5 made me grumble a little, but it
was mostly very minor changes. About an hour of work for all my code.

But, yeah ... CPAN, and C-TAN, are things to behold. Python hasn't done a
great/good job with this. Npm is just plain awful. Julia's Pkg was good in the
0.6.x days ... seems to be borked now, though this may be due to the 0.6 ->
1.0 transition.

For me, Perl is my go-to scripting language. I've written some pretty
intensive apps in it, which would be horrifying in other languages. It has
(many) warts, though packaging isn't one of them.

I am looking at using Julia for scripting in places where I'd ordinarily use
Perl ... mostly data clean up. This noted, it is very hard to beat Perl in
munging data. R comes close, but writing parsers in it is hard.

Perl6 aka Rakudo is very interesting to me. Addresses many of the issues I've
had with Perl in the past, and gives some truly incredible power going
forward. Adoption appears to be low and slow right now. I don't actually have
time to play with it now, as I've got other higher priority issues to deal
with.

------
berdon
I agree with the OPs points but disagree with the degree to which the author
has used them as a means to "hate" a language. I generally avoid Python too
but saying you hate the language because of a bunch of contrivances mostly
wrought from inexperience and holding too strongly to C like languages is poor
form.

Versions: Ok? Versioning and fragmentation is a hard problem. Backwards
compatibility is a hard problem. Moving fast and never breaking anything is a
nearly impossible problem. Python sucks at it, lots of things suck at it.
There are many examples of other languages (.NET Core, for example),
platforms, frameworks, etc that all suffer from this. It can be a reason to
avoid those things but probably not one to base a loathing on.

Also, lots of people still use Perl. Lots of people still love Perl. I don't
know why.

Installation: This screams "windows only" user. Path'ing, local dependencies,
and package management is relatively common and you should force yourself to
be comfortable with those concepts. Just saying "I should be able to just run
one thing and be done forever", albeit ideal, is naive and never going to
happen.

Syntax: Yep. Spacing blows and you're always going to have stupid issues with
it. I hate Python's spacing. Someone ought to create a custom interpreter that
allows for using braces.

Includes: Most of these complaints sound like they're coming from someone
largely silo'd in the C/C++ world of wanting to know everything. "With C, you
can just look in /usr/include/*.h" \- the author is admitting he's unhappy
because Python isn't C.

Quirks: General complaints about other languages... and using those complaints
to somehow sour Python? The quirks he does list for Python aren't even strange
- they're pretty useful.

Local Names: OP probably could have just included this in quirks rather than
having another point. I'm pretty sure there's actually a means of avoiding
this type of import issue by some silly Python pathing shenanigans.

~~~
ArchTypical
> author is admitting he's unhappy because Python isn't C

That's not the point at all. I mean, did you read it?

How do you mischaracterize the specific point about the casual opportunity for
foreign module metaprogamming? Module initialization is bad in a pernicious
way. While you can't do operator overloading, you can clobber namespaces
(which was referenced). Paired with a community repository, this is exactly
the same case of what's so dangerous about npm.

~~~
berdon
My point wasn't to devalue his arguments - in fact, I find them valid
arguments. My point was he's using inexperience and/or familiarity with C/C++
as a reason to "hate" it.

He complains about Python developers grep'ing directories when he admits to
looking through just as arbitrary of a directory. His complaints about random
code execution during import is valid but also seen as a feature _allowing_
metaprogramming. It's just as bad as C/C++ allowing clobbering over memory.

These are features that come with trade-offs. The author is focusing _only_ on
the trade-offs and how they don't exist in his favored language as a reason to
hate the language. That's certainly fine for his subjective opinion but not as
appropriate in a blog post where he is clearly trying to persuade others.

~~~
ArchTypical
> It's just as bad as C/C++ allowing clobbering over memory.

That's a good parallel.

> My point was he's using inexperience and/or familiarity with C/C++ as a
> reason to "hate" it.

I have less familiarity with C/C++ than Python and I hate it because it's not
about language perspective. It's bad language design, for such a high level
language. Inclusion wrapped with execution is unsafe and has an easy fix for
most language interpreters. Don't allow execution during a declaration. If you
want to do metaprogramming, there are other ways that don't break the paradigm
(rewriting files before inclusion, chaining programs, etc).

------
romeisendcoming
This article illustrates amateur hour in many ways.

The whole can't manage my environment and don't understand how to manage the
python thing at all has my sympathy. Python is messy at that level.

With the organizational 'control' sysadmin deprecated by devops and
containers/automation becoming the new norm these types of complaints have to
be dealt with by people who have no idea of what they are doing in generalized
context.

------
mixmastamyk
This article gets worse with every paragraph:

> My code for Python 3.5 won't work with the Python 3.7 installation unless I
> intentionally port it to 3.7.

Probably not. While I can't guarantee there are zero breaking changes, it is
highly unlikely to encounter any from 3.5 to 3.7. Another numerical pair might
have been a better example.

The split between 2/3 was an issue, widely known, and in the past. Personally
I'm glad some big problems in 2 were fixed, though there was some pain.

> When Perl5 came out, a lot of people just switched to a different
> programming language that was more stable.

Nope, Perl 5 was incredibly popular. It was 6 and the two decade wait where
folks jumped ship.

> And I pity anyone who miscounts spaces and accidentally puts in three spaces
> instead of four somewhere -- this can take hours to debug and track down.

Nope, it tells you the first line where the indent is wrong.

> imports: then search every file in every directory

Nope, just type import ... If you want to know which file it found,
print(module).

....

Others have found the other issues. Most of these are nitpicks from someone
who doesn't fully understand or agree with the tradeoffs chosen.

IMHO, the biggest design flaw left in Python is that it is always dynamic and
that's what makes it so slow.

Why too dynamic? Well, changing types of variables isn't used much in
practice. So, to pay a time cost for it on every single line is unnecessary.
If types were fixed by default but let you opt in to dynamic when needed, we'd
have the best of both worlds. Speedy most of the time, dynamic and slow when
actually useful.

Basically whole infrastructures like Cython have been built to correct this.

~~~
a-dub
hah yeah, perl5 was basically perl's renaissance. the web took off and perl
was basically used to glue it all together. they did go crazy with perl6
though, and i think a lot of the reason why python took off was because of the
hole the perl developers left and google liked python.

it seems the performance problems in python can (and are) being fixed. the big
downsides i see are the 2to3 mess (which seems like it will be solved with
time), weak concurrency support in the default implementation and the lack of
the ability to do much real static analysis.

makes for great interactive glue though!

------
mattbillenstein
Stopped at "I'd rather rewrite it in C" \- I guess he's one of those
programmers with infinite time.

Python has its warts, but so do most languages that are almost 30 years old.

------
ezoe
Reason 2 is getting out of hand for Python, Ruby, JavaScript, Haskell and
OCaml.

These so called package manager can't manage packages at all. I'd like to call
it package downloader. They just download everything from language interpreter
to library to a single directory and call it job done. No easy way to remove
the package. The interpreter and library's version is forever fixed.
Theoretically, it can upgrade the version but the user mostly don't.

I really hate their ecosystem.

~~~
bdcravens
> They just download everything from language interpreter to library to a
> single directory and call it job done.

This is scoped to the project in npm. In Ruby, you can specify the path
(common to "vendor" your gems). You can use version managers (like rvm or nvm)
to scope your libs to versions or even named projects (thinking of rvm's
"gemsets")

> The interpreter and library's version is forever fixed. Theoretically, it
> can upgrade the version but the user mostly don't.

I can't speak for all ecosystems, but on Ruby projects I've been a part of,
keeping gems updated is pretty common. Github even includes monitoring for
vulnerabilities to encourage this.

Having been part of ecosystems that don't have package management (for
example, ColdFusion) even the worst package managers are a major improvement.
(Though I do think the isolation of python's virtualenvs is a better approach
than most systems)

------
faitswulff
> Here I am hating on the language I love, but I remember when I would have to
> review this question on StackOverflow every time I wanted to create a new
> virtual environment:

> [https://stackoverflow.com/questions/41573587/what-is-the-
> dif...](https://stackoverflow.com/questions/41573587/what-is-the-difference-
> between-venv-pyvenv-pyenv-virtualenv-virtualenvwrappe) What a mess.

Came here to post something similar, but a commenter on the blog post itself
got to it first. Virtual environments never made sense to me.

~~~
velcrovan
This right here is the biggest problem with Python. I don't see this garbage
in any other programming language.

------
honkycat
I will stick up for this person. I agree with all of the points listed here.
But especially: Python version management and installation sucks.

A while ago I had a broken python ship with my Ubuntu desktop. Pip decided
they were going to deprecate behaviour, and nobody updated or tested on
Ubuntu.

Also it is slow and ugly. Just write it in Golang or something.

~~~
icedchai
Version management is pretty easy to solve: Just use virtualenv and you won't
have a problem. If you start messing around with system level python package
installs, you'll likely make a mess.

As for ugly, I disagree and find Python some of the easiest code to read.
"Slow" depends on the application. For 90% of the apps out there, you're
waiting on something else (network IO, DB, etc.) and it's fine.

~~~
honkycat
I have used pipenv, virtualenv, pip, poetry, xyz. I still have consistent
problems with package versions and the like.

I like the library `invoke` for scripting A LOT, I just prefer to write my
larger software in other languages.

------
superasn
I too have tried it many times mainly because of all the great ML libs for
python but each time I dreaded using it for Reason #3 (Syntax).

Using indents for blocks just seemed unintuitive and error prone to me. But I
dismissed it because all the programming languages I've worked with have had
curly braces so maybe the reason for my discomfort was that it was unfamiliar.

~~~
Symmetry
Most languages that use braces also encourage you to indent the things
enclosed by the braces to make it easier to read. However, people sometimes
make mistakes. For instance I've seen this quite a number of times

    
    
      if (a) 
        somestatement;
        someotherstatement;
      athirdstatement;
    

Which is of course horribly misleading unless you're careful because the
second statement isn't actually conditional on a. Python forces the indent to
match the semantics.

~~~
newen
Does no one have auto indentation in their editors? Every so often I just
select the block of code I'm editing and auto indent it, which matches
indentation with semantics without me having to think about it. Annoyingly
impossible to do this with python since indentation is semantics. It also
results in copy pasting of code being 100 times harder in python than other
languages.

~~~
acdha
That doesn't help with the problem you're replying to – in fact it would
contribute to it.

More generally, yes, many people use auto-indenting and it works in Python in
most editors. It's possible that you're using one where it doesn't work
correctly but that doesn't mean that's true for everyone else.

~~~
newen
It does help with the problem I replied to, which was code written in C. Auto
indenting that code block would indent the `someotherstatement;` line
correctly and I would notice that mistake. Anyway, single line if statement is
a flaw in C's design.

What I said was that in Python's case, if I indent some code block wrong, I
can't just fix the indentation using auto indenting in python, because the
indentation _is_ the semantics. There would be "nothing" to fix and the code
would just run wrong. This problem comes up always when I copy paste python
code. Of course I should notice that it's indented wrongly but that doesn't
always happen. (And please don't advise me to never copy paste code. Life
doesn't work that way.)

~~~
acdha
> Auto indenting that code block would indent the `someotherstatement;` line
> correctly and I would notice that mistake.

In my experience that last part is somewhat optimistic for the implication
that someone would notice it immediately.

> if I indent some code block wrong, I can't just fix the indentation using
> auto indenting in python, because the indentation is the semantics. There
> would be "nothing" to fix and the code would just run wrong.

This is true in some cases — most of the time you'll get an indentation error
instead of it running incorrectly — but also why many editors have an auto-
indent option for pasted code and autoformatters covert things like code which
is consistently indented to match your project's indentation size.

------
rcthompson
It seems unfair to complain that Python 3 breaks backward compatibility and
then also complain about the reason that Python 3 broke backward compatibility
(i.e. broken string encoding in Python 2).

------
preordained
For me, the siren call of Python was the supposed "elegance" (executable
pseudo code!). But then you have these horrible non-composing list
comprehensions (compared to say Ruby where the chain just flows from left to
right instead of getting more and more nested), and that god awful "self" and
"__init__" cruft. It just seems like a poorly designed (and/or evolved?)
language.

It'd be nice if something else would carry the torch for nice AI library
wrapper language...that alone is the only thing that can tempt me touch it.

~~~
zmmmmm
It's such an odd mix of elegance and completely half-assed botched up language
design isn't it? It always feels to me like one of those movies where they ran
out of budget half way through and hastily pasted together the rest of the
script.

------
zmmmmm
Well, I do think Python sucks but those reasons have relatively little to do
with it to me. I just don't like it from an engineering point of view.

\- lack of proper typing - it pretends to have a type system but hardly
enforces it anywhere at least with any of the common practices used by the
community. 'quacks like a duck' is a completely asinine excuse for not
properly using types and interfaces.

\- lack of true multithreading (aka, GIL): if you can't use all the cores on
your computer you drastically limit the scope of applications that can be
implemented. No, I don't want to restructure my application into a distributed
multiprocessing system just to access the basic capabilities of the CPU in my
computer thanks.

\- lack of true cross-platform. partly because of the previous point half of
Python's ecosystem is written in C and needs to be compiled for (if not on)
the target platform. Python tries to pass as a language with Java-like
bytecode but the reality is it doesn't even come close to that. We regularly
try to install Python tools and find that they can't run because some obscure
shared library isn't available on our system, etc.

Mostly, I dislike Python because it seems to be such a trap for new
programmers who learn programming in it and then think they should never have
to learn anything else. Trying to coach people on my team who started with
Python to use or learn anything else is extraordinarily difficult. I remember
when Java was like that and it was ugly then - it's just as bad if not worse
with Python.

------
markbnj
>> Most programming languages pass function parameters by value. If the
function alters the value, the results are not passed back to the calling
code. But as I've already explained, Python goes out of its way to be
different. Python defaults to doing functions with pass-by-object-reference
parameters.

Python passes method arguments by value, pushing them on the stack like every
other language I've used. Because everything is an object in python the passed
_scalar_ values are references (addresses), the objects the references refer
to are on the heap. I sometimes think literally everyone should have to use C
for six months, most of this stuff would stop being debated endlessly.

~~~
brudgers
Everything in Python may be an object in some technical sense. Semantically,
everything isn't. The utility of "everything is an object" is as a promise
that lets programmers write:

    
    
       3.fizzbuzz # returns "fizz"
       5.fizzbuzz # returns "buzz"
       7.fizzbuzz # returns 7
      15.fizzbuzz # returns "fizzbuzz"
    

as is the case with Ruby or Smalltalk. I think that the author's complaints
center around Python behaving like C sometimes and Smalltalk other times.

In particular, some operations happen according to the semantics of types and
others happen according to the semantics of objects. At the lowest levels of
Python, object oriented programming isn't available to do things like adding
methods to Integer.

~~~
civility
Are you after monkey patching, where you can add new methods outside of the
class definition? That's not really a standard feature of all object orient
languages - Java doesn't do that, for instance.

Python integers are definitely objects:

    
    
        (3).real # returns 3
        (3).imag # returns 0
    

Python's lexer/parser made different choices than Ruby's, so the parens are
needed here.

~~~
brudgers
In no particular order

\+ Java doesn't promise "everything is an object." It has Base Types.

\+ Python doesn't make a semantic promise that "everything is an object." Code
for

    
    
      (3).fizzbuzz => "fizz"
    

probably needs written in C because built-in types are closed and object
literals use the built-in types. "3" cannot be forced to use a subclass of
Integer.

At the bottom, '3' is defined in terms of Types (i.e. "Built-in Types") not as
an Object.

\+ Ruby's semantic promise that "everything is an object" means:

    
    
      class Fixnum
        def fizzbuzz()
          if self % 15 == 0
            "fizzbuzz"
          end
          if self % 3 == 0
            "fizz"
          end
          if self % 5 == 0
            "buzz"
          end
          return self
        end
      end
    

And "3" behaves just like any other object. The "everything is an object"
promise means that behavior as an object is a cross-cutting concern (or an
aspect).

~~~
ubernostrum
_probably needs written in C because built-in types are closed_

"Everything is an object" does not necessarily imply "all objects are always
infinitely monkeypatchable at all times". It also doesn't necessarily imply
"you can change how the parser interprets literals".

You're also going to be really mad when you learn about __init_subclass__ and
the fact that Python lets you write a class that can't be subclassed!

~~~
brudgers
Python doesn't make me mad. It's frustrating because it's design never makes
any sense to me.

__init_subclass__ is a perfect example. Not at the level of what
__init_subclass__ does. But that instead of implementing private methods,
there's are rules around double underscore methods _and_ double underscore
methods have different behavior (name mangling). They don't actually make the
method private, the actual name is not the name in the source, and the name is
not anonomized.

I can see a rationale for making some methods private. I can see a rationale
for making no methods private. Python doesn't make methods private _and_ then
deliberately makes it hard to reap the benefits of this design decision.
Instead of implementing the design intent of private methods, what gets
implemented are impediments to utilizing the absence of private methods.

~~~
ubernostrum
Mangling of double-underscore names isn't there to provide access control like
in Java or C++.

Mangling of double-underscore names is explicitly documented as existing "to
avoid name clashes of names with names defined by subclasses". The use case
there is a parent class defines a method called, say, "foo". Other methods of
the parent call self.foo(). Then a subclass overrides foo() but changes the
signature (say, by adding a new non-optional argument), and doesn't override
the other methods that call self.foo(). Without name mangling or something
like it, this breaks. If the parent class either names the method "__foo" or
aliases a copy of the parent class' implementation to "__foo", and calls
self.__foo(), name mangling ensures those calls will find the right (as in,
compatible) implementation of the method based on where the call came from.

That's it. That's the one and only use case for invoking name mangling in
Python, and it's a thing that generally you shouldn't be doing anyway.

Name mangling also _isn 't_ invoked for leading + trailing double underscore
-- a "__foo__()" method would not get mangled.

------
TheAlchemist
All this hate is justified, but not the conclusion.

The libraries available in Python, for everything touching data / scripting
are just so powerful and well thought, that for many small projects, using
Python is a no-brainer. The best thing is that those libraries are actually
incredibly fast, while Python is supposedly slow.

------
PaulHoule
The version problem is Python being a victim of its own success.

Since so many Linux distros used Python 2 for system scripting, you still have
to have a Python 2 sitting around on your system somewhere.

Then people came along with "python3" and (yikes!) "pip3", but now you might
have python 3.4, 3.5, 3.6 and 3.7. The transition was pretty painful because
of the Unicode thing.

It does make it painful, though, to give people instructions on how to use
Python-based software products.

I am converging towards the solution, however, of installing Python straight
from the python web site with the appropriate version, hiding that Python
somewhere where people won't mess with it, then working out of a venv.

Even though I have trouble with the implementation, I like the idea behind
pypoetry. If it were me though, I'd put in a real SMT dependency solver
because you don't need to download a whole wheel to get the dependencies, you
just have to look at the ZIP directory at the tail of the file and you then
grab the metadata file and leave the rest.

When kivy officially supports asyncio and they make it a little easier to
install cross platform (e.g. brew was down for me over the weekend) that will
be nice.

~~~
orf
> I am converging towards the solution, however, of installing Python straight
> from the python web site with the appropriate version, hiding that Python
> somewhere where people won't mess with it, then working out of a venv.

Pyenv[1] is your friend.

    
    
       pyenv install 3.6.4
    

1\. [https://github.com/pyenv/pyenv](https://github.com/pyenv/pyenv)

~~~
PaulHoule
That "shim executable" trick sounds evil to me.

~~~
orf
How so? There are lots of evil tricks at most layers. This one is particularly
effective, and I can't think of another solution to it.

------
raldi
One more for the list, and my all-time most hated Python annoyance: No
equivalent of Perl's "use strict vars". In other words...

    
    
        blah = 1
        if foo:
          balh = 2
        print blah
    

...doesn't let me know I've made a typo the way the equivalent Perl would:

    
    
        my $blah = 1;
        if ($foo)
          $balh = 2;
        print $blah;
    

Which outputs the following even without "use strict vars":

    
    
        Name "main::balh" used only once: possible typo
    

And if you turn that on (like all Perl programmers have, in all their
programs, for decades):

    
    
        Global symbol "$balh" requires explicit package name

~~~
mixmastamyk
Ya know this isn't a bad idea to float on python-ideas. I first thought
pyflakes would flag it, but it doesn't.

Don't think it would hard to implement a warning, without need for strict, as
python already spits various warnings when given non-optimal code.

------
bakery2k
Regarding reason 3 (syntax), I don't mind significant whitespace in itself,
but it has knock-on effects which can be problematic. It's the direct cause of
Python's `lambda` limitations [1], and IIRC the lack of an explicit end-of-
block marker is also the reason for Python not having `do-while` loops.

However, what would be the alternative to significant indentation? I really
don't think C-style syntax would work for Python...

[1]
[https://www.artima.com/weblogs/viewpost.jsp?thread=147358](https://www.artima.com/weblogs/viewpost.jsp?thread=147358)

------
dheerendra73
Reason 5: Nomenclature

That is problem with every single programming language out there.

\- Python array are not called arrays because they are not array in C/C++
sense. It's like saying in C++ lists are called vector and not lists/ArrayList
etc.

\- Python library naming is inconsistent like PyGame, Numpy etc. Most of these
mentioned libraries are third party libraries. How can a language enforce
naming convention or documentation of a library?

\- If you pick all softwares and libraries for all languages, you can't guess
uses for most of them just by name. What are WireShark, TimeMachine, ReactJS,
Boost, Armadillo etc?

------
sevensor
I'm taking this article as a lesson in humility. It's really easy to concoct
specious reasons for hating something, reasons you believe you've backed up
with sound technical and philosophical arguments, but which are really just
rationalizations for your failure to understand it.

------
sidcool
Interesting points. I disagree with Reason 2 though. Python has smoother
installation than Java and GCC.

One of the reasons Python is popular is because it's easy to do a lot of
things. Some python choices don't make sense technically, but they were made
to make python as easy as possible. Performance was never the first criteria
of Python (or ruby). My personal peeve is with mandatory indentation. But
again, that's the idiom the language has adopted.

~~~
camjohnson26
I think the huge volume of 3rd party libraries that Javascript and Python have
show that prioritizing developer experience over technical perfection leads to
a more useful language. I hate Python's quirks but it's the first language I
reach for if I'm just fetching data from an api or doing some web scraping.
It's so fast and expressive that it makes up for the negative parts of the
language.

------
amelius
Author forgot to mention:

\- The GIL (global interpreter lock), which can in some cases reduce your
multicore CPU to a single core CPU.

\- No multiline lambdas. You can't write a quick anonymous closure and pass it
to another function, unless you manage to fit the whole thing in one line.

------
sehugg
I would post "these are very reasonable gripes" but I can't decide whether to
make my string a unicode object or a UTF8-encoded bytes object...

------
altmind
One of my biggest gripe is how python have a hidden non-declared agenda to
have syntax as far from C as possible.

its really not giving language any usage benefits when you cannot use ternary
expressions, ! as not, !=, increment operators.

Also, PEP8 is very very presriptive, you are disallowed to do violate any
rule, even when if you need to to make the code better. (I feel shunned by the
community for not liking 80 chars line hard breaks)

Python3 migration was not planned well - the lack of back and forward
compatibility gave users a legit reason to stay with python 2 forever. I've
seen some conference talks where end users/projects being shamed for not
jumping on python3.

GIL in python is something that was talked about 5 years ago and will still be
talked in 5 years. It limits the ability of python to reap the benefits of
better hardware.

This may be minor, but I really missing ruby rich set of collection methods:
take_while, group_by, sample. Yet I can see a point in extracting that to a
external library.

Of course, all this does not mean python is not good. Builtin pip/venv,
adrequate unicode in python3, some of fantastic libraries(numpy/scipy, bokeh)
making it indispensable.

~~~
acdha
> GIL in python is something that was talked about 5 years ago and will still
> be talked in 5 years. It limits the ability of python to reap the benefits
> of better hardware.

It's also a huge source of misattributed problems — I've seen more cases where
a complaint about the GIL was really “my algorithm depended on a single locked
data structure” or “I was calling a C library which isn't thread-safe” than
where the GIL was actually the limiting factor. That's not to say that there
aren't real problems for people who want to run pure-Python computational code
(not e.g. libraries like Numpy or Pillow) but it also seems to be popular as
the bogeyman to blame when someone doesn't want to run a profiler.

> This may be minor, but I really missing ruby rich set of collection methods:
> take_while, group_by, sample. Yet I can see a point in extracting that to a
> external library.

See
[https://docs.python.org/3/library/itertools.html](https://docs.python.org/3/library/itertools.html)
and
[https://docs.python.org/3/library/random.html](https://docs.python.org/3/library/random.html)
for the sample function. I believe the difference is mostly that the Ruby
methods are on Array but the Python ones are seen as processors for iterables
so they're in a separate part of the standard library.

------
booleandilemma
I feel like Python is a case of the emperor’s new clothes.

In this case the emperor has no visible scope delimiters.

~~~
KMag
The counter-argument is that in practice, most programmers use the indentation
of the first non-whitespace character on each line to estimate lexical scopes,
which is why removing all indenting drives most programmers wild.

I've seen several bugs in C++ and Java where colleagues have indented the code
for the correct control flow, but misplaced the curly braces, resulting in
incorrect flow. Granted, the two bugs that come to mind first are dangling-
else problems that were fixed by inserting the optional braces.

I think that you and I both prefer auto-formatters to force indenting to match
flow control. However, there's an argument to be made for actually enforcing
it at the language level rather than at the tooling level.

------
giffarage
Of all the things to “hate with a passion”, choosing a programming language
sounds miserable

------
carlsborg
* Versions and installation: Consider doing all dev work in a virtual env. It installs the correct python interpreter on your PATH, and installs pips in that isolated env.

$ python2.7 -m virtualenv .venv or $ python3.6 -m venv .venv

$ source .venv/bin/activate

// dev + test here

$ deactiveate

> This worked great until I started on a second project that needed Python
> 3.6. Two concurrent projects with two different versions of Python -- no,
> that wasn't confusing.

Note that Java also comes in various version of the compiler and jvm, and its
common to have several versions on the same system. They are backward
compatible but forward compatibility issues exist: your main server app runs
on java7 but your batch process is running java9. you might not want to make
java9 the default on the system without formally upgrading the server app.

* Syntax/spaces : you get used to it. Hey some people write code in perl :)

* Includes: In principle, this works somewhat similar in Java: You use imports and the imported package hierarchy can nest quite deep so you need to look.

> The import function also allows users to rename the imported code. They
> basically define a custom namespace..

This can be a good thing, it helps you prevent name clashes. C++ also lets you
do this, its called Namespace aliases.

namespace fbz = foo::bar::baz; std::cout << fbz::qux << '\n';

* Nomenclature:

> In every other language, arrays are called 'arrays'. In Python, they are
> called 'lists'.

Thats because it is a list. Nodes are dynamically allocated and appended to
the list. You can expect similar algorithmic complexity for the operations.

Python also has arrays if you want the better efficiency:
[https://docs.python.org/3/library/array.html](https://docs.python.org/3/library/array.html)

* Pass By Object Reference: same as java

------
woodrowbarlow
> if I'm testing a screen capture program with a C library called
> "libscreencapture.so", i would call my program "screencapture.c" and compile
> into "screencapture.exe"

author must be running an unusual OS.

~~~
Kliment
I've seen ELF executables with .exe suffices (as well as .run, .bin, no
suffix, etc etc, I'm just waiting for someone to name one .com). This was done
specifically to distinguish them from a directory of the same name.

------
drugme
_If I have the choice between using some pre-existing Python code or rewriting
it in C, I 'd rather rewrite it in C._

Go ahead, get your jollies and rewrite it in C.

But will anyone else be able to read it and maintain it? That's the core
issue.

------
leshow
A lot of these gripes are unfair and don't really matter IMO. I think
complaining about things as trivial as syntax is really just scratching the
surface and doesn't serve your conclusion.

A dictionary is an interchangeable word with hashmap in most situations. The
string 'quirks' actually look to be pretty helpful.

Gripes I do actually agree with: the schism in versions, mutation from pass by
ref (although this isn't different from JS, Java or any other OO lang). In my
opinion you can add OOP in general to the list of gripes against python.

------
VectorLock
A lot of these "problems" are things I love about Python.

I complained about the whitespace thing back in 2002 before I really loved
Python too.

And trying to make out poorly named projects as a Python issue? Please.

------
ApolloFortyNine
>By the same means, Python has distinct silos of code for each version. And
the community keeps dragging along the old versions. So you end up with a lot
of old, dead Python code that keeps getting dragged along because nobody wants
to spend the time porting it to the latest version. As far as I can tell,
nobody creates new code for Python2, but we drag it along because nobody's
ported the needed code to Python3.x. At the official Python web site, their
documentation is actively maintained and available for Python 2.7, 3.5, 3.6,
and 3.7 -- because they can't decide to give up on the old code. Python is
like the zombie of programming languages -- the dead just keep walking on.

I think I could make a comment on every one of this authors 'gripes' but I'll
just do one for now.

Does this author think a minor version update should immediately EOL the
previous version (3.5,3.6)? And obviously this author never heard that Python
2.7 is EOL 2020 [1]. But you know just reading this author's problems that if
Python 2.7 had been EOL right after 3 released, or if a minor version upgrade
immediately EOLs the previous minor versions (seriously, how is this a
complaint?) he'd be posting about that instead of these 'which version do I
choose' issues.

I just honestly can't believe a developer would complain about maintaining
code for 'too long'.

[1]
[https://legacy.python.org/dev/peps/pep-0373/](https://legacy.python.org/dev/peps/pep-0373/)

~~~
lmm
> Does this author think a minor version update should immediately EOL the
> previous version (3.5,3.6)?

More likely the author thinks minor version updates should be backward
compatible, like they are in virtually every other language? In most languages
you'd be able to uninstall 3.5 when you installed 3.6, because you'd be
confident that all your 3.5 code would keep working in 3.6.

~~~
Hello71
Except... they mostly are? As far as I can tell, Debian only ships one Python
per major version per release, Fedora does the same, Arch does the same.
Gentoo lets you install everything side-by-side, but it does the same thing
for gcc, binutils, ruby, wine, llvm, and dozens of other packages, and I don't
see the author complaining about those.

~~~
lmm
Well, it sounds like this author's employer required their devs to use
multiple minor versions at once:

> I was advised by one teammate that I needed to configure my environment so
> that everything uses the Python 3.5 base. This worked great until I started
> on a second project that needed Python 3.6.

Might be an issue specific to that company of course.

~~~
ApolloFortyNine
I think that whole paragraph he mixed up python 2 and 3.

>However, Python installs in separate installations. My code for Python 3.5
won't work with the Python 3.7 installation unless I intentionally port it to
3.7. Enough Linux developers have decided that porting isn't worth the effort,
so Ubuntu installs with both Python2 and Python3 -- because they are needed by
different core functions.

The way he just segways from talking about 3.5 to 3.7 seems really unnatural,
I think he's talking more about from python 2 to 3, since that's what the
second sentence is about. All code from 3.5 should work 3.7, unless they were
using some undefined behavior of some sorts.

A quick google reveals python 3.6 is fully backwards compatible with 3.5, and
3.7 has only 2 exceptions. The words async and await are now reserved. So even
if he did have a problem with this, any ide, or even just a find replace in a
text editor, would be able to refactor the 3.5 code to work.

>[https://docs.python.org/3/whatsnew/3.7.html](https://docs.python.org/3/whatsnew/3.7.html)

~~~
lmm
> All code from 3.5 should work 3.7, unless they were using some undefined
> behavior of some sorts.

Interesting; that certainly wasn't always the policy (e.g. I remember 2.4 ->
2.5 being a major, breaking upgrade) and maybe his employer never got the
memo. If it's now the case that you can do fearless upgrades between minor
versions then maybe that just needs to be better advertised.

------
qwerty456127
Looks more like a proof Python is near-perfect to me. Because they've tried to
write a list of what's wrong with Python and failed to name a single real
problem/quirk you even have to know about. I've seen lists illustrating how
JavaScript, PHP, C++ and other languages are bad and they all made me feel
like "that's so crazy I will never code this language!" but this list for
Python is just "pff... will you name a single thing that is not a minor
inconvenience?".

The only thing that really annoys me about Python as a language (and it still
is just an inconvenience and a matter of taste) is the file=module thing, I
want to split a module into a number of files so I could define every class in
a separate file without having to import every one from a separate module
then, C# namespace model feels a way better. I would also love to see 1-st
class support for type enforcing (i.e. if I define a "type hint" and a value
fails to comply to it should raise a warning) and support for immutable
variables (that can only be assigned once). Using 4 spaces per indentation
level indeed sucks (I would prefer 2 spaces) but this is not a language
problem and its seriousness is futlie.

------
CiPHPerCoder
> Inevitably, the discussion will turn to programming languages. One might
> lament "I have to modify some Java code. I hate Java. (Oh, sorry, Kyle.)"
> (It probably doesn't help that we gave Kyle the nickname "Java-boy" over a
> decade ago.)

This circle of "friends" sounds like a toxic environment where apologies are
empty and contempt runs rampant.

Are they _truly_ sorry for what they said, or are they sorry they said it to
Kyle's face?

------
IvyMike
His early history of Perl is at odds with my memory. In my memory, perl was
pretty great with not breaking old stuff. Even the pretty amazing feature set
added between perl4->perl5 seemed a natural evolution to me.

[https://en.wikipedia.org/wiki/Perl#Early_versions](https://en.wikipedia.org/wiki/Perl#Early_versions)

(P.S. yes yes perl 6 went kookoo crazytown, but that's not what he was talking
about.)

------
jcranberry
I don't often use python nor do I know it well but it's obvious to me that
several of these points are stupid, misinformed or wrong. Numbers 3, 5 and 8
are just nonsense whining. Number 7 is terribly wrong.

I find it incredibly surprising that this person got a Computer Science PhD
while confusing Python lists with arrays and not knowing that pass by
reference semantics is by no means niche.

------
rafiki6
I used to hate python because of of the lack of static typing. I realized the
reason I hated it because of that, was due to other people's bad code. One of
the nice things with compiled languages that are statically typed is that
there's that nice check up front for types. I actually think you need to be a
really good developer to properly use dynamically typed languages.

------
GuB-42
The one good thing with Python is that it is great at making beginners write
readable code. I had nightmares about code written by scientists who certainly
were experts in their fields, but their coding skills were limited to the bare
minimum for running their calculations, once.

With python, not only their code is readable, but they also enjoy using it.

For more advanced programming however, it is a mess, and I understand the
author. It limits your option so that there is basically only one way to do
things (the opposite of Perl), it makes it annoying to write since even debug
code needs to comply. But on the other hand, it gives you constructs that are
very permissive. Pass by mutable reference is an example: there is no easy way
to know what will happen to your arguments. You can completely modify just
about anything so that even simple operations can do really weird stuff in the
background. Flexibility is nice but it feels strange for a "clean" language to
let you mess things up so deeply with very little safeguards.

------
arduinomancer
What is he even trying to say in the pass by reference part?

Does he want the language to automatically deep copy objects every time
they’re assigned?

------
yellowapple
I also rather strongly dislike Python (which tends to be a problem given that
my employer's engineering team uses Python for everything, whereas I very much
prefer to use the right tool for the job - which might be Python sometimes,
but not often, let alone always). Whitespace-sensitive languages are - in my
opinion - not at all user friendly, and the quirks around passing variables by
object reference (like how you should never do "def foo(bar=[])" unless you
_want_ bar to equal [1,2,3] when you call foo() after having previously called
foo([1,2,3])) make JavaScript look somewhat sane.

I will say, though, that I don't mind Python calling things lists and dicts.
Those are indeed common terms (both are used in Erlang/Elixir), and reflect
the fact that there are multiple possible implementations (lists might be
arrays, linked, double-linked, etc., and dicts might be hash tables, keyword
lists, etc.).

------
Gatsky
Interesting to compare R on these specific pain points. I’m ignoring 5,6 & 8
because they are silly (you have to learn the language to use it at the end of
the day).

1\. Versions.

R gets updated quite frequently, and most users just update regularly. It is
rare for there to be breaking changes. Packages often require the latest
versions of R, so that is an issue.

2\. Installation.

Well on linux distros R often has the same problem, you install R with the
package manager and it isn’t clear which version it is. Some additional config
is required to make sure you get the latest version. This is explained on the
R core website. On windows and Mac, this isn’t an issue.

3\. Syntax.

If you don’t like indents then R is your friend. The syntax is pretty flexible
compared to python. For data science this is a plus in my book.

4\. Includes.

In R, for larger projects the issue is dealt with by turning your code into a
package, which is quite neat and tidy.

7\. Pass by object reference.

R functions default to pass by value. You can still mess around with global
state if you want to complicate your life.

------
Symmetry
I agree with a number of these but I really don't understand #4. If you want
to know what's in a module then 'import foo; help(foo)' in your interpreter
will give you it. In C you can't just grep /usr/include because you might be
importing form somewhere else.

And in C everything goes directly into your main namespace, the equivalent of
'form foo import *'. And even with single letter renames you can just quickly
check at the top of the file for what the rename is, 'gg<c-o>' in vim and
probably similarly easy in most people's editors. And really importing common
libraries as single letters should be by convention in a codebase.

I really think that Python's import story is one of my favorite things about
the language and it's something where I'm often comparing other languages to
Python and finding that they're coming up short.

~~~
breatheoften
There's so much incidental design exposed to the user/library author because
of python's import system ... Ultimately you have to step through a large list
of questions in order to understand the actual import behavior -- its not easy
and adds a large (pointless?) cognitive load for every library user/author ...

Are you import'ing a Module or a Package? If it is a package then maybe
there's a magic file called __init__.py in a directory that might have an
__all__ = [...] array or might just import some other modules but not contain
an __all__ or it might import some names from some other modules. Or maybe
there's a namespace package somewhere which has some behavior when there are
directories that contain .py files but don't have an __init__.py (I honestly
don't know the rules -- but I do know they can't be explained to me in a small
number of words and that makes me insane!) ... And by the way -- every
instance of 'import' used throughout your program is additionally beholden in
its behavior to a global runtime magic state magic called the PYTHONPATH (that
often has to get munged from the shell environment prior to invoking a python
program ...) which is a list of path's that will be consulted/augmented
differently depending on whether its a (module/package/namespace) import
search to ultimately decide which set of files will be inspected ...

As a half-assed python developer (who is firmly in the 'I hate python camp') I
honestly have very little idea how you are 'supposed' to use these mechanism
when defining a package. I recently tried to figure out actual best practices
so I could publish a small package -- I relied on lots of boilerplate copying
from what seemed like knowledgable sources. I think I got something vaguely
workable
([https://github.com/breathe/NotebookScripter](https://github.com/breathe/NotebookScripter))
but there's a lot of line noise all throughout the filesystem layout ... What
is it about my Project name that python demands I should repeat it in the
filesystem over and over and over again?

I believe this is actually the common pattern for laying out a small library
...:

Project/setup.py Project/Project/__init__.py
Project/Project/SomethingToDoWithProject.py

------
paavoova
Not mentioned under quirks/syntax:

\- Special-snowflake, verbose ternary syntax (expr if cond else expr)

\- (De)evolution of language features over time, such as format strings (from
"%s" % val to "{}".format(val), and now to format strings f"{val"

\- Poor design decisions all around, and stubborn in its refusal to admit
wrong, such as the sudden but long overdue addition of assignment expressions

\- Lack of control flow like switch statements, leading to data-structure
abuse e.g. via dictionaries

The recent addition of assignment expressions provoked much discussion and
much effort into its proposals, but, outside of Python's echo chamber, it's a
language feature that most other languages have, and that should have just
been included from the beginning. Instead, decades after the fact, the
language is tacking on the syntax and pretending it's some genius new feature.

------
jhuni
One note about point (2) dealing with the versions and the languages object
oriented features. I noticed the object-oriented support has been tacked on,
before Python 2.2 the objects had their own type which was accessed by
.__class__. The tacked on nature of the OOP support of the language is perhaps
why there are these __identifiers__ which are hard to type using consecutive
letters, needing shift to be held down, are still used in the language.
Although Python fixed the problem partially, it only did so only by adding new
style classes along the old style ones in order to avoid breaking
compatibility, which only complicated the issue. Unfortunately, Python 2.7 is
still around. As this post mentions, Python 2.7 & 3 are both installed on
Linux machines and the default is still Python 2.7 when you type python.

------
dangom
Actually, PyPI and PyPy are pronounced differently. The former is pronounced
Pie-Pea-Eye, whereas the latter Pie-Pie.

"PyPI (Python Packaging Index): said aloud by using its full name, or by
spelling out the last two letters, as in "Py-P-I". Alternatives are to
abbreviate as the "Packaging Index", or to use the colloquial nickname "the
Cheese Shop" (which refers to the name of a Monty Python's Flying Circus
sketch). Referring to the packaging index aloud as "Py-Py" is strongly
discouraged, as "PyPy" is the name of a popular alternative Python
interpreter."

See, for example, [https://github.com/pypa/python-packaging-user-
guide/issues/8...](https://github.com/pypa/python-packaging-user-
guide/issues/89)

------
firefwing24
People hate on spacing, but people rarely talk about the benefits that
specific spacing has.

Yeah, sure, you can complain about how _strict_ it might be, and complain
about how it can cause bugs when something is mis-indented.

But it's not like brace-languages are perfect either.

How about people who mix tabs & spaces within a single line because of lack of
discipline or maybe a mistake from refactoring code? Imagine that nightmare of
rereading that based on what editor you use.

Missing braces can sometimes be annoying and difficult to find, and placing
the brace in the wrong place can result in bad code. Isn't that equivalent to
a lingering whitespace in Python?

Yeah sure, you might say "Once you code enough, that usually doesn't happen"
But Pythonistas can say the same thing with their indentation.

It's just a different way of programming. Get over it.

~~~
cageface
The more serious issue with significant white space is that it makes writing
code formatting tools like Prettier impossible. That’s too much to give up to
avoid having to write an extra brace or two IMO.

~~~
minusf
heard of black?

------
Lazare
About 1/4 are valid, important criticisms, another 1/4 are technically true
but quite trivial (and are mostly caused by his very idiosyncratic coding
habits), and 1/2 are just howlingly wrong, mostly in that order. A decent
chunk of the actually correct ones seems to boil down to "C does it
differently", which well...if that's you're yard stick, you're going to be
pretty busy criticising other languages.

I've got to call out his point 7 in particular; it's so wrong it kind of makes
me wonder what he was trying to say. He's calling out Python for not following
a convention that doesn't exist, nobody else follows, couldn't even work, and
which you wouldn't even want. What in the world?

~~~
mark-r
Point 7 is only relevant because it leads to behavior that's not intuitively
obvious. If you _reassign_ an object in a function then it's not visible
outside the function, but if you _modify_ the object it is. That's a very
subtle distinction.

------
androidgirl
For one and two: in what world is any of the software in repos like apt or yum
up to date?

Every time I set up an ubuntu machine for using at work, I end up compiling a
few packages from source, a myriad of packages that are installed from app
images or curl | bash installed binaries (like docker, ugh), and more PPA's
than I care to keep track of and clean out. And now there's flatpack,
snapcraft... packaging on linux is a mess currently.

Honestly, on workstations the rolling release model is the only one that makes
sense.

But for python, with tools like pyenv, virtualenv, or even just using
LXC/docker/vagrant/whatever, versions in the 3.5-3.7 range are a non-issue.

I agree the quotes thing sucks, though. I wish there was more enforced
discipline on that.

------
smt88
I'm flagging this not because I disagree, but because there's nothing new or
insightful in the article and the headline is just flamewar bait.

I'd love to see a deep dive from an expert on why Python sucks, because I
truly hate Python, but this isn't it.

------
Annatar
While I agree with the author's reasons why Python sucks ass, he's wrong about
Commodore but thinks that he isn't:

"Where's Commodore today? It died out as users abandoned the platform."

No. Commodore died because Irving Gould told Tramiel to pack his bags and go
when Tramiel told him it wasn't okay to use company's assets like the jet as
personal property. Once Tramiel was fired, the company was plagued by chaos
and mismanagement, but it had nothing to do with how bad or good Commodore's
computers were. It's the 21st century and people still write fresh software
and design modern hardware for Commodore computers, so they've never been
abandoned.

~~~
DerekL
He gets so much wrong in that paragraph:

> Commodore created one of the first home computers (long before the IBM PC or
> Apple).

Commodore, Apple and Radio Shack all released home computers in 1977. Six
months is hardly “long before”.

> But the Commodore PET wasn't compatible with the subsequent Commodore CBM
> computer.

He must mean the CBM-II, because the original Commodore CBM machines were just
rebranded PETs.

------
rafaelvasco
I can only agree to his hate of spaces. I personally hate space based
languages. It only brings annoying problems and you have to care for things
(spaces/tabs) that you shouldn't have to care about in the first place. {}'s
-> Love.

------
mindcrime
I don't think the author of TFA makes the case he's trying to make at all. And
mind you, Python isn't my first or favorite language, and I'm not particularly
biased in terms of defending Python. My language of choice is Groovy in most
contexts.

Anyway, this all seems like a lot of nit-picking to me. Yes, these "issues"
are real, they just don't amount to much. And basically _every other language_
has an equally long list of similar nits you could pick.

If the author had called this "Reasons Python Sometimes Annoys Me" then I
could get behind that. But none of this, IMO, reaches of the bar of
establishing that the language "sucks".

~~~
mixmastamyk
Right, Python is better than most in terms of nitpick-ability. It's one of the
only mainstream languages to make it big without corporate support due to
that.

------
drosan
Loud title for an article from a person who has little to none experience with
real life programming (imho). Talking about passing objects as a copy or by
reference looked plain retarded even, he barely understands what are
advantages or disadvantages of both methods.

When I went down to reason 8 I was already utterly disappointed and felt like
my time was wasted on a ramblings of 13yrs old that wrote "hello world" in 2-3
different scrypt languages and already thinks of himself an expert and a
_hacker_ (that's even in the website title).

Too bad it is a senior citizen that some people might have actually listened
to and think he know what's he is saying.

------
metaculus
Though it's an opinion piece and I don't agree with all the points, some I do.
The readability issue is real when dealing with any code more than a hundred
line, and worse the convention seems to encourage using empty lines very
sparingly. The shortcomings came out clearer as I've been teaching someone to
program in Python. The subtlety of per-scope indentation really confused her.
The concept of a "block" is just not visually clear. Not to mention mixing
spaces and tabs by accident. That could halt a new programmer for an hour.

------
projektfu
The random complaint about Perl version compatibility was particularly
bizarre. There was really no incompatibility between Perl 3 and 4. Then I
guess all those people got fed up and quit using Perl when they made the next
version and it was left in, what? a 15 year glory period where several orders
of magnitude more software was written with it?

Talking about how there's very little new software written in Perl now is
definitely using post-hoc reasoning. There's probably a language named after a
British comedy troupe that is somewhat responsible.

------
tanin
Coming from Ruby, I encountered this funny situation in Python.

I was looking how to get first element of an array or get nil if the array is
empty.

Python library doesn't provide this kind of functionality.

[https://stackoverflow.com/questions/363944/python-idiom-
to-r...](https://stackoverflow.com/questions/363944/python-idiom-to-return-
first-item-or-none) offers multiple ugly ways of doing it.

For Ruby, we use `.first`.

In Ruby, the standard library is richer. A lot of libraries are "official"
because Rails uses it.

------
lajun
I can't believe this was upvoted. These aren't reasons that Python sucks,
they're nitpicks from a guy who has decided long ago that he knows what he
likes and refuses to try anything else.

> "If I have the choice between using some pre-existing Python code or
> rewriting it in C, I'd rather rewrite it in C."

I should have stopped reading there, because this shows just how set the
author is in his ways. Both languages have a place, and if I'm writing a web
scraper, you can bet your ass it's not going to be in C.

------
turlando
>The Python manual says that you can use any number of spaces or tabs for
defining the scope.

But it doesn't. In Python only modules, classes and functions make a new
scope. A block doesn't. (And that's because it "forces" you to write small
self-contained functions.)

It's funny that he also links to a documentation page that clearly doesn't
talk about scope at all.

Personal reflection: I rarely rant publicly about something, but when I do I
make sure that I'm not saying something stupid that a quick google search can
refute.

------
nurettin
As a python newbie, I've had some trouble with the unstable async API (many
differences between 3.6 and 3.7 and within minor versions of 3.7). Many ways
of accomplishing the same goal with slightly different side effects are off-
putting.

Another problem is packages. Authors don't really care about fixing dependency
versions (had trouble with celery, quart and redis so far) we have much less
trouble with node in this respect.

plus sides are: vs code has been amazing. pipenv is almost good enough.
Community is great.

------
sli
> And Python? It uses spaces. If you need to define a scope for complex code,
> then you indent the next few lines. The scope ends when the indent ends.

Curiously, I never see the indent scope complaint about, say, Haskell. It's
always just Python. I've wondered for a long time why that is. There's the
obvious one, that Python is just far more popular, but I'd expect experienced
people to have used or at least seen another language that does it.

~~~
the_gastropod
No idea if this is true, but my gut feeling is Python is commonly written in
an imperative style, whereas Haskell is more functionally written. Imperative
style (especially at the beginner level) tends to include lots of nested
conditionals which quickly create this indentation triangle of confusion.

------
Agathos
As far as I can tell, nobody creates new code for PostgreSQL 9, but we drag it
along because nobody's ported the needed code to PostgreSQL 11. At the
official PostgreSQL web site, their documentation is actively maintained and
available for PostgreSQL 9.4, 9.5, 9.6, 10.6, and 11.1 -- because they can't
decide to give up on the old code. PostgreSQL is like the zombie of relational
databases -- the dead just keep walking on.

------
luord
> because someone thinks recursive acronyms are still funny

Not that I was expecting depth from a site called "hackerfactor" by a guy who
wrote something like "open source sucks", but seriously, this middle school
level "sass" (and about a popular practice at that) shouldn't be near tech
writing.

Should have stopped reading there. On that note, this has way too many upvotes
for such a misinformed, badly written, sophomoric piece.

------
pmarreck
Elixir has none of these faults, so I guess I will continue to enjoy using it.

Lists and arrays are fundamentally different beasts, though. Shouldn’t most
coders understand that?

------
exabrial
Python: something you can't see causes significant change in program behavior.

Go: Something you see ends up as a compiler error.

Oft heard is the bellyaching cries of the proponents that try to conflate
these two things, but they are not the same thing. One results in bugs, the
other can be bypassed. Most languages opt for the second. (With Java for
instance, most shops have a checkstyle gate in their build process).

------
corydominguez
I agree with a lot of these points. To get around them I created
[https://github.com/c11z/python-mk](https://github.com/c11z/python-mk) which
is a make file that contains the seed of a python development environment. It
uses docker containers to get around most of the issues this article brings
up.

------
SamWhited
I tend to agree with the author (although not with a few of his specific
reasons) that Python is terrible. Everywhere I've ever been that used Python
they've claimed it was to make development faster, but mostly we just fought
with bugs that cropped up around tests that were too aggressively mocked and
weren't testing things, or stuff that somehow was in the wrong scope because
someones editor was using the wrong type of whitespace, etc. And don't get me
started how on every single code review I had to force people to write unit
tests that wouldn't have to exist if there was a static type system to
effectively be those tests for us.

That being said, if your alternative is C or PHP suck it up and stick with
Python. There is no situation in which PHP is the appropriate tool for the
job, and as simple as C is and as much as I love it you're much more likely to
introduce weird bugs and create broken software if you're using C. Python at
least has some basic memory safety, even if its tooling and versioning is all
horribly broken. As a user of software (and also a devloper): please stop
writing things in C and related languages, if I keep seeing segfaults in
popular products with huge QA teams behind them, I'm going to go insane.

~~~
tabtab
Re: _There is no situation in which PHP is the appropriate tool for the
job..._

While clunky as a language, PHP's "environment" is better if you are doing web
apps. Easier to install, including a test setup, more web-oriented libraries
and functions, and a built-in HTML templating language for "view" pages (per
MVC).

If your stack is designed right, you'll be spending most your time plugging in
parameters to API's such that the language itself won't make a whole lot of
difference. You should be mostly gluing libraries, not writing an OS from
scratch. If I were doing the second, then Python would be the better choice.

~~~
SamWhited
If you're doing web dev it just makes it easier to write crap. I am also
utterly sick of pentesting every garbage website written in PHP and finding
dozens of easily avoidable bugs that always boil down to PHP being terrible at
what it does. It may be easy to use, but that's no excuse to use it and write
bad software.

~~~
tabtab
They probably copy and pasted decade+ old code floating around that was
written before Php wised up about security.

~~~
SamWhited
It doesn't matter that PHP has wised up about security; I've seen modern PHP
too, the language is still a mess and encourages bad practices and bad
engineering.

~~~
tabtab
Top 3 examples?

------
Chazprime
There certainly are some drawbacks to using Python versus another language
like C (I’m thinking of the GIL in Python 3 specifically), but I’ve yet to
find a better language with which I can prototype reasonably complex
applications in the space of an afternoon...even GUI apps with Qt.

------
golergka
> In contrast, many Python modules include initialization functions that run
> during the import.

I just thought it's a natural consequence of a dynamic languge. Defining a
class IS running code - you can even decide to define or not to define
something based on a runtime random roll.

------
mothsonasloth
Deep inside every Python developer is a frustrated Java dev waiting to come
out...

 _i just made that up_

------
zzo38computer
I thought I was the only one to put debug code in the first column. (The code
doesn't last long; generally debug code in the first column is expected to be
removed very soon; debug code that lasts longer goes in its proper column.)

------
projektfu
C and its standard library have some consistency and C89 code mostly runs on
future versions of the spec (provided they don't use something like _Bool).
But the idea that you don't run into version hell in C is crazy.

------
chasedehan
(2) —> virtual environments.

------
calhoun137
At the end of the day the thing that makes Python the best programming
language is not actually the language itself, which has a lot going for it,
but the community around it. The python community is the full of extremely
good programmers, and there is a vast ecosystem of first class resources that
are available for everyone.

Yes, these are all valid points, and I laughed. Holding up javascript (npm
anyone?) as some kind of counter example that proves python is bad may have
held some un-intentional humor as well. Don't get me wrong, I love js but it
seems to me like if you took these same 8 points and made them about
javascript it would be 100 times more damning.

Heck, I am even willing to count this great article itself as a reason to love
the python community even more. Someone who hates python so much must do so
from a place of extreme love.

------
nickthemagicman
I personally do not think python is more readable than other langs.

Making a language more Englishy, does not make that language more readable.

I still have to learn what the hell the syntax is trying to express except the
English makes it more verbose.

------
perrychan
You are right! Any language has its disadvantages. Btw, I'm very interested in
which programing language you're using mainly? Would you like to share with
us? Thanks in advance ^_^

------
abcmer
Bill and Neal? Are these the geeks from Freaks and Geeks all grown up?

------
davesque
I feel like it's sadly telling that such a poorly written article has managed
to sucker at least 175 HNers into up-voting it (assuming that's how the score
system works).

------
hyperbovine
If someone forced me, an avowed Python lover, to write 1000 words about why I
hate Python, I imagine it would turn out something like this article.

------
mark-r
Why hasn't somebody come up with a code editor that shows left-brace or right-
brace in the left margin when the indentation changes?

------
rienbdj
I don’t like Python, but not for the reasons given.

My dislikes:

\- no pipe operator \- no type checker (something Flow would do) \- over
dependence on whitespace syntax

------
dbllxr
> And Gawd forbid you make the mistake of running 'sudo pip', because that can
> screw up your entire computer!

virtualenv is your friend.

------
commandlinefan
There are two types of programming languages - the ones nobody uses, and the
ones people complain about.

------
lindbergh
Python is like democracy. It's the worst programming languages except for all
the others.

------
jancsika
> PyPy, PyPi, NumPy, SciPy, SymPy, PyGtk, Pyglet, PyGame...

pyimport pygame

Name two things wrong with what I wrote above.

------
agounaris
Yea you cannot do molecular meta-dynastic micro transdusevelociraptatable
programming

------
est
These are the reasons why python sucks?

Gosh python must be a pretty good programming language.

------
jimnotgym
I'm not even sure his pronunciation anecdote is true.

Pypy is pronounced pie-pie

PyPI is pronounced Pie Pee-Eye

Isn't it?

------
nicodjimenez
For scripting, there's nothing better than Python (that I know of).

------
reachshabib
Love it or hate it, python is here to stay for a really long time.

------
jonnycomputer
import numpy as n

seriously? the community norm is:

import numpy as np

and because its a norm, nobody is confused. But the author certainly is.

the whole list of complaints basically exposes his basic lack of familiarity
with the language.

------
kekeblom
The thing that actually sucks is in python is parallelism.

------
Koshkin
Strong opinions usually come from a lack of experience.

------
SilverSlash
How does this garbage make it to the front page of HN?

------
bribri
if you could only chose one language for server side "web apps", would you
choose python or javascript?

------
trumped
for me, the main reason why python is not as good as it could be is because of
the slow interpreter

------
minimidge
_nods head and agrees_

But I still love Python XD

------
KK89
I dislike python but I use it sometimes. I love Matlab, and I usually use it.

------
Nickersf
Someone's mad at some python code and needed to vent.

------
triMichael
My take on this is that it has some valid points, but is mostly unjustified
rants:

1\. Versions: Definitely an issue with Python, the v2 to v3 split was a huge
mess and is Python's biggest issue IMO.

2\. Installation: Pros and cons, what I find is that Python tends to be easy
to set up, but that it does it automagically for you via pip, which means if
you run into trouble it is harder than doing it manually

3\. Syntax: Python's syntax is wonderful and I find these arguments mostly
flawed. The space vs tabs wars are the exception and a valid criticism that
the language doesn't force one or the other. As someone on the tab side, I
don't run into his issue at all of accidentally putting 3 spaces instead of 4
in, but then I do run the issue of going against the language's grain so to
speak.

On the other hand, his issue about deep nesting is a problem in any
programming language - unless he is not indenting properly when he wants to,
which is my guess. If that is the case, that will cause severe issues when
anyone else tries to read it! Debug code without indents also sounds like a
bad idea to me. And even if you aren't a fan of Python's whitespace, I find
that there are other features, such as using words instead of symbols (and,
or, not instead of &&, ||, !) that definitely make Python one of the most
readable languages out there.

4\. Includes: I'm mixed on this one. On the one hand, I don't understand the
first half of what he is saying, I have to go track down includes in any
language. In Python at least I only have to deal with one include, whereas in
C and C++ I have to go track down two, the header include and the actual
library. This mostly seems to be complaining for the sake of complaining.

The last bit I personally agree with though. I once worked on a project that
would analyze other people's Python code. At first Python seemed to do this
extremely well as it can take any Python code and change it into its abstract
syntax tree for further analysis. However, I soon found that in order to do
this, it would have to execute any global code while it was reading it! I'm
definitely not a fan of how Python technically runs anything it imports.

5\. Nomenclature: Definitely unfair criticisms here. First, Python's lists
aren't arrays but are lists! Arrays are blocks of unchanging memory, whereas
lists are a structure that under the hood points to an array, but that array
can be deleted and reallocated to resize it. I admit, I've never liked
Python's word for dictionaries, but I don't like hash either, I think map is
the better term, but it's still just a single name of a concept, not a huge
deal. His arguments about the names of libraries are stupid, they are third
party libraries that Python doesn't even control! And as someone who is very
picky about function and variable names, a library name hardly ever matters,
especially as Python allows you to rename imported modules.

6\. Quirks: I don't even understand what his complaint is here. Does needing
to triple quote multi-line strings really bother him that much? The binary and
raw syntax might be a bit confusing, but I'll take that any day over C++'s L""
for wide strings and _T() for strings that may be wide or not and are
determined at compile time. The string vs unicode is a bit confusing, I'll
give him that, but I think the entire concept is confusing in any language.

7\. Pass by object reference: I actually completely agree with him here,
though I don't know how Python would fix this. I think I can explain it better
than he does though. The issue is that if you create a list "list1" and then
set "list2 = list1", and then append the element "3" to list2, list 1 changes
as well even though list1 was never directly changed. This was one of the
biggest things I struggled with in Python until I learned C++ better which
taught me how Python was working under the hood. Python makes you think that
it doesn't have pointers, but the truth is that everything in Python is a
pointer, which I found confusing relative to how everything else in Python was
beginner friendly.

8\. Local names: I don't really understand his complaint here, don't shadow
names.

------
kanox
Obligatory [https://xkcd.com/1987/](https://xkcd.com/1987/)

------
Walkman
A great example of how Trump has been elected. He lied a lot, (or said stupid
things because he was ignorant in a topic) but it doesn't matter, because
rebuttal takes a bit more effort than saying stupid things so what he said
stuck with a lot of people. Sorry, but this article is just ignorant in almost
every point.

~~~
dragonwriter
> A great example of how Trump has been elected. He lied a lot, (or said
> stupid things because he was ignorant in a topic) but it doesn't matter

A number of the people with federal felony convictions, some having already
gotten federal prison sentences to go with them, for their role in supporting
Trump's dishonesty might quibble with the “doesn’t matter” characterization.

------
juhzy
Python sucks because how slow it is. The rest of problems pale in comparison.

------
n-gatedotcom
I want to get a vote on indented nested blocks- how many of you like them?
Please up the appropriate child comments (if I'm rate limited someone else
please make child comments with like and unlike).

My reasoning (please give yours below proper heading)- I'm deadly afraid of
refactoring or even accidental indentation change.

------
MichaelMoser123
the self argument for methods/method calls is stressful (having to define self
for methods and having to call a method via self); also the fact that you need
to check if dictionary key exists, else you get an exception when trying to
get the keys value. Also ':' at the end of each line.

I always forget at least one of these. You didn't have any of these goodies in
good old perl (sob, sob)

(wow, this one got flagged pretty quickly, wonder why)

~~~
dagw
_you need to check if dictionary key exists, else you get an exception when
trying to get the keys value._

What should be the correct behavior when accessing a key that doesn't exists?
If you want a specific default value when a key doesn't exist you can use the
get() method.

 _Also ':' at the end of each line._

What do you mean? You don't need ':' at the end of each line, only at the
start of a block (basically anywhere you'd use a '{' in other languages).

~~~
blattimwind
> What should be the correct behavior when accessing a key that doesn't
> exists?

Undefined behaviour, i.e. the JIT generates code to 3D print a clay golem on
your desktop that sets your village ablaze.

