
Python 2 vs. Python 3: A retrospective - mitchelllc
https://www.dropbox.com/s/83ppa5iykqmr14z/Py2v3Hackers2013.pptx
======
justinmk
I'd really like to see the video for these slides. But here's what caught my
interest:

    
    
        Set and dict comprehensions
        {x**2 for x in range(10)}
        {x: x**2 for x in range(10)}
    
        Why reduce() must die:
        ... the applicability of reduce() is pretty much limited
        to associative operators, and in all other cases it's 
        better to write out the accumulation loop explicitly.
    
        int [divided by] int should return float
    
        nonlocal
    

Explicit nonlocal variable modifier which (I guess) "promotes" the variable
outside its local scope. Kind of the inverse of Java requiring 'final' to bind
a variable to a closure.

~~~
jzwinck
You know what's funny? All of those things could have been done in Python 2.8,
apart from the int division change. And the division change does as much harm
as good, because lots of people use Python and also use another language where
int division works the "old fashioned way"; for them (me) this change is
counter-productive because it adds a pointless distinction. It is a great
change for programming novices, for sure, but that's only part of Python's
audience, and probably won't be the longest-lived part.

~~~
yen223
The division change is good. I have a hard time understanding why you'd want

    
    
        3/2 = 1
    

as the default behaviour.

~~~
TylerE
Imagine the following (admittedly bad, minimalistic to make my point) code

    
    
        x = int(input(">>> "))
        a = x / 2
        append_int_to_magical_db(a)
    

If the division does a "naturaL" thing, you suddenly have a float "polluting"
your integer algorithm, but it's _not consistent_. If the user enters "4", you
get an int back. If they enter 5, you get a float.

~~~
meowface
Users of Python 3 and up will just have to remember that the result of any
division will be a float.

It's a breaking change, yes, but in general I think it's a good one.

~~~
nhaehnle
And if they do want integer division, they have to remember // and %.

------
yeukhon
The one thing I wish they could change in the future is forcing list and
dictionary iterable same syntax:

instead of writing

for index, element in enumerate(some_list)

for key, value in my_dict.items()

they should unify and make items and enumerate default behavior. i.e.

for index, element in my_list:

for key, value in my_dict:

I really don't see the benefit of not doing this as default behavior. I always
find if I need to loop a list there is a good chance the index can help, and
even if I don't need it it doesn't hurt to have one either. Simple is better.
And the whole looping dict and get back the key only sucks too because you
often need the value as well so you essentially do dict["key"] but why not
just default return both key and value?

~~~
asperous
Explicit is better than implicit.

I think you think for is magical and could be modified like this, but really
for just iterates over something. It's enumerate and items that are the magic.
Enumerate zips a range onto a list, the ``index,element`` unpacks the zip.
Items returns a list of (key,value) tuples and the key,value unpacks that.

You couldn't modify the iterators because it would effect EVERYTHING.
sum([1,1,1]) would now be sum([(1,1),(2,1),(3,1)]) AHH! And ``key in dict``
wouldn't work any more, since the iterator would return key,values. EEK.

~~~
yeukhon
I never said it would be easy to implement or whether it would be actually
possible. My complain is that what we are doing right now isn't convenient and
is counter-intuitive. I don't write programming language so I wouldn't know
how difficult it would be to change the grammar and the semantic of for.

Being simple vs explicit is a political debate. I prefer if Python has simpler
magical syntax.

~~~
aidos
That's totally against the ethos of python. I think you'll find that very few
python developers would side with you on that change. If I'm iterating over
something I'd like the elements of the thing I'm iterating over, not some
weird results based on the type of iterator. In the (extremely) rare cases I
need an index I wrap the list/whatever in the enumerate function.

What are the use cases where you frequently need the index? I write and read a
lot of python and I almost never see it. Maybe if you're working in a problem
domain where it's a common issue you could create some abstraction to better
handle it for you.

~~~
yeukhon
Whoever downvoted me have some weird negativity here.

