Why Python 3?

A

Anthony Papillion

Hello Everyone,

So I've been working with Python for a while and I'm starting to take
on more and more serious projects with it. I've been reading a lot
about Python 2 vs Python 3 and the community kind of seems split on
which should be used.

Some say 'Python 3 is the future, use it for everything now' and other
say 'Python 3 is the future but you can't do everything in it now so
use Python 2'.

What is the general feel of /this/ community? I'm about to start a
large scale Python project. Should it be done in 2 or 3? What are the
benefits, aside from the 'it's the future' argument?

Thanks,
Anthony
 
P

Paul Rubin

Anthony Papillion said:
Some say 'Python 3 is the future, use it for everything now' and other
say 'Python 3 is the future but you can't do everything in it now so
use Python 2'.

Python 3 is generally better than Python 2, except for a few packages
that haven't been ported.

That said, I don't know anyone who actually uses Python 3. I don't
think it's a matter of wanting to use some problematic package, or
having particular technical concerns. It's just that the improvement
from 2 to 3 is rather small, and 2 works perfectly well and people are
used to it, so they keep using it. There are nice tools that
help port your codebase from 2 to 3 with fairly little effort.
But, you can also keep your codebase on 2 with zero effort.
So people choose zero over fairly little.

If you're starting a new project and you get to choose between 2 and 3,
other things equal I'd say use 3. I've kept using 2 basically because
it's the path of least resistance. I'm somewhat following the 3
situation and of course I'd use 3 if I were doing something that
benefited from it, but so far it hasn't been an issue.

Eventually the main Linux distros will include 3 instead of 2 by
default, and we'll probably see more migration then. Right now I type
"python" and get 2, so I use it.
 
C

Chris Angelico

If you're starting a new project and you get to choose between 2 and 3,
other things equal I'd say use 3. I've kept using 2 basically because
it's the path of least resistance. I'm somewhat following the 3
situation and of course I'd use 3 if I were doing something that
benefited from it, but so far it hasn't been an issue.

Eventually the main Linux distros will include 3 instead of 2 by
default, and we'll probably see more migration then. Right now I type
"python" and get 2, so I use it.

Several of the main distros are already including Python 3 by default
(eg Ubuntu), but when you type "python", you still get Python 2, for
reasons of compatibility. (See PEP 394.) As long as you set your
shebang to say python3, it'll work just fine.

I strongly recommend going for Python 3 unless something actually
stops you from doing so. If you absolutely must use Python 2, try to
aim for a minimum of 2.6 or 2.7, and start your program with this
line:

from __future__ import print_function, unicode_literals, division

That'll make Python 2.6/2.7 behave like Python 3.x in three ways:
firstly, "print" will be a function instead of a statement (and it's
more powerful than the statement form, as well as being more
flexible); secondly, quoted strings will be Unicode strings, not byte
strings (that'll help you to start thinking about what's bytes and
what's text, which is an important distinction in Python 3); and
thirdly, though less important than the others, the division of two
integers will result in a floating point, not an integer. I personally
think the last one was a mistake on Python 3's part (why bless float
specifically? what if you're working with integers and
decimal.Decimals?), but if you're going to move to Python 3, you may
as well have your code start working that way, so you get used to
typing // to divide integers and get an integer (floor division).

But if you possibly can, aim for Python 3. Every new version adds
features, and new versions within the 3.x line break very little
(generally only what would have been working with a bug anyway, like
narrow Unicode builds of 3.2 becoming universal on 3.3). If you aim
for 3.2 today, and tomorrow try to run your code on 3.4, chances are
it'll work. The main thing is, know what's a text string and what's a
string of bytes; that's critical in 3.x, but not in 2.x. Force
yourself to think about that, and your code will be more reliable -
regardless of even what language you write it in.

ChrisA
 
I

Ian Kelly

That'll make Python 2.6/2.7 behave like Python 3.x in three ways:
firstly, "print" will be a function instead of a statement (and it's
more powerful than the statement form, as well as being more
flexible); secondly, quoted strings will be Unicode strings, not byte
strings (that'll help you to start thinking about what's bytes and
what's text, which is an important distinction in Python 3); and
thirdly, though less important than the others, the division of two
integers will result in a floating point, not an integer. I personally
think the last one was a mistake on Python 3's part (why bless float
specifically? what if you're working with integers and
decimal.Decimals?), but if you're going to move to Python 3, you may
as well have your code start working that way, so you get used to
typing // to divide integers and get an integer (floor division).

