If so, then why the breaking language change? Why should I port my Python 2.7 code to Py3 for some libraries that I didn't feel like I was missing?
I'd suggest including more demos of how the backwards-incompatible changes made Python 3 better than 2.7.
Because Python 2.7 will no longer be supported past 2020.
You could have broken down those changes into small pieces, with deprecation. But then, you would have spent the last 10 years changing your code every 2 years. I don't think that's better.
Look at the JS community. They break things every 6 months. The result ? Oh they are moving fast.
But most projects I met in JS are disposable ones. They will not evolve. They will not be maintained. They will be trashed and rewritten.
So yes, the transition has issues, and it could have done it better. But it's far from as bad as most people say it is. People just like to be have everything without paying any cost, but it doesn't work. They want a modern language, but that never changes. They want something stable but that stays up to date. They want to write code and never touch it again, but then complain they can't use their shinny new toy.
And seriously, I always hear about those too many huge hours spent to port code 2 to 3. That is so much bullshit.
I do that regularly with my clients, and that's far, far away from the reality. Unless you have some very exotic code, it's a few minutes per files. Something you do anyway cause you redactor and clear your code.
The team of numpy, twisted and dropbox did suffer from the port. But come on, most people are not them. And THEY didn't complain. People that don't have the problem usually complain the most. They are just scared of the movie they played in their head. They all think they are a special snowflake.
Without the ability to mark variables as constants, a switch-case can't implement an efficient jump table. And without a jump table, a switch/case statement is merely syntactic sugar for an if/elif/elif chain.
Now everyone uses python 3 and has stopped griping, which wasn't warranted in the first place.
Also, when making kwarg only functions, you don't need to name the rest args parameter. You can do this:
def a(a, b, *, options=None):
Type annotations that don't do anything are one of the worse ideas I've ever seen in a programming language. Optional type annotations that are checked and used for optimization would be fine. But what's gone in is useless. Also, the syntax, which puts some type information in comments, is lame.
Python 3 isn't bad at this point. The first few years of Python 3 really sucked. The syntax was less compatible, and particularly hard on those who used Unicode in Python 2.7, because u'abc' was prohibited. "2to3" didn't work very well. Many, many libraries were not converted. The newer libraries for Python 3 were buggy due to being underutilized. Python 3 before Python 3.3 was quite bad.
Most of that's been fixed. The "six" module was a big help in porting. Eventually, "u'abc" was allowed. Most of the libraries were ported and available and debugged on both 2.7 and 3.x. But it took many years, and gratuitous incompatibilities made it harder than necessary.
It's fitting punishment for Von Rossum that he's forced to maintain the Python 2.7 system at his day job at Dropbox.
Unicode support is tremendously easier in Python 3. You don't have to deal with the confusing encode and decode stuff, and Python 3 strings have the right behavior in a lot of weird cases where Python 2.7 unicode objects do not.
Unicode support was my biggest reason for switching to Python 3, because I was dealing with natural language data with a lot of emojis and Python 2.7 was just an endless headache.
The alternative is to use a byte array without an encoding, which would be OK if Python 3 made coercion between the two easy (and had the concept of a 'validated' unicode string; operations known to keep a unicode string valid could leave that set, otherwise it would be 'not validated' but you wouldn't /need/ to care).
This is only the case in python2. In python3(.6), I don't believe there is any type information that cannot be expressed only in comments.
As in any language, they “do something” in Python, to wit, enable static type checking.
Now, static type checking is provided by systems separate from the language implementation, but the still exists.
> Also, the syntax, which puts some type information in comments, is lame.
The comment-based component of the syntax is a compatibility feature for Py 2.x.
That's almost a direct quote from the static typing proposal. No such checker existed at the time. There's a half-completed one, "mypy". It's a bit different from Python 3.6 type annotation, though it tries to stay close.
If you disable JS, they'll be shown all at once.
from pathlib import Path
directory = Path("/etc")
filepath = directory / "test_file.txt"
[Apparently I don't know Windows very well, since I'm told the following sentences are wrong:] Anyway, I thought Python was meant to try and be cross-platform. On Windows, the forward slash is not a path separator.
Unless it was Cygwin being sneaky, that is...
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type # pylint: disable=invalid-name
The best reason to move to Python 3 is:
-- It is just an easier language --
It's easier to write. It's easier to read. It's easier to maintain. It's easier to debug.
The problem is, there is no killer feature that shows that.
You only realize it when you wrote 10 projects in Python 2, and 10 in python 3, which I did.
What makes Python 3 easier is not "this one big thing", but a hundred of little things that cumulatively make your whole program just easier to <anything>.
Among the stuff:
- A lot of mistakes you could make with Python 2 are impossible in Python 3. Stupid comparisons, bad import layouts, concatenation of string and bytes, overriding keywords, loading too many objects in memory...
- Things are just less verbose. Automatic super(), no object inheritance, better unpacking, no from __future__ or encoding declaration, no longer generator aliases, f-strings, imports from codec...
- The right thing to do is more obvious. Way less aliases for modules, methods and built-ins, the easiest way is usually the best way (f-strings, range(), etc), division is doing what people thinks...
- The stdlib is way more consistent. Better naming, unicode/bytes in => unicode/bytes out, the __path__ protocol allow Path objects everywhere...
- Python is globally easier to debug. The error messages are better, we have new tools to debug memory consumption, but all in all, because everything is easier, you just produce less bugs. And you can type check on big code bases if you wish to.
Each of those things are not revolutionary. But cumulatively they are adding up to a huge difference. Much like being in the sea doesn't feel that much different until you go out and gravity calls again. That's why it has been hard to sell.
That and the fact Python 3 has started to be usable only on 3.3, cool in 3.5 and to really, really rock in 3.6.
What's more, most of those things could NOT have been done without breaking compatibility. True, improving error messages could, but fixing unicode, comparison, verbosity, naming, etc. would have broke so many programs anyway. But yes, they could have been done more incrementally though.
However, I can't help but notice that a lot of people complaining are doing so for the sake of it. Without real knowledge about it.
Most porting take a few minutes to a few hours. Not kidding. I've been doing that a lot. It's way scarier in people's head.
In reality, it is not that much work. Very few people have such a big and complicated code base that it's hard to port. They do exist. And it's a real pain for them. But most people on this thread are not them.
Porting to Python 3 is most of the time really easy, and the gain , while not obvious at first, are actually quite enormous.
What's hard is to make this shitty mix of 2 + 3 compatible code base.
In all case, I'm quite glad a lot of people will wait until the last minute to migrate. I'm starting to position myself as a consultant export in 2 => 3 and I plan to make a lot of money with it in 2020.
a, *rest, b = range(10)
print(rest) # prints [1, 2, 3, 4, 5, 6, 7, 8]
head, *tail = list_to_split
head, tail = list_to_split, list_to_split[1:]
a, b, c = (l, l[1:-1], l[-1]) is also feasible, but I think it adds a bit of overhead