
Show HN: Shareable reasons to upgrade to Python 3 - kichik
http://whypy3.com/
======
beering
Aren't most of these also backportable to Python 2.7? Especially the
libraries, where the reason seems to be, "we added a nifty little tool."

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.

~~~
blickentwapft
Python 2 is dead, end of life coming soon, move on.

------
itamarst
You know, if Python 3 had been backwards compatible everyone would've been
using it 10 years ago and you wouldn't need to waste time creating stuff like
this. And more to the point, we wouldn't all have had to waste tends of
thousands of hours of programmer time porting to Python 3.

~~~
halfnibble
I'd have been using Python 3 ten years ago if they put something semantically
useful in like a switch/case statement.

~~~
raymondh
FWIW, I worked on a switch/case for Python about ten years ago and abandoned
the effort because it reached a dead-end.

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.

~~~
tonyedgecombe
I'd be happy with the syntactic sugar.

~~~
sametmax
I don't see how it saves you that much of typing.

~~~
halfnibble
It's not about typing. It's about code legibility. With a series of if/elif's
you have to mentally evaluate each condition to verify what's happening. If
the use case really is switch/case, then a switch/case statement would allow
the programmer to mentally evaluate only one condition and quickly glance at a
list of possibilities.

------
jchw
Not very compelling at the moment considering how few examples there are. But
fully explaining why Python 3 is worth it is at this point, actually quite
hard. Things like better Unicode support, type annotation syntax, and removal
of old school classes are some of my favorite reasons.

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):
    

I think this case also enforces that you don't add any additional positional
arguments that go unused.

~~~
Animats
Unicode support and new style classes were in Python 2.7.

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.

~~~
canjobear
> Unicode support and new style classes were in Python 2.7.

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.

~~~
mjevans
I actually argue that it's worse. In Python 3 you are FORCED to deal with
unicode encoding; Python 3 does not react well with legacy data that should
just be handled as is (without making things worse or incompatible).

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).

~~~
dbcurtis
Well, I spend most of my time dealing with internet and serial protocols, and
the strict demarcation between unicode strings and byte strings is what keeps
me sane. Explicit encode/decode calls are a feature, IMHO.

~~~
Avernar
I wouldn't mind the strict demarcation if the internal format was UTF-8. Then
a simple validate call on input would be all that was needed.

------
cdubzzz
It would be nice to have a little plain English description for each example
as well. E.g. the suppress example[0] kind of does this with a comment, but
the Enum example[1] isn't really clear about what advantage it creates over
Python 2.

[0] [http://whypy3.com/#2](http://whypy3.com/#2)

[1] [http://whypy3.com/#8](http://whypy3.com/#8)

~~~
jajern
At the bottom there is a link to the inspiration for this project. It has a
much better format. "You can already do this:" "Now you can do this:" which
actually shows the differences. Really a simple explanation of what's
happening and why it's useful and why it's better than py2 would be nice.
Especially for newer programmers who are trying to figure out which version to
start with.

------
scribu
Those seem like excellent reasons, but I really don't like that they keep
repeating after a while.

~~~
jwilk
There's only 9 of them.

If you disable JS, they'll be shown all at once.

------
Smaug123
The very first one I was presented with was the following perversity:

    
    
        from pathlib import Path
        directory = Path("/etc")
        filepath = directory / "test_file.txt"
    

Overloading the addition operation for list concatenation: fine. Something
something monads composition symbol. But the division operation?

[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.

~~~
khedoros1
We've got a C++ codebase with its own path class, which works this way. They
also used unary operator* (dereference operator) in the string class to return
a pointer to the underlying c-string. These are the "clever" kinds of things
that the original devs used to get kind of sheepish about when I first brought
them up.

~~~
ktRolster
At one time, operator overloading was encouraged. See for example, << in the
cout command. Everyone was trying to think of new ways to use them.

~~~
khedoros1
Well, and it worked well enough, in the limited context of our software
system. There were a few quirks like that, that everyone knew about. It was
kind of funny how opinions changed in the years between when it was written
and when I started working there, though.

------
NiceGuy_Ty
I do every new Python project in Python 3 when I can. Unfortunately, there are
still cases where I need to write a script to run on CentOS6 environments, and
I can't install any dependencies :/.

~~~
tmearnest
I've always just bit the bullet and compiled Python 3 and installed it to
~/.local when I had to deal with such a system. It generally compiles without
needing me to build any other dependencies. Unless I need sqlite, berkeley db,
tk et al., that is...

------
sametmax
For those you are still wondering why you should use Python 3, you should know
that most of the reasons given to you have been far from the best one.

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.

------
TekMol

        a, *rest, b = range(10)
        print(rest)  # prints [1, 2, 3, 4, 5, 6, 7, 8]
    

In which context could this be useful?

~~~
tomrod
When you want to quickly slice off the first and last elements of a list?

~~~
kmill
If it's a list (and not a generator like `range`), then `l[1:-1]` will do.

~~~
tomrod
Of course.

Consider though:

a, b, c = (l[0], l[1:-1], l[-1]) is also feasible, but I think it adds a bit
of overhead

