20 ms·
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 t
by notacoward 8y ago
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.
- diminoten 8y agoThank you for going point by point. I was blown away by how little experience the author had with Python, compared to how strong his opinion is about it. I hate hate hate language debates, but this isn't even that, it's just a misunderstanding. If this guy took a class on Python he'd figure out like 5 or 6 of these issues no problem!
- bdcravens 8y agoTrue of most "X Sucks" discussions. I used to do a lot of ColdFusion. A mention of that would elicit the oh-so-clever, "I'm sorry...." A little digging found they either had never written a line of CFML in their life, or they worked on a project back in 2005 before they added numerable features, and before many of the frameworks and tooling that a typical developer would use.
- neurobashing 8y agosame for PHP. Still not great but there is in 2018 essentially a "good parts" set of best practices, which combined w/ v7 is not a horrible language/platform. I feel you if you just don't like it, but I see so many people just quoting that old "fractal of bad design" post that's really not relevant any more.
- szatkus 8y agoAnd for JS. If you disable in linter some awkward features left for backward compatibility, modern JavaScript is pretty cool language.
- codeape 8y agoTotally agree. The author needs to read the Python docs.
- fhood 8y agoIt'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.
- closed 8y ago> I regularly wish python required some sort type indication for function parameters You can use type annotations, either via the builtin lib or 3rd party libs! https://docs.python.org/3/library/typing.html https://docs.python.org/3/library/typing.html > do_x() if a.y() I feel this. You can use `a.y() and do_x()`, but I'm not sure how people would react :o
- fhood 8y ago> You can use type annotations, either via the builtin lib or 3rd party libs! > https://docs.python.org/3/library/typing.html https://docs.python.org/3/library/typing.html I know, but tragically, because I am not forced to, I never do. I do appreciate that feature though. Maybe this will be the impetus I need to start taking advantage of it.
- computerfriend 8y agoI started doing this about a year ago and it has made me a better Python developer. Getting into the habit of always writing a type annotation was hard at first, but you quickly get used to it. It helps if you configure mypy to complain at you if the annotations are missing.
- Hello71 8y ago> 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 so hilariously wrong that it is clear that the author has never actually tried any of the things he complains about. Python 3.7.1 (default, Oct 22 2018, 10:41:28) [GCC 8.2.1 20180831] on linux Type "help", "copyright", "credits" or "license" for more information. >>> if True: ... if True: ... pass ... pass File "<stdin>", line 4 pass ^ IndentationError: unindent does not match any outer indentation level same error in Python 2.7.15. the caret is at the wrong place, but the error message is perfectly fine on its own. edit: I checked the CPython source, and this message actually dates back to 2000. so unless the author was using python 1.x back in the 90s, or is dumb enough to use single spaces for indentation, the story is a complete fabrication.
- fhood 8y agoNot to mention, who hits the spacebar four times for their indentation? Actually. Do people do that?
- mikestew 8y agoTo back this up, I was at a place where vim on my Mac and the Windows editor on the machine of one of the people consuming my code would somehow munge the spacing (tabs-to-spaces, or summat). Point is, I'd see this problem constantly until I figured it out. And not once did it take more than a few minutes to fix it because, as you point out, it shows you where the problem is. And if you use PyCharm, or VS Code with Python extension, or a raft of any other editors, it'll bark at you long before you try and run the code, with circles and arrows, and a paragraph on the back of each one explaining the problem. So, yeah, the author is making shit up. And needs to learn about what the Tab key does.
- folkrav 8y agoThe article read more like a rant of "I PERSONALLY HATE THIS" than a well-reasoned argument of why the language might actually suck. Here's an example : > PyPy, PyPi, NumPy, SciPy, SymPy, PyGtk, Pyglet, PyGame... (Yes, those first two are pronounced the same way, but they do very different things.) I understand that the 'py' is for Python. But couldn't they be consistent about whether it comes first or second? First, stupid examples. PyPy and PyPi (actually PyPI, with the uppercase) are not pronounced the same, its "pie-pie" and pie-P-I. Second, on the package names, they're third-party. They could be named pretty much anything. Why does their naming matter in any way? I haven't seen much consistency in any language I've encountered anyway. I'd even say most of the examples he gave are at least pretty self-descriptive, compared to a lot of libs in multiple languages...
- RobertKerans 8y ago> The article read more like a rant of "I PERSONALLY HATE THIS" Given the entire premise of the post is that he's written a list of things he hates about Python as an answer to his friend's question as to why he hates Python, I'm not sure why you think there's some ambiguity here.
- ChrisSD 8y agoWhich makes it perplexing that it's on the HN front page. A list of very personal and petty gripes aren't all that informative. Especially when half of them seem to show a profound lack of familiarity with Python.
- AcerbicZero 8y agoPerhaps it was upvoted because there is a prevailing sense that something in Python isn't right, and even though most people seems to disagree about what exactly isn't "right". I "hate" python for my own (much more petty) reasons, although the horrible naming conventions struck a cord with me, so I upvoted this article, with the hope that I'd be able to learn something from the discourse it creates.
- kbrackbill 8y ago
- pdonis 8y agoWith regard to "pass by reference", it's not even clear to me that that's a correct way to describe how Python passes variables to functions. Python variables aren't names for storage locations to begin with; they're namespace bindings. Passing a variable to a function means passing a particular namespace binding from the caller's namespace to the function's local namespace. I don't think the author of this article understands any of that.
- tom_mellior 8y ago> Python variables aren't names for storage locations to begin with; they're namespace bindings. Can you explain the difference? What is a "namespace binding"? When accessing a variable's value, the interpreter's code sure looks like it treats the variable name as the name of a storage location. > Passing a variable to a function means passing a particular namespace binding "Passing a variable to a function" is not a thing. Passing a value to a function means passing a pointer to that value. This is the same for "foo(some_var)" and "foo(1)". Since "1" is presumably not a "namespace binding", you seem to suggest that there are different parameter passing mechanisms for these cases. There aren't.
- kzrdude 8y agoEvery value in Python is a reference to an object. All function parameters are such values that are passed as they are. You get the same references to objects that the caller passed. We could call this "passing references to objects by value."
- zephyrfalcon 8y agoOver the years, I have found this article to be useful: http://effbot.org/zone/call-by-object.htm http://effbot.org/zone/call-by-object.htm
- Izkata 8y agoThat's a long form of what I most often hear: "pass by value of reference" But in any case, that's the point that made me go wtf while reading through as well. Whatever you want to call it, it's the same as what C (when not passing pointers), Java, PHP, Javascript, and many many other languages use. Which is why it's so frustrating we don't have a good, easily-understood/well-known name for it.
- 013a 8y ago> 1 (versions) and 2 (installation) have to do with the ecosystem, not the language. This argument really summarizes a beautiful and dangerous thing we see in the tech community far too often; you have a strong technical and scientific understanding of the system, but lack product and design thinking. You're right. Its a problem with the ecosystem, not the language. I'm still not going to use python because of the ecosystem. If the language cares about its users, it needs to care about the Product, which includes the ecosystem. Users interact with the Product, not just the Language. That's something recent languages like Go, Typescript, Rust, and even old languages like Java, understood quite well. Its not just about the syntax and the compiler; getting users into your language means caring about the IDE, caring about the development experience, the package management, the libraries, basically everything that a developer will touch. That doesn't mean you have to touch all that stuff as the core development team, but it does mean you need a Strategy and a Message.
- notacoward 8y agoI don't disagree with any of what you said, but I'd say its importance is up to the developer. Characterizing the difference as a "lack" is pretty rude IMO. The language and the ecosystem should be separable to some degree. It's called modularity, and I won't say you lack familiarity or appreciation of that even though you obviously prioritize it differently. If the author hates those particular parts of the ecosystem so much, s/he is quite free not to use them, probably more so in Python than in most other languages due to the explicit "batteries included" ethos of its creators. If you want to think about the "product" and a "strategy" (all for an OSS project) then that's great. The world needs more like you. Knock yourself out. Other people quite legitimately prefer to focus their attention and energy on the core technology. The real problem here isn't that Python was used to mean the language alone when it should have been used to mean the entire ecosystem, or vice versa. The problem is that it's ambiguous. I didn't mention that points 1 or 2 are about the ecosystem to invalidate them. There are stronger refutations available. I was just trying to identify a scope that the author had left ambiguous.
- toyg 8y agoNote how almost all languages you take as shiny examples of virtue post-date Python: they all learnt from it so much, particularly on things like the stdlib. Python’s stdlib was the gold standard for a long, long time (the “batteries included” slogan was effective for a reason - they really were!). This was not by accident - Guido and others have always had the utmost care for good developer experience out of the box. How many languages pack an editor ready to go? Or a way to install modules with a single command? Not even Java, with all its commercial might, ever achieved that - it barely got a REPL last year, which Python has had for what, 20 years now? What people decry about “the Python ecosystem” is simply a function of its success as a generalist computing language over 25 years. Nobody uses Typescript to build Linux distributions; nobody uses Go to build lib-gluing GUI apps; nobody uses Rust to write spreadsheet formulas. Python does all that (and more), and this of course resulted in a sprawling community, with tools pulled every other way. If any of your new shiny languages will ever achieve a similar level of popularity, you can bet their ecosystem will also become a complete mess.
- pkolaczk 8y ago7 Isn't Python actually pass-by-value / pass-pointer-to-object-by-value like Java is? Many confuse pass-pointer-to-object-by-value with pass-by-reference, but they are different things. Pass-by-reference allows to write a procedure that swaps two external values.
- clumpthump 8y agoPeople confusing this terminology is one of my pet peeves. And it's not a petty one. It often impedes the conversation they're trying to have.
- civility 8y agoYou're right that you can't perform swaps with a Python function, but it's never pass-by-value like Java primitive types. It feels like pass-by-value because int, long, float, complex, and string are basically immutable.
- szatkus 8y agoI may be missing something, but I can't find any example in my mind which indicates difference between passing in Java and Python. And it's pass-by-value for all types, because for objects an address is the value.
- civility 8y agoJava primitives (short, float, double, etc...) are copied to the calling function, but arrays and objects are passed by reference. This is easier to explain in a language like C++, which can do either: // Java always does these: void f(Object& o) { ... } // passes objects by reference void g(double x) { ... } // primitives are copied // Java can not do these: void p(Object o) { ... } // copy of the object void q(double& x) { ... } // reference to primitive CPython always passes by reference (pointer), and a C extension can break the rules and modify the otherwise immutable types (int, float, complex, string, etc...). You can squint and say everything is pass-by-value because you can always pass pointers, but then we're really losing any meaningful definitions for what semantics we're describing. I mean, it's all pass-be-electron if you dive deeply enough.
- com2kid 8y ago#7 is so very wrong in so many ways. Even languages that are pure "pass by value" cheat pass the value of a reference for objects. Very few languages support doing a deep copy when passing an object. I'm trying to think of a single one, and I know that none of the major ones do. C will pass an entire struct, and so long as the struct doesn't have any pointers, sure... But even in C passing a struct by value is highly discouraged, since it can spew all over registers and the stack! I've worked with coding conventions where pointers to structs are passed, and then the called function memcpy's the struct if it needs to hang on to it, or just leaves well enough alone if it only needs to pull values.
- srfilipek 8y agoThat one dumbfounded me as well. Has the author never given a pointer as an argument to a function before? Do they make copies of their strings and structs every time they want to pass it around? I just... I just don't understand how they could think that.
- triMichael 8y agoI think I can answer this one because it is one of my gripes of Python. The problem isn't that it doesn't copy, rather it is that the = assignment operator specifically doesn't copy. If you create a list "list1", set "list2 = list1", and change list1, both of the lists change. When I learned Python, this was a major source of confusion for me. Eventually I learned that in Python, instead of nothing being a pointer as it first appears, it is actually that everything is a pointer. On the other hand, while the same things occur in C++, the assignment operator does a shallow copy and anytime you are doing a pointer copy it is explicit.
- notdonspaulding 8y agoI don't remember when in my Python career I learned about names vs. values, but it finally clicked for me that I'm predominately just binding a value to a name with the = assignment. Now everything I read has become very easy to reason about and understand. Ned Batchelder is a good resource for learning many things about python, and this talk he gave at Pycon some years ago is no exception: https://nedbatchelder.com/text/names1.html https://nedbatchelder.com/text/names1.html
- dbdjfjrjvebd 8y agoOn pass by reference.. I really miss Fortran's intent(in). You get a reference to the data but it is immutable... I would like if Python had something similar...
- deaps 8y agoGlad you took the time to write that. I stopped reading the article after his beef with imports...
- mirko22 8y ago> 7 (pass by reference) is another totally-wrong one. Yes, specially cos it is not "pass by reference", but "call by sharing" http://www.effbot.org/zone/call-by-object.htm http://www.effbot.org/zone/call-by-object.htm https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sh...
- IshKebab 8y ago> 1 (versions) and 2 (installation) have to do with the ecosystem, not the language. How exactly do I use Python while entirely avoiding the Python ecosystem? I get what you're saying but you're also massively nitpicking. His point is correct.
- jaxtellerSoA 8y ago>3 (syntax) seems to be about not supporting the author's own highly idiosyncratic habits Yeah, I don't get the author at all. Using indentation is so, so, so, so, much cleaner and easier to understand, even with lots of nesting than trying to figure out if you closed all the stupid curly braces, curly braces be damned.
- riskable 8y agoI asked a "C all the things!" developer a while back why he hated Python's enforced indentation and in a whole lot of words he basically said that it makes it difficult to visually track scope when you have long chains of conditionals. The standard Python developer response to that is, "Aha! You like braces because they enable your bad programming practices!" However, I found the best way to illustrate that point is this: I asked him, "If you're never allowed to use a text editor/IDE that highlights braces or the space between them ever again would you still prefer braces to indentation?" I had to re-explain this concept several times but eventually I think he understood my point at least a little bit... "Aha! You're using spaces because Python lacks decent development tools! In fact, because there's no static typing you can't even make a decent IDE for Python! Spaces are a crutch!" Sigh.
- pfranz 8y agoIsn't deep nesting (hence deep indentation) a sign of code smell? Yeah, you might end up shuffling the logic into a new file or a function that makes the file much longer, but I've noticed when doing that kind of refactoring it forces you to clean up the scoping quite a bit so there's less state to keep track of.
- Karunamon 8y agoIt depends on your definition of "deep". Imagine an if, inside of a foreach, inside of a function definition, inside of a class. This is not terrible code, it's perfectly reasonable. Now you're indented four levels in. Now combine this with some rather unreasonable and outdated assumptions that PEP8 (automatically enforced in many shops and OSS projects) has, like pretending that people are still on glass terminals and that anything longer than 79 characters is a problem. It also insists on four-space tabs, so this very simple construct has eaten 20% of your line budget. ..not to mention how it makes your code harder to read. I also share the author's concern about how you're less able to separate your debug code from your actual code.
- sam0x17 8y ago> 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. Regarding 1: I'm sick of people saying that the ecosystem != the language. No one is going to be able to prop up an alternative ecosystem and get more traction than the language's own ecosystem, so you are basically always stuck with whatever crazy ecosystem comes with the language. Most of what people care about is the ecosystem and the syntactic sugar relationship the ecosystem has with the language, so it is a very real criticism imo if a major programming language has a bad ecosystem. You are stuck with the ecosystem you ship with the language, so get it right the first time.
- blattimwind 8y agoThere actually are separate Python ecosystems (applications embedding Python or relatively detached distributions like Anaconda). Similarly you don't really care about e.g. the larger Lua ecosystem when you are targeting a specific application using Lua. It has its own ecosystem.
- sam0x17 8y agoThat's my point though. Unless the primary language developers themselves say "Hey, this ecosystem is broken" and then make an alternate one, we are generally stuck with the old broken one being the de facto standard. And even in that scenario you have to make the choice between breaking compatibility with everything that relies on the old ecosystem, or supporting both new and old at the same time. The lesson to be learned here is you only really get one shot at doing the ecosystem the right way, so do it right the first time. Hence Crystal/Go/Rust/Nim/etc
- alexchamberlain 8y agoGenerally, yes, but in Python, no; there are at least 2 good ecosystems.
- 8y ago
- sifoobar 8y agoI'm pretty sure Python's list type is implemented as a dynamic array, otherwise random access wouldn't work very well. Maybe try to not identify so hard with language choice? That way you gain the capability of processing critique without loosing your marbles.
- blattimwind 8y agoPyList is a dynamic array (usually called vector) of PyObjects, i.e. it contains objects and never values.
- lolc 8y agoWhy should it matter how lists are implmented?
- sifoobar 8y agoBecause someone claimed that they're not arrays, which they are. So the posted article is correct in that sense; and not wrong about everything, which was also claimed.
- sebastos 8y ago3: Yes. Mandatory indenting is a godsend to readability. Author is wrong. 4: Yes. Imports >> Includes in every conceivable way. However, what is actually available to import _is_ confusing. This is really a symptom of a different problem though... 5: Yes 6: Yes - picking on the quotes thing with Bash is just one of a million syntax "quirks" that make Bash a horrible no good language. ( as an operator is my vote for most egregiously mind-bending "feature". 7: Yes. Once you get used to it, Python usually does what you want in terms of passing parameters. 1 and 2: NO. The ecosystem and the language are the same thing. They're useless without each other. Every other point the author makes is dumb, but this one is utterly correct. Now, the version schism is unfortunate, but it's spilled milk. I agree with the author that it's obnoxious, but there's not much to do about it now. However - creating, sharing and installing packages in python is THE problem. And I'm not saying it's an unsolvable problem - that's what makes it so frustrating! You have a thriving, healthy community of package maintainers creating amazing libraries that allow regular engineers like me to get work done out of the box. And in many ways, as other posters have pointed out, python paved the way for making this experience better than the hell that is c++ package management. Sure. But the current user experience of trying to give somebody an application that happens to be written in python? The story of how you take some python code you wrote, bottle it up, and make it work on somebody else's system? And the story for how they take that code and make it available to themselves on their own system? It. is. atrocious. Which one of these tools, concepts, commands and filetypes do I need to care about: package, module, egg, wheel, bdist, sdist, distutils, setuptools, easy_install, pip, pipenv, poetry, PEX, PyInstaller, py2exe, PyPI, conda, miniconda, anaconda, virtualenv, venv, requirements.txt, setup.py, pyproject.toml, pipfile, site-packages, dist-packages, $PYTHONPATH or motherfucking .pth files??!?! Ever been curious how sys.path gets populated at startup? Gaze into the darkness: https://github.com/python/cpython/blob/master/PC/getpathp.c https://github.com/python/cpython/blob/master/PC/getpathp.c And to anyone saying "Just use a virtualenv": that is so, so not an answer to this eldritch horror. Let me ask you this - when you installed chrome, did you have to create a new virtualenv? No. If you want to effectively distribute code to lots of people, you need more than a god damn virtualenv. The whole world isn't just scientists tooling around in sandboxes.
- empthought 8y ago
- kakwa_ 8y ago> 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. There is one big difference between Pypi and a distribution repository: With Pypi, every contributors are truly individuals, they upload their packages alone, they maintain them alone, they basically do whatever they want. The maintainer here can likely be a single point of failure. With distribution even if most packages are maintained by a single person, the repository content is the responsibility of the distribution as a whole. These distributions have formalized their processes and policies a long time ago. For example, if a critical security issue is found, unless something goes wrong, the package will not be left unpatched, even if the package maintainer is not reacting. Also, Distributions put huge efforts into providing stable versions, if you are using packages from a distribution, you have some guaranties about stable APIs, and that these packages with stable APIs will actually be maintained for a few years. Even if it's not always perfect, with non-critical bugs not always fixed, it's a far cry from Pypi where the only true possibility is to hard pin every single version of your dependency tree inside requirements.txt.
- pbalau 8y agoIsn't pep440 actually dealing with versioning? In my mind, if there is a pep, then is the language.
- deleted 8y ago[deleted]
- stochastic_monk 8y ago1 and 2 are big issues for portability for me. It’s easier to ask for a C++17 compiler than insist on Python 3.6 with MKL. It’s not central to the language, but how people use it affects distribution.
- anzuo 8y agoThank you for taking the time to explain this in such depth. This was one of the most frustrating articles I have ever read.
- tigershark 8y agoIt’s even false that python passes parameters by reference. It passes the references by value, that is a completely different thing. It’s really easy to prove it by implementing a function swap(a, b) and looking at the values of a and b after calling the swap function. Obviously a and b are not swapped because they are not passed by reference, but instead the references are passed by value. It’s an article written by someone that doesn’t have the slightest idea of python if even I, that I used it only a bunch of times, don’t make this beginner errors... Btw I don’t like python, I prefer to it a lot of other programming languages.
- wutbrodo 8y agoYea I was pretty surprised; Python really does suck, but I don't think I found a single one of the reasons listed in the article compelling.
- kamaal 8y ago>>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. Telling users they are not good enough for your technology is not the way you go about these things. Also if this works in other languages, people do expect it should work in Python.