It doesn't against ethos of Python. There is a Zens of Python, I don't know
Ethos of Python.
[http://www.python.org/dev/peps/pep-0020/](http://www.python.org/dev/peps/pep-0020/)

Beautiful is better than ugly. Writing .items() or surrounding enumerate()
does not make your code look prettier, does it?

Explicit is better than implicit. In fact, my proposal is more explicit than
the implicit of for key in my_dict or for item in my list. I think returning
both key,value are more explicit than say remembering the default return value
in looping a dict is a key, not value, or relying on remembering enumerate or
items.

It is simpler to write such code, and if you just need one of the return
values, just that one, they are named.

You want a use case. I will give you one: find the location of a specific item
in the list. and if you use django, you know your template engine can read
your psudeo python template code. And you often need that index.

~~~
pdonis
_my proposal is more explicit_

One could just as easily say that your proposal is _less_ explicit, because a
sequence is a sequence of items, not (index, item) tuples, yet you're making
the "for" iteration yield tuples.

Similarly, a dict is a container of keys, not (key, value) pairs. The reason
is that otherwise you would be unable to check to see if a key was in the dict
unless you knew the value that went with it: but in that case why would you
need the dict? (Technically, you could still iterate over the entire dict
looking for your key, but that's extremely slow; the whole point of having a
dict is to be able to do _fast_ lookups of keys in order to retrieve their
values.)

 _Writing .items() or surrounding enumerate() does not make your code look
prettier, does it?_

Neither does having to extract just one item from a tuple when I don't need
the index. There's no way around the fact that _one_ of the types of iteration
(either just items, or index, item tuples) is going to have to be spelled with
something extra. So just saying "I shouldn't have to type something extra"
isn't a sufficient argument. You need to justify why your preferred type of
iteration should be the one with the shorter spelling: and since your
preferred type of iteration has extra baggage attached to it, it seems
perfectly legitimate to me that it should have the _longer_ spelling, not the
shorter one.

 _find the location of a specific item in the list_

That's what the "index" method is for.

~~~
ceol
I forget if it's Jinja or Django's template, but one of them has a function
that only exists inside of for loops that returns the current index. I thought
that was a great way to handle it, since it's always available without
changing any syntax.

In retrospect, I suppose the .index() method would be fine, since Lists can't
hold two of the same object, and Dicts return the key by default.

~~~
pdonis
_Lists can 't hold two of the same object_

Yes, they can. Try it! The index method has extra arguments to let you specify
a range of indexes in the list to search, so you can find multiple indexes
that point to the same object (by picking a range that excludes indexes you've
previously found).

 _Dicts return the key by default_

Dicts don't have an index method; dict keys are not ordered.

------
MBlume
Can anyone else not read the last lines of some of the slides?

~~~
ChronosKey
Dropbox's powerpoint viewer isn't perfect. I had to download the pptx. Works
fine in Keynote.

~~~
jzwinck
Thanks for pointing out it's a Dropbox thing--at first I thought it might be a
Chrome problem. Specifically the viewer seems not to use the proper font for
this presentation. Preview on Mac OS works fine.

~~~
MBCook
What was worse for me was the font kerning on some things (supposed to be
fixed width?) was _amazingly_ atrocious.

I'm kinda impressed though. I don't think I have a program that will view pptx
files, so I was happy to be able to read it online.

------
_random_
"People positively hate incompatible changes – especially bad for dynamic
languages", "Never again this way – the future is static analysis and
annotations".

Wouldn't it be better to pick a better-suited language then?

John Carmack put it nice way:

"One of the lessons that we took away from Doom 3 was that script interpreters
are bad, from a performance, debugging, development standpoint. It’s kind of
that argument “oh but you want a free-form dynamically typed language here so
you can do all of your quick, flexible stuff, and people that aren’t really
programmers can do this stuff”, but you know one of the big lessons of a big
project is you don’t want people that aren’t really programmers programming,
you’ll suffer for it!"

~~~
LBarret
Epic might disagree, the UnrealEngine is heavily scriptable. This was one of
its major selling points in the last generation.

I have a huge respect for Carmack but some other people prooved him wrong in
the past. His opinions are often taken as gospel but more discreet people
(like Sweeney) may have different and a s worthy points of view.

------
tomp
Why does Guido think that slices syntax is screwed up? I mean, it's not
exactly natural, but at least it's consistent (first bound is included, second
is excluded):

    
    
      a = '12345'
      a[0:-1] == '1234'
      a[-1:0:-1] == '5432'
    

Personally, I think that "downcounting" slices are rarely used. For code
clarity, I prefer reversing the string/list first.

~~~
JeffJenkins
This came up on python-ideas recently, there was a long thread:
[https://mail.python.org/pipermail/python-
ideas/2013-October/...](https://mail.python.org/pipermail/python-
ideas/2013-October/023733.html)

------
midgetjones
I would have been more interested in learning Python if there wasn't such a
great divide. I read the first chapter of several books that said "Python 3 is
out, but we're going to stick with 2.7 because too much shit is broken".

~~~
jzwinck
As someone who learned Python when 3.2 came out, I completely agree with you.
I have only really used Python 2.7!

Because too much shit is broken (NumPy, hello). Because Python 3 has been the
default on basically no system ever (OK, maybe this is changing right now,
slowly).

As Guido says, it's been five years and it will take another five. This whole
experiment has been a huge misstep for Python, an absolutely massive gaffe.
Some of Python's peers did it too, roughly around the same time (Perl, and to
a lesser extent Ruby).

Python (Guido?) noticed its own maturity a bit too late. The damage is
incredible; along with the performance stuff (which is in a way easier to
overcome) this may be a key factor leading to the fall of a great language.

~~~
nron
On the other hand, my experience has been very different: I learned Python
when 3.2 was current as well, using Lutz' "Learning Python", which takes the
approach of "teach Python 3, and explain how 2 is different whenever
necessary". I've followed suit and taken the approach of writing Python 3 code
first, and to make it work on 2.7 only when I need to, which I found fairly
easy to do, though it can make the code a bit uglier sadly (writing cross-
version-compatible metaclass code is the one that annoys me, since it adds
some verbosity).

I'm looking forward to 2.x dying out to eliminate that retrofitting step (and
it's happening: the improving dependency landscape means I find I have to do
it less and less often), but I've not experienced any major pain overall. From
where I'm sitting, Python 3 is a better, cleaner language, and as someone new
to Python, I'm happier for it.

~~~
chilldream
My story is similar, and I learned Python 3.2 _for_ Numpy.

------
michielvoo
Question for the professional Python developers: do you (on a
daily/weekly/monthly) basis switch between projects in Python 2 and Python 3?
Is that hard to do (e.g. do you have to constantly and consciously remind
yourself of syntax/semantic differences), or does your mind sort of
automatically adjust to the new/old patterns?

------
pmelendez
This is my problem with Python: "Rename func_name —> __name__, etc Rename
.next() —> .__next__()"

Too many ugly renames, too few alternatives of doing things. To be honest the
only attractive thing to me is all the libraries that they support but I don't
find the language itself interesting.

~~~
sillysaurus2
__ is basically a namespace for official language extensions. How would you
suggest they do it? Prevent "next()" from being a valid method name?

~~~
pmelendez
That has been addressed in some many other ways by several languages that goes
from the C++ way where you actually have namespaces to the C way where you
don't worry about it and pick another name. From all of them I find this the
most odd way to address it, specially when python was supposed to improve
legibility by design (at least for me those underscores are very distracting)

~~~
chilldream
The underscores are distracting on purpose; any method surrounded by double
underscores is one that you're virtually never supposed to explicitly call
(there's a builtin `next(foo)` in Python 3, for instance)

------
izzle9
whoa did he just say static analysis is the future?

~~~
andreisoare
yeah, I'd love to understand the reason behind that statement.

~~~
nly
PyPy?

~~~
masklinn
pypy is dynamic analysis.

~~~
nly
Semantics. Pypy's RPython dialect is "a restricted subset of Python that is
amenable to static analysis", to quote the PyPy website.

~~~
masklinn
RPython and Pypy are different things.

RPython is a restricted subset of python indeed, but its purpose is to be a
toolkit for implementing virtual machines. It is not and does not aim to be a
general-purpose programming environment.

PyPy is a JITed Python runtime implemented in RPython.

The relation between PyPy and RPython is more or less the relation between
CPython and C.

------
fidz
Could someone create/convert the PDF version? I don't think my computer good
enough to open PPT* format

Edit: not really needed, just loaded the dropbox preview, it is still readable

------
mortenlarsen
Angry noscript user here. Visit URL... almost blank page... with non-working
download button. Enable Javascript... Get .pdf named .pptx.

~~~
justinmk
> Angry noscript user

Redundant, I think.

~~~
zwegner
As a noscript user, I think you're probably right.

------
rpedela
Does Python 3 fix the import system? Can I import a file from any location in
the file system?

~~~
baq
you always could, see __import__ and imp module.

------
pstuart
Now that I get to use Go, I have no desire to go back to python. I think I'm
not alone, and that python will soon enough become the new perl.

~~~
spamizbad
The Python ecosystem is far too diversified to get knocked down by one
language. Python has a wealth of production-quality libraries across a ton of
domains (Web, scientific computing, data science, NLP, parsing,
scripting/automating, etc). Go is a non-entity in most of these domains and
isn't even a top-20 programming language on Github (source: [http://sogrady-
media.redmonk.com/sogrady/files/2013/07/progr...](http://sogrady-
media.redmonk.com/sogrady/files/2013/07/programming-lang-rankings-june13.png))

Python went everywhere Perl did and then expanded the map for "scripting
languages". This didn't happen by accident: Python is, by design, very easy
comprehend and learn. The Python community also one of the most newbie-
friendly around, with mountains of freely available resources for beginners.

A programming language cannot be sustained by uber hackers, PLT nerds, and
hipsters alone. You gotta make it reach the world (Like JavaScript, Java) or
it'll never be"Tier 1" programming language. I have yet to see the Go's
developer or community put forth a strategy to make this happen -- which is
completely understandable given how new the language is.

~~~
steveklabnik
The scientific Python community will never leave 2.5 -> 2.7, though...

~~~
ajford
The science community will get there. The problem is that for a long time,
NumPy/SciPy/etc. didn't support 3.x. And when you're more interested in end
results, why would you rewrite your code (or spend days/weeks/months
relearning) when you could use a still perfectly acceptable and supported
version?

There's also a lot of reuse and expansion on existing code bases, which would
involve a lot of work to migrate to 3.x. There's also the matter that on top
of moving to 3.x, you also have the task of making sure there's no hidden bugs
that may alter your results in ways you may not notice. A lot of scientific
code has been repeatedly vetted to make sure that there's no bias or glitches
that may skew your results.

Hell, I know astronomers who are still using Fortran code that was written in
the 80's. It still works (though now it requires a long build process, as it
is no longer compatible with the latest Fortran compilers), so no reason to
try to rewrite it just because the language is dated.

~~~
masklinn
> The science community will get there. The problem is that for a long time,
> NumPy/SciPy/etc. didn't support 3.x.

They were some of the earliest ported widely-used packages. Numpy was ported
in 2010, scipy very early in 2011 (except for weave iirc)

------
U2EF1
empty dict: {:} empty set: {}

Ah, the road not taken.

------
andyl
It seems like I've been reading about the difficulties of Python V2 -> V3 for
awhile. Why is that? Is this Python upgrade unusually difficult/ambitious? Or
is the Python community just very reluctant to jump on new things?

~~~
lmm
It's a big, ambitious update. The biggest difference is forcing users to
distinguish between strings and byte sequences; essentially programs now
_have_ to be encoding-aware (at least if they use any of the standard library
functions). Which is a Good Thing, but can require a ton of work for existing
codebases.

~~~
krakensden
It's not that ambitious- none of the changes are particularly compelling, none
of them scream "update now".

It does, on the other hand, break backwards compatibility. Which is why hardly
anyone updated.

~~~
smnrchrds
Maybe not in the world of ASCII, but the new Unicode system scream seems
pretty loud to me.

When I decided to use pelican for a non-English blog, I thought it would be
piece of cake; just changing the theme and plugging a calendar converter and I
would be done with it. In reality, I had to fork pelican and the calendar
library (which was not well-maintained) and bang my head to the wall for three
days to make them work together, all because of the whole string/unicode
seperation and the fact that things work automagically as long as you're just
using ASCII.

~~~
gcr
Does this get easier or harder in python 3?

I like the explicit separation that Racket has between "here is a buffer of
binary data" and "here is a sequence of Unicode characters," and (looking on
the outside without working with it), I'm glad that Python 3 began to adopt
some of that.

~~~
rspeer
smnrchrds's case of fixing someone else's ASCII assumption gets easier,
because the code probably would not have been written that way.

In Python 2, it's really easy to write code that confuses bytes and
characters, which introduces bugs and crashes when non-ASCII characters show
up.

In Python 3, they made it easier to work with Unicode, because it's the
default for everything, and _much harder_ to confuse bytes and characters,
because of that separation between the data types.

------
mixmastamyk
As a dev that hasn't been able to move to Py3 yet (but will soon), I'm wishing
they'd fix the rest of the issues, bundle PyPy, and ship Python 4 instead!
Make it a compelling upgrade.

Then Py3 could be nicknamed "Vista," I suppose.