If you're working with decimals, then the result is a decimal. If one
side is an integer and the other is a decimal, then the result is
still a decimal. Similarly if one of the operands is a fraction, then
the result is a fraction. The change from / denoting "classic
division" to "true division" really only affects the case where both
operands are integers, so far as I'm aware. If you want to divide two
integers and get a decimal result, then convert one or both of them to
decimals first; you would have needed to do the same with classic
division.

We also gained a consistent and explicit way to differentiate between
the two different styles of division that classic division
represented, as opposed to picking at run-time based on type.

As for "why float" specifically, the division __future__ import has
been around since 2.2, longer than either decimals or fractions.
 
C

Chris Angelico

The change from / denoting "classic
division" to "true division" really only affects the case where both
operands are integers, so far as I'm aware. If you want to divide two
integers and get a decimal result, then convert one or both of them to
decimals first; you would have needed to do the same with classic
division.

If float were a perfect superset of int, and the only logical superset
when you want non-integers, then it'd be fine. But if you're mixing
int and Decimal, you have to explicitly convert, whereas if you're
mixing int and float, you don't. Why is it required to be explicit
with Decimal but not float? Of all the possible alternate types, why
float? Only because...
As for "why float" specifically, the division __future__ import has
been around since 2.2, longer than either decimals or fractions.

.... it already existed. There's no particular reason to up-cast to
float, specifically, and it can cause problems with large integers -
either by losing accuracy, or by outright overflowing.

Suppose you take an integer, multiply it by 10, and divide it by 5. In
theory, that's the same as multiplying by 2, right? Mathematically it
is. In C it might not be, because the multiplication might overflow;
but Python, like a number of other modern languages, has an integer
type that won't overflow. In Python 2, doing the obvious thing works:

x * 10 / 5 == x * 2

In Python 3, you have to say "Oh but I want my integer division to
result in an integer":

x * 10 // 5 == x * 2

Yes, I can see that it's nice for simple interactive use. You type
"1/2" and you get back 0.5. But doesn't it just exchange one set of
problems ("dividing integers by integers rounds") for another set
("floating point arithmetic isn't real number arithmetic")?

Anyway. While I think it was a mistake to bless float in that way, I'm
aware that it isn't going to change. Which is why, for anyone who's
looking at starting a project fresh, I recommend "from __future__
import division", as it'll make the port to Py3 that much easier.

ChrisA
 
M

Marko Rauhamaa

Ian Kelly said:
if you're going to move to Python 3, you may as well have your code
start working that way, so you get used to typing // to divide
integers and get an integer (floor division).

[...]

We also gained a consistent and explicit way to differentiate between
the two different styles of division that classic division
represented, as opposed to picking at run-time based on type.

Very often when integer division is needed, so is the remainder. Then,
it is good to remember the builtin divmod() function:

https://docs.python.org/3.4/library/functions.html#divmod

In fact, divmod() goes a long way toward removing the need for // and %
in Python code.


Marko
 
S

Steve Hayes

Hello Everyone,

So I've been working with Python for a while and I'm starting to take
on more and more serious projects with it. I've been reading a lot
about Python 2 vs Python 3 and the community kind of seems split on
which should be used.

Some say 'Python 3 is the future, use it for everything now' and other
say 'Python 3 is the future but you can't do everything in it now so
use Python 2'.

Yes, that made me more or less abandon my attempt to learn Python.

I had Python 3 on my computer (came on one of those freebie discs you get with
magazines, I think) and my son had a book on it, so I thought with the program
and the instructions I should be able to learn something.

It took me a week, with some help from this forum, to get the Print statement
to work.
 
C

Chris Angelico

Yes, that made me more or less abandon my attempt to learn Python.

I had Python 3 on my computer (came on one of those freebie discs you get with
magazines, I think) and my son had a book on it, so I thought with the program
and the instructions I should be able to learn something.

It took me a week, with some help from this forum, to get the Print statement
to work.

If your book and your interpreter didn't match, then that's a problem,
just as if you were working with different versions of any other
software. (Can you imagine reading through a Microsoft Excel tutorial
and trying to do the exercises in a different version of Excel?) The
print statement wouldn't work because there isn't one; the print
*function* will work quite happily, though. All you need is for
someone to explain it to you as a function, and you'll be fine.

ChrisA
 
R

Roy Smith

Chris Angelico said:
I strongly recommend going for Python 3 unless something actually
stops you from doing so.

