The Python I Would Like To See
lucumr.pocoo.org
lucumr.pocoo.org
But it comes off as a rant without a real suggestion.
Python 3 was an internal interpreter cleanup. That's actually part of its lack of widespread popularity. The core developers didn't add a ton of unique functionality (and most of the new stuff was backported to 2.7 anyway), but they fixed some annoying problems in the CPython codebase and broke some things in the name of cleanup/unification of concepts. They made Python easier to maintain and easier to build new features atop. They sharpened the axe.
Yes, they didn't clean up Armin's pet thing -- slots. And they created new problems for library developers in their bytes vs unicode changes. But they cleaned up a whole lot of other stuff.
I personally think with the maturity of pypy and the stability of both the 2.7 and 3.4 lines of development, the Python ecosystem has never been more exciting. The advances in pypy make Python attractive for CPU-bound work and the inclusion of asyncio in the stdlib will make it more and more attractive for I/O-bound work over time. Python has long been a winner for mixed workloads, and the ecosystem around Python, especially pydata utilities like numpy and pandas, keep getting better. Stop complaining -- let's just build an awesome future atop this marvelous language.
How exactly is that a rant? It's an exploration about a design decision / mistake that was carried through Python for 25 years and has left an impact. There is no complaint and there is no suggestion for Python.
As I said in the early paragraph it's something that's interesting for people that are interested in language design.
The removal of the slot system would be a backwards incompatible change with very little direct benefit for developers. It could be interesting as a general goal for a hypothetical Python 4 but I do not believe it makes any sense to discuss this as anything more than a hypothetical case for the next few years.
This internal detail you focused on solves real problems; it's also a wart internally. OK, we get it. It's also not a hugely important wart, IMO. I don't think it's holding Python back.
But, like I said, I think the article was an interesting walkthrough of the internals. I enjoyed it overall :)
In contrast, the article suggests that the implementation of method dispatch slots (not __slots__!) actually constraints the optimizations you can make.
I get that you're trying to suggest that they're both small, but I think that this analogy only serves to confuse things.
Did you actually read TFA? It makes some very real suggestions towards the end, and pinpoints clear issues and how they could be changed all the way through.
>But they cleaned up a whole lot of other stuff.
Which is irrelevant to the current discussion. How is "they cleaned X" a response for "they should clean Y"?
print linewithnonewline,
with the comma indicating the lack of newline, now has to be done through print(line, end=""). Which is more practical and pythonic?This post remember me of Spolsky's one (http://www.joelonsoftware.com/articles/LeakyAbstractions.htm...) though. When you get to a point where you get to know what's under the hood and why it's not working the way you are trying to use, however in a majority of cases you are just fine and don't need to know what's happening under the hood and maybe if this majority is big enough that's just fine.
In particular:
In modern usage, this question also serves as a
metaphor for wasting time debating topics of no
practical value, or questions whose answers hold
no intellectual consequence.
Python will (or won't) be used for a particular application regardless of whether some contrived test takes 0.158 usec or takes 0.256 usec per iteration.This sort of misunderstanding comes up so often that there are a plethora of cliches for it. Here's another one: "Missing the forest for the trees.".
>>> original = 42
>>> class FooProxy:
... def __getattr__(self, x):
... return getattr(original, x)
...
>>> proxy = FooProxy()
>>> proxy
42
For anyone else who found this as confusing as I did ("wtf, how can proxy actually be 42?"), what's going on here is that it's calling `proxy.__repr__()` when it attempts to display `proxy`, which in turn calls `42.__repr__()`. (Similarly, `proxy + 1` calls `42.__add__(1)`.)However, I am disappointed with the difficulty of turning a program into a Windows EXE. I wrote a small program (couple of thousand lines), tried Py2exe which failed to handle the Numpy (or Matplotlib, I forget which) imbroglio.
PyInstaller works, except that the EXE is 85MB, and takes one minute to start up. Not practical for customer distribution. I can't expect my customers to install the Python runtime. In contrast, my 500KLOC C++ program, with all its third-party libraries, is 19MB. Yes, I know, Python needs everything including the kitchen sink. Still, 85MB is not practical.
Too bad. Not all programs run on a server.
C++ has had this operator overloaded for strings for decades.
With regard to the size of compiled executables, I can't really say much except "that's not what it's made for". If you need to ship compiled executables to people, Python is an extraordinarily inappropriate choice; stick with C++.
Here's the code (Visual Studio 2010):
#include <string>
#include <time.h>
char buf[64], buf2[64];
clock_t start = clock();
for(i = 0; i < 100000; i++)
{ _snprintf(buf, sizeof(buf), "%d", i);
_snprintf(buf2, sizeof(buf2), "%d", i * i);
#if defined FAST
strcat(buf, buf2);
#else
std::string s1 = buf;
std::string s2 = buf2;
std::string s3 = s1 + s2;
#endif
}
_snprintf(buf, sizeof(buf), "%.4f\n", (float)(clock() - start) / (float)CLK_TCK);
OutputDebugString(buf);C++ is all about low-cost abstractions. Any speed difference between the C++ way and the C way should be very small, and the C++ way is safer. Use std::string (and std::vector and all the rest) unless you have a very good reason not too, and then you should probably just write your own custom implementation. Reverting to the C way is just asking for issues.
I'm all for using abstractions and working smarter, but why pay such a performance penalty?
Operator overloading is something, that belongs to the 'pro' skill-set of C++ developers and done wrong, can lead to many problems.
In Python it is much easier to overwrite the behavior of such standard methods and the language core can be learned in about 1/4 of the time you need to learn in C++ to just know the basics (C core, C++ object basics, Operator overloading, standard library basics like the string class, ...) -- in Python you get the power with much less learning effort and without the technical troubles.
The template syntax is a great productivity boost compared to C++.
>>> sys.getsizeof(OldStyleClass), sys.getsizeof(NewStyleClass)
(104, 904)
>>> sys.getsizeof(OldStyleClass()), sys.getsizeof(NewStyleClass())
(72, 64)
I agree that OldStyleClasses might be simpler (while less featureful), but I think I'd care more for the footprint of instances, rather than class objects themselvesA great feature that's not really talked about is the __prepare__ function in metaclasses: you can supply a custom type that stores all class members. You could whip up multiple-dispatch using this (it lets you handle classes with duplicate property names) in conjunction with signature annotations, which I think is pretty neat.
Ronacher should also know better than to post microbenchmarks like the one provided here, especially without corresponding (C) profiler output. At the C level, slots allow the implementation constant-time access to the most common code paths for an object, and especially when you have C code calling other C code via the type system (IMHO the primary use for Python, and still its strongest use case), "interpreter overhead" is reduced to a few extra memory indirection operations.
In the alternative world, sure, perhaps some microbenchmark may behave faster, but now systemically, and for e.g. "reduce(operator.add, range(1000))" requires more hash table lookups than I can count.
Python is all about providing a lightweight way to compose bits of fast code (the kernel, network stack, NumPy, MySQL, whatever). Unfortunately somewhere along the way solutions like Django got popular, which are almost the antithesis to this old viewpoint. Ronacher seems to be advocating that we should punish the CPython implementation's traditional strong areas in favour of.. actually, he didn't even describe any vision that was impacted by his complaints. He just seems to want the CPython implementation to suffer.
Perhaps his complaint about new-style __getattribute__ would be better suited as a bug report, it seems the only substantial observation made about the language itself in this post.
You might think that, but you are very wrong and I should probably make that point in another blog post. These CPython specifics are enshrined in the language. While PyPy does not have the actual structs, it needs to implement the same user exposed API as it slots were used.
PyPy cannot just say "a + b" means "a.__add__(b)", it needs to implement the exact same dispatch logic that CPython has because people's code depends on it.
//EDIT:
> Ronacher seems to be advocating that we should punish the CPython implementation's traditional strong areas in favour of.. actually, he didn't even describe any vision that was impacted by his complaints.
Maybe I did not make my point very clear but the whole last paragraph advocates about trying a version of Python that abolishes the internal slot system.
The next might be "__getattribute__ mechanism has surprising behaviour in common use-case" (which itself would imply having a use case where any of this mattered). This one might actually result in some productive discussion regarding a fix.
Your second reply is basically a doc bug, one of "__getattribute__ optimization is not specified in the language reference" or "__getattribute__ optimization causes non-comformance with the language specification", either way, you would get the attention of the few people who can actually help you, rather than attention from the many more who can't
As it is, the title at least primes the reader to think you are asking for what you go on to describe.
Ronacher says: "Python is definitely a language that is not perfect. However I think what frustrates me about the language are largely problems that have to do with tiny details in the interpreter and less the language itself. These interpreter details however are becoming part of the language and this is why they are important."
He is right, Python has not real standard with clearly defined semantics. Actually, the standard is CPython, but CPython is full of crap that other implementations are then forced to implement thus making that crap part of the language. You should avoid Python at any cost, into the trash it goes.
Having an abstract specification of the language, rather than "whatever CPython does", would give implementors more freedom, and thus allow the use of Python in more places and circumstances.
I'd probably argue that most uses of metaclasses are a reason to step back and make the code simpler. There are a few cases where they come in very usefully, but at least in open source code, they create a barrier to understanding and increase complexity.
ython starts to get ugly when you start writing code that does "automagical things", and that's somewhat tolerated because it's not a language for building automagical things.
Or, to say it another way, if you have to think about how the interpreter works, your python has jumped off the idiomatic wagon a while ago.
That being said __slots__ as a performance enhancement is crazy useful - and I'd like to see more things in that area. Though for most people, the thing that would lead to cleaner code would be a more powerful and elegant standard library.
Can you be more specific? The article claims that it's not a performance boost at all. Where is it useful?
__slots__ are useful to reduce memory usage when you're instantiating lots (tens of thousands or millions) of Python objects. Since objects defined in Python code support the addition of arbitrary attributes, their members are internally represented as a dictionary which isn't necessary when your tens of thousands of objects have a limited set of attributes.
Defining a sequence __slots__ tells the interpreter that your Python class will only need memory for the members defined in that sequence and restricts your ability to arbitrarily add new members (see [1] for details).
[1] https://docs.python.org/2/reference/datamodel.html#slots
http://morepypy.blogspot.ca/2010/11/efficiently-implementing...
__slots__ as PyPy shows is completely unnecessary.
2. __slots__ are not actually useful, Pypy does what they do by default and deoptimizes as needed, CPython probably could as well
3. the only thing __slots__ do is lower memory usage (by not allocating a dict per instance) and PEP 412 has already improved that
__slots__ is not "crazy useful" by any definition of the expression, it is somewhat useful when you have a huge living number of simple objects.
>>"In recent years there is a clear trend of making Python more complex as a language. I would like to see the inverse of that trend. I would like to see an internal interpreter design could be based on interpreters that work independent of each other, with local base types and more, similar to how JavaScript works."
Sounds like OP should investigate Lua (and LuaJIT in particular).
He might like Lua more than Python.
(Given that OP created Flask, I'd love to see a Flask equivalent developed in Lua)
Edit: typo
>> This is in fact how many other dynamic languages work. For instance this is how lua implementations operate, how javascript engines work etc. The clear advantage is that you can have two interpreters. What a novel concept.
(Just a joke, people. Just a joke.) Anyway, I wonder why Armin's not more involved with core Python things, his perspective should be valuable. As someone doing some Python stuff on the side his articles are always worth reading carefully.
The Python community has always been the best part of the language, but the important subcommunities like NumPy, Twisted and PyPy has always seemed like they are a bit outside looking in. I don't know why. Perhaps the language would have evolved differently if these projects were a bit more involved in the actual language development.
So I think it's about time that leaders of the community like Ronacher, Rietz, Gaynor, etc come together to talk about the next generator of Python.
We have PyPy now; why not use the tremendous advances there in the next Python?
We have Go and Javascript to compete with and we understand a lot of why they're winning; it's time Pythonistas fought back instead of just leaving.
Python 3 was supposed to be "the next thing" five years ago; it fizzled. Let's make the real "next thing" for 2016. Python 4.
Now people are just getting a lot of stuff done with this productive language and nobody needs to be convinced any longer how good a language it is. Most people already know.
Now, we're onto the good work of building a huge ecosystem of open source modules atop it. Call me when Go and JavaScript have the equivalent of the PyData stack and rock-solid drivers for every database technology on the planet. Then maybe I'll look at them for anything other than niche use cases. (Obviously JavaScript is still the only game in town inside the browser and Go seems like a pretty interesting alternative to C for UNIX system utilities.)
I agree Python is, in my subjective opinion, the best language spec and community in programming. It's simply the most fun, productive environment.
But people are leaving; important people and newcomers and loyal stalwarts. Im on the go right now so can't access links, but there have been a handful of posts here in the past 6mo or so of prominent members leaving, or sharing their disenchantment. Many other "I'm moving to go" posts. And the velocity of npm/go are undeniable (look at the stats). Remember, npm is largely for the server, where js shouldn't have an advantage.
I love Python. I want it to win. Maybe "lose" is too strong of a word, but it's certainly slipping.
Things fall apart; the centre cannot hold;
Mere anarchy is loosed upon the world,
The blood-dimmed tide is loosed, and everywhere
The ceremony of innocence is drowned;
The best lack all conviction, while the worst
Are full of passionate intensity.As a full time python developer I'm seriously concerned about how viable it is as a platform going into the future; this 'everything is fine' attitude is the problem.
WAKE UP.
Python is not doing fine.
It's growing as the target for scientific computing (which is great~), but I'd argue that's masking a downturn in the use of python for serious software engineering tasks, where the people who traditionally used it (webdevs, backend system tool makers, like disqus) are turning to tools with better performance and distribution tooling (like Go, node-webkit, etc) and less drama (py3).
I would argue this means quite the converse - JS will die while bejng replaced by language ports which compile to JS. Python included.
secp256k1.nim: https://www.refheap.com/9f22921d3d39d2c47ce8a633b
secp256k1.py: https://www.refheap.com/97fcb85a23fff65a6e207add2
It's not about "hype period". It's about moving on with the times to avoid becoming the next COBOL or TCL. Being even older and problematic than Python haven't stoped a language like C++ to ease its users problems and make them happy with C++11. Javascript, almost as old as Python (1995 vs 1991) got 20-100x speed boost with the 2006-era generation of JITs.
A ho-hum remake, like Python 3, that breaks compatibility without much important to offer, doesn't cut it. If you're gonna break compatibility solve real problems people have. A large speed boost (entirely possible as V8, LuaJIT and co have shown even for a most dynamic language) is a great thing to entice upgrades. A good async/multicore story also. The removal of GIL. Etc. Those are things people have been nagging Python devs about, not improved Unicode or print as a function.
>Now people are just getting a lot of stuff done with this productive language and nobody needs to be convinced any longer how good a language it is. Most people already know.
Languages that nearly vanished from the job market and current use trends, like Smalltalk, TCL and Perl also said the same thing...
Exactly this. Python 3 was an unfortunate triumph of purity over practicality. We'd be in a much better place if half of the effort expended in the Python 3 transition was instead focused on the issues you listed, and I'd also include browser support by compilation to JS.
You mention "a good async story" -- that has already been addressed with asyncio. A better multi-processing API has also been addressed in the concurrent.futures module. It's true that "multi-core" is still unsolved in Python, but most practitioners work around this problem by just using process-oriented parallelism instead.
Nonetheless, the frequent complaints about multi-core haven't fallen on deaf ears; they will probably come next! It's pretty much the primary focus of the pypy project and recent development work has begun on a Software Transactional Memory implementation that would remove the GIL.
GvR at PyCon 2014 said that he thinks pypy is the future of core Python development -- and that at some point in the future, pypy might become the reference implementation rather than CPython.
So, to conclude, I agree with your points, but progress is already advancing on many of the fronts you are demanding from the community.
I think the future of programming languages clearly belongs to statically typed languages, and Python will not be part of this future unless it evolves in that direction.
I recently got fed up with python and have been doing C, Go and Lua instead. I've started to rediscover programming and I'm enjoying myself much more. Go is very addicting.
It all started when I tried to get one of my projects that requires a lot of concurrent IO working in both Python 2.7 and 3.x. Gevent, of course only works in Python 2, so I tried to switch to the asyncio family. This was a disaster.
I'm sad to see it go, but I've decided to mostly drop Python. I'll probably still use it for Flask apps (I seriously love Flask). But anything that requires heavy lifting will probably be done in Go or C.
Because PyPy as cool as the project is, is terrible to develop on unless you are a PyPy person. I would consider myself a reasonable programmer but PyPy makes me go crazy. Slow iteration times, super complicated code.
There's lots of British comedy troupes that came after Monty Python, and lots of snakes if you want to go in that direction.
Also, <3 Flask. So good.
I wish that Python would introduce a few things from the Javascript world. Easy async, and a real-time Meteor like framework.