I understand why people like it. And I like scripting languages, it's nice to find a piece of script somewhere and being able to edit it directly having to find the correct source code and recompiling. But it has lots of shortfalls and quirks too (multi-threading, dependencies management, deployment, no refactoring/static checking, python 2 vs 3, 50 different kinds of strings, APIs full of abbreviations which probably meant something to their creators 20 years ago, etc).
It's a nice language, among others. Not an "ultimate" language by any means in my opinion.
>multi-threading
Most interpreted languages have a GIL, sadly. But yes, this is annoying.
>dependencies management
Annoying, but resolved in part with new projects like pipenv, and also still a big issue for other popular languages.
>deployment
Also helped by pipenv, and Facebook's xar (https://github.com/facebookincubator/xar) is new but looks promising.
>no refactoring/static checking
It's a dynamic language. But this is now possible to some extent with type hints.
>python 2 vs 3
They did screw this up, yeah. Python 3 fixes a ton of issues and is a better language, but the backwards incompatibility created way too many problems.
>50 different kinds of strings
There are 2 kinds: bytes and unicode.
>APIs full of abbreviations which probably meant something to their creators 20 years ago
Can you give some examples? This is an issue in a few of the old standard libraries, but even then it's not too common. This is way, way more prevalent in PHP and C than in Python.
No I mean single quote, double quote, triple double quotes, r prefix, u prefix, f prefix, combinations, etc
> Can you give some examples
The one I have in mind is the os library, which I use a lot (like why st_mtime?).
These are all extremely helpful, though. All of those quote combinations are equivalent, and can be used to prevent having to escape quotes within the string. The u prefix is gone from Python 3, r is a raw string (which many other languages have, like C#'s @ prefix), and f is a new feature which generated a lot of debate but basically allows interpolation similar to Ruby and ES6.
>The one I have in mind is the os library, which I use a lot (like why st_mtime?).
That's the one I thought you were going to bring up. I agree the naming conventions in the os module have a lot of warts. The function names could use a refresh.
I disagree, in that I think they are only somewhat helpful. If we only had double-quoted strings, and not single-quoted strings, then I think there would be little difference to the language or its quality of use.
Going back to the question of "why st_mtime?" - that's because os.stat() is a wrapper around the POSIX stat(2) system call. My FreeBSD man page defines it as:
st_mtim Time when file data last modified. Changed by the mkdir(2),
mkfifo(2), mknod(2), utimes(2), write(2) and writev(2) sys-
tem calls.
The Python implementation of stat for MS Windows is basically doing its own emulation layer for POSIX compatibility. from collections.abc import Sequence
Slower? import numpy as np> Slower?
Yes, overall the language is slower than PHP. It's not a bad thing, just the result of benchmarks. It doesn't mean one should stop writing Python.
Some benchmarks might be slower, but I don't know anyone doing high-performance computing with PHP. I do see the topic at Python conferences.
ABCs are like interfaces in they can be used to enforce properties (like the presence of particular functions) of a class that extends/impliments them; BUT, interfaces can also be used to enforce a particular variable always refers to something with certain properties (without worrying about what it is concretely).
There's more than one variety of inheritance. Both Python and Java chose implementation-inheritance, meaning that the children get to use not only the interface, but also the implementation of the parent.
For some reason, I'm not quite sure why, the Java folks thought that multiple implementation-inheritance would cause too many problems. They still recognized it's useful, so they provided a 2nd form of inheritance that supports multiple parents, interface-inheritance.
There are more varieties of inheritance that a language could choose, for example, prototypes like JavaScript.
[1] https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamo...
The trouble is that English, and other human languages, have never been as clear or specific as we assume they are when we start writing code. For example, what is a bird? It's a thing that flies? Oh, ostrich, penguin...
All these supposed OOP inheritance problems aren't unique to inheritance but to the translation of human language to programming. There's no need to exclude multiple inheritance, because nearly every aspect of programming is afflicted.
if __name__ == '__main__':
main()
Code like that just doesn't make any sense to me.__init__ is called that because it initializes the object. It could have been called "__construct__", but I think "__init__" is a lot clearer about what it actually does - the object is already created when it enters __init__, __init__ just prepares it.
Calling it "self" instead of "this" is super traditional. Smalltalk did it.
The __name__ == '__main__' pattern is ugly, and I'm not a huge fan of it. You don't always need it, it's just a guard to let you tell whether a script is run directly or imported as a module. The key is that Python only has runtime. A function declaration or class declaration is a fancy variable assignment. The content of the file is executed sequentially.
Python is not especially weird, but it is different from what you're used to. Wrapping your head around it takes a while, like with all languages, but things start to click eventually.
It helps to experiment. The REPL is great for that. If you don't understand why something is the way it is, mess with it until you think you understand its behavior, then mess with it some more.
I don't know what you mean by "idiomatic approach". That phrase, I thought, refers to languages that are highly opinionated about using a specific style -- this philosophy is encoded in Python's philosophy:
https://www.python.org/dev/peps/pep-0020/
There should be one-- and preferably only one --obvious way to do it.
> Pretty much every popular OOP language does it either by naming a constructor the same name as the class name or through some form of a `construct` notation
Seems kind of arbitrary to complain about the constructor keyword `__init__` when the constructor word for pre-ES6 JS, C, Perl, Ruby varies between prototype, constructor, __construct(), and new. Not sure how you say Python's use of `__init__` is somehow worse. As for why `self`, no idea, but seems to be a pretty easy convention to figure out.
As for the complaint about the `if __name__ == '__main__':`, to which language are you referring to that has a more self-evident way of encapsulating that functionality?
C doesn't have classes. pre-ES6 - agreed, but who writes it? I think Perl is a bad example, it's dying and is one of those highly opinionated guys, with all its `method`, `trusts`, etc.
> As for the complaint about the `if __name__ == '__main__':`, to which language are you referring to that has a more self-evident way of encapsulating that functionality?
My gut tells me that this is an error-prone idiom.
I'm not saying Python is bad, I just don't like it. I'd love to know what are the strongest sides of the language though?