To me, the killer feature is better lazy evaluation (generators). In particular, important builtins like map, filter, zip, enumerate, etc are generators, instead of returning lists. This makes it feasible to write things like
(process(line) for line in map(str.upper, open('giantfile.txt')) if line.lstrip()[0] != '#')
Some of the above can also be done with itertools package in Python 2, but not everything.Python 3.4 changelog is here, it contains e.g. asynchronous io facilities (asyncio module): https://www.python.org/downloads/release/python-342/
edit: added enumerate() in the example above, for line in open(filename) returns a generator in Python 2.x too.
edit2: enumerate is lazy in python2, I replaced it with map(str.upper)
Generators provide a convenient syntax to implement that sort of object.
But the point should be obvious, without generators that would potentially consume a lot of memory.
(process(line) for line in open('giantfile.txt') if line.lstrip()[0] != '#')
Is that line really using any new features in Python 3? The lazy evaluation there is in the file object and the generator expression, both of which have long been present in python2. (process(line.upper()) for line in open('giantfile.txt') if line.lstrip()[0] != '#')Here's another one you can't change that easily:
tests_pass = all(process(input) == output for (input, output) in zip(open('inputs.txt'), open('outputs.txt'))The fact that a bunch of builtins and the values/items methods of dictionaries have become iterators is not very siginificant IMHO. Python 2 code could already be written to use iterators or generator expressions, so in the parts where it was crucial it was already done. In this regard Python 3 has not added new functionality but only changed defaults.
The unicode change is the big one.
Changing that to line.lstrip().startswith('#') would be an alternate approach.
The key point is that 2.7 is a language frozen in time, while 3.4+ is continuing to develop and improve. And most of the hand-wringing was before the critical mass of third-party modules was ported to 3.x.
https://docs.python.org/3/whatsnew/3.4.html
https://docs.python.org/3/whatsnew/3.3.html
https://docs.python.org/3/whatsnew/3.2.html
- function annotations (allows runtime type checking via third party modules)
- asyncio (not as easy to use as Go's goroutines but still vastly superior to the multiprocessing module)