One of the problems is you don't know in advance if something is going
to stop you. By committing to P3 now, you are eliminating from possible
future use, all of those third-party modules which only support P2. And
you don't know which of those you'll need until you sometime in the
future.

It's rare to find a modern, actively maintained module which doesn't
either support P3 already, or at least has that on its roadmap, but
there's a lot of old stuff out there which is still very useful.
If you absolutely must use Python 2, try to
aim for a minimum of 2.6 or 2.7

That I absolutely agree with. Unless I had some specific legacy use
case I needed to continue to support, I wouldn't waste any time worrying
about 2.5 support, and we're quickly reaching the point where the same
can be said about 2.6.
and start your program with this line:

from __future__ import print_function, unicode_literals, division

That seems reasonable, but be prepared for possible unicode issues.
There is code out there in third party modules which makes
unicode-unfriendly assumptions about strings. For example:

https://github.com/brandon-rhodes/pyephem/issues/35

I'm not saying don't use unicode_literals (we do), just we aware that
you might have to explicitly cast things to str() once in a while.
 
C

Chris Angelico

One of the problems is you don't know in advance if something is going
to stop you. By committing to P3 now, you are eliminating from possible
future use, all of those third-party modules which only support P2. And
you don't know which of those you'll need until you sometime in the
future.

Conversely, committing to Py2 now eliminates from possible future use
all modules which support only Py3. Is there strong evidence that one
of those groups is larger than the other?
That I absolutely agree with. Unless I had some specific legacy use
case I needed to continue to support, I wouldn't waste any time worrying
about 2.5 support, and we're quickly reaching the point where the same
can be said about 2.6.

Red Hat? :) Though that's likely to be the last bastion of ancient
Python out there, soon. Debian Squeeze (oldstable) ships with 2.6, so
if you aim for 2.6+, you should catch all the distros that derive from
Debian (the current Debian stable, Wheezy, ships with 2.7). But Red
Hat will be supporting older Pythons for a good while.
That seems reasonable, but be prepared for possible unicode issues.
There is code out there in third party modules which makes
unicode-unfriendly assumptions about strings.

Right. It's not the magic line that fixes everything; if it were,
Python 3 wouldn't be a big deal at all. Go Py3 if you can, but if you
can't, at least make your double-quoted strings Unicode strings, and
then you have a chance to find problems.

ChrisA
 
R

Rick Johnson

Hello Everyone,
So I've been working with Python for a while and I'm starting to take
on more and more serious projects with it. I've been reading a lot
about Python 2 vs Python 3 and the community kind of seems split on
which should be used.
Some say 'Python 3 is the future, use it for everything now' and other
say 'Python 3 is the future but you can't do everything in it now so
use Python 2'.
What is the general feel of /this/ community? I'm about to start a
large scale Python project. Should it be done in 2 or 3? What are the
benefits, aside from the 'it's the future' argument?

Python 3000 is the direct result of a hubris that even
surpasses Hitler's boneheaded attempt to fight the war on two
fronts. Yes, most of us agree that the changes are "positive
evolution" HOWEVER, are these minor repairs REALLY worth
polarizing a vibrant community and causing Python's
propagation to stagnate?

HELL NO!

Who would want to choose Python for a scripting language for
their project when EVEN the community cannot agree on which
version is best to use? But even *IF* every respected member
was a total "high-knee smooching tool" of GvR parroting off
that "Python 3000 is the best!", we cannot ignore the
functionality concerns that will result from choosing
between 2x or 3x.

NOBODY IS ACTIVELY CHOOSING PYTHON ANYMORE FOLKS!

Python is destined to destroy itself internally JUST like
the American society is currently destroying itself, and
what a travesty, since Python was the shining light of what
a program should be.

THE REVOLUTION WILL NOT BE TELEVISED!

Python is set to become extinct because GvR bought his time
machine AFTER infecting the code base with a print
statement -- thanks Guido, thanks for everything! Maybe next
time you should consider buying bean stalk beans instead!
 
R

Rustom Mody

It took me a week, with some help from this forum, to get the Print statement
to work.

How long does it take one to learn to drive a car?
To play the piano? To become a brain surgeon?

No I am not exactly in the "gung-ho over python 3" camp
However if you dont start out learning programming with an estimate of work somewhere between learning to:
- drive-a-car
- play-the-piano
you are setting yourself up for failure.
But its equally unreasonable to expect to learn programming more easy than to drive a car.
 
T

Terry Reedy

That said, I don't know anyone who actually uses Python 3.

I have no idea who you know ;-)

LibreOffice bundles 3.3. So anyone who does Python scripting in
LibreOffice is using Python 3. Actually, I believe LO uses Python
internally for some of its scripting. If so, everyone using LO is
indirectly using 3.3.
 
C

Chris Angelico

LibreOffice bundles 3.3. So anyone who does Python scripting in LibreOffice
is using Python 3.

This much I agree with...
Actually, I believe LO uses Python internally for some of
its scripting. If so, everyone using LO is indirectly using 3.3.

.... but this is kinda pushing it, I think. You're not *using* it any
more than you're using Python whenever you post to Savoynet [1] -
after all, Savoynet is a Mailman list, and Mailman runs on Python. But
all those theatre people don't become Python users because of that.
I'd have to say that "using Python 3" means writing code that runs in
Python 3. So the LO people would, by your statement, be using Py3.3,
as would anyone who actually writes LO scripts; but someone who just
fires up LO, edits a document in the WYSIWYG editor, and goes about
his business, isn't really using Python.

Though the broader definition does have its uses. It's fun to explain
to someone how that little device that shows him a map and where he is
on it is depending on both special and general relativity. (GPS
signals are strongly based on time, and the satellites are moving
relative to the observer, and gravity is weaker up there.) But you're
not really making use of the science yourself, you're depending on
someone else having made use of it - same as you can hop on an
airliner without understanding the physics of flight, much less the
effects of birdstrike on jet engines. You're just glad that someone,
somewhere, has worked all that out :)

ChrisA

[1] http://savoynet.oakapplepress.com/
 
A

Albert-Jan Roskam

----- Original Message -----
From: Chris Angelico <[email protected]>
To:
Cc: "(e-mail address removed)" <[email protected]>
Sent: Saturday, April 19, 2014 3:42 PM
Subject: Re: Why Python 3?

Right. It's not the magic line that fixes everything; if it were,
Python 3 wouldn't be a big deal at all. Go Py3 if you can, but if you
can't, at least make your double-quoted strings Unicode strings, and
then you have a chance to find problems.

Totally agree. It's not that hard at all. I consider it true craftmanship that Guido had the guts break backward compatibility and clean up some mistakes. Compare this with CRAN R, where so much illogical S-plus stuff is present (word count for "historical anomaly": 1000+ ;-).

Am I the only one who always thinks of Rogers' Diffusion of Innovations curve with these Python2/3 debates? http://en.wikipedia.org/wiki/File:Diffusion_of_ideas.svg. source: http://en.wikipedia.org/wiki/Diffusion_of_innovations
 
I

Ian Kelly

If float were a perfect superset of int, and the only logical superset
when you want non-integers, then it'd be fine.

Decimal is also not a perfect superset of int (although I believe it
is a superset of the intersection of int and float). Even if it were,
I'm not sure it would be appropriate to bless Decimal in this way
either, because they have no place in Python's number type hierarchy:
False

But if you're mixing
int and Decimal, you have to explicitly convert, whereas if you're
mixing int and float, you don't. Why is it required to be explicit
with Decimal but not float? Of all the possible alternate types, why
float? Only because...


... it already existed. There's no particular reason to up-cast to
float, specifically, and it can cause problems with large integers -
either by losing accuracy, or by outright overflowing.

The authors of PEP 238 expressed their hope that when a rational type
(i.e. Fraction) was implemented, it would become the result type for
true division on two integers. I don't know why that never came to
pass; perhaps performance considerations won out.
In Python 3, you have to say "Oh but I want my integer division to
result in an integer":

x * 10 // 5 == x * 2

Technically this says "I want the result of floor division", not "I
want the result as an integer". If you apply the floor division
operator to a non-int type, you'll get a non-int result. It just so
happens that the result of floor division of two integers can be given
as an integer, whereas the result of true division cannot.

Considering that Fraction and Decimal did not exist yet, what type do
you think the PEP 238 implementers should have chosen for the result
of dividing two ints? If float is not acceptable, and int is not
acceptable (which was the whole point of the PEP), then the only
alternative I can see would have been to raise a TypeError and force
the user to upcast explicitly. In that case, dividing arbitrary ints
using floating-point math would not be possible for those ints that
are outside the range of floats; you would get OverflowError on the
upcast operation, regardless of whether the result of division would
be within the range of a float.
Yes, I can see that it's nice for simple interactive use.

More importantly, it's useful for implementers of generic mathematical
routines. If you're passed arbitrary inputs, you don't have to check
the types of the values you were given and then branch if both of the
values you were about to divide happened to be ints just because the
division operator arbitrarily does something different on ints.
 
C

Chris Angelico

Considering that Fraction and Decimal did not exist yet, what type do
you think the PEP 238 implementers should have chosen for the result
of dividing two ints? If float is not acceptable, and int is not
acceptable (which was the whole point of the PEP), then the only
alternative I can see would have been to raise a TypeError and force
the user to upcast explicitly. In that case, dividing arbitrary ints
using floating-point math would not be possible for those ints that
are outside the range of floats; you would get OverflowError on the
upcast operation, regardless of whether the result of division would
be within the range of a float.


More importantly, it's useful for implementers of generic mathematical
routines. If you're passed arbitrary inputs, you don't have to check
the types of the values you were given and then branch if both of the
values you were about to divide happened to be ints just because the
division operator arbitrarily does something different on ints.

Or you just cast one of them to float. That way you're sure you're
working with floats.

The main trouble is that float is not a perfect superset of int. If it
were, then it really would be upcasting, same as turning a float into
a complex is; there's no downside, other than performance.

If I'd been in charge, I would have simply let int/int continue to
return an int, as that's the one thing that is guaranteed not to
behave differently on different input values. Python 3 fixed Unicode
handling by ensuring that mixing text and bytes would cause problems
straight away, rather than waiting until you get a character with a
codepoint higher than U+00FF; 3.3 went further and made sure you
wouldn't get problems by going past U+FFFF even on Windows. I think we
all agree (well, all bar the trolls) that that was a good thing. So
why do we have this sort of thing go weird?

def always_true(x):
assert type(x) is int
return x*10/2 == x*5

In Python 2, I believe that will indeed be always true, for any
integer x. (Yeah, there's a naughty type check in there. I'm talking
about integers, mmkay?) In Python 3, it might not be.
False

(32-bit Windows, because I'm on the laptop. Other Pythons, other CPUs,
etc, may have different points where that happens, but the same will
happen.)

So either you keep a very close eye on everything to make sure you
don't have floats infecting your calculations, or you ignore the
problem and then start seeing odd stuff happen with specific numbers.
I'd rather have to explicitly request floating-point division; that
way, you get issues a lot sooner and more simply. "Why is 34/10 equal
to 3?" is a lot easier to explain than "Why does my program not work
when I give it numbers with lots of data encoded in them, when it
works fine with sequential numbers from zero?". (Imagine if you work
with invoice numbers, for instance, and your code is fine; but if you
encode the date into the first eight digits, then put the store number
in the next three, register number in the next three, and then the
last three are sequential. Should work the same, right?)

Anyway, way too late to change now. That ship sailed in 2.2 or thereabouts.

ChrisA
 
I

Ian Kelly

Or you just cast one of them to float. That way you're sure you're
working with floats.

Which is inappropriate if the type passed in was a Decimal or a complex.
 
C

Chris Angelico

Which is inappropriate if the type passed in was a Decimal or a complex.

In that case, you already have a special case in your code, so whether
that special case is handled by the language or by your code makes
little difference. Is your function so generic that it has to be able
to handle float, Decimal, or complex, and not care about the
difference, and yet has to ensure that int divided by int doesn't
yield int? Then say so; put in that special check. Personally, I've
yet to meet any non-toy example of a function that needs that exact
handling; most code doesn't ever think about complex numbers, and a
lot of things look for one specific type:
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
"asdf"*3.0
TypeError: can't multiply sequence by non-int of type 'float'

Maybe it's not your code that should be caring about what happens when
you divide two integers, but the calling code. If you're asking for
the average of a list of numbers, and they're all integers, and the
avg() function truncates to integer, then the solution is to use sum()
and explicitly cast to floating point before dividing. Why should the
language handle that? It's no different from trying to sum a bunch of
different numeric types:
sum([1.0,decimal.Decimal("1")])
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
sum([1.0,decimal.Decimal("1")])
TypeError: unsupported operand type(s) for +: 'float' and 'decimal.Decimal'

The language doesn't specify a means of resolving the conflict between
float and Decimal, but for some reason the division of two integers is
blessed with a language feature. Again, it would make perfect sense if
float were a perfect superset of int, so that you could simply declare
that 1.0 and 1 behave absolutely identically in all arithmetic (they
already hash and compare equally), but that's not the case, so I don't
see that division should try to pretend they are.

ChrisA
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top