[Python-Dev] Common subset of python 2 and python 3
Steven D'Aprano
steve at pearwood.info
Wed Jan 15 23:35:48 CET 2014
On Wed, Jan 15, 2014 at 09:25:04AM -0500, Eric V. Smith wrote:
> On 1/15/2014 8:21 AM, Chris Angelico wrote:
> > On Wed, Jan 15, 2014 at 11:22 PM, "Martin v. Löwis" <martin at v.loewis.de> wrote:
> >> I don't think that it is possible to write an interpreter that is fully
> >> compatible for all it accepts. Would you think that the program
> >>
> >> print(repr(2**80).endswith("L"))
> >>
> >> is in the subset that should be supported by both Python 2 and Python 3?
> >
> > Easiest fix for that would be to have long.__repr__ omit the L tag.
> > Then it'll do the same as it would in Py3.
>
> I think Martin's point is not this specific thing, but that such a
> subset would be useless. Would you drop dict.items() because it returns
> different things in both languages? Drop range() because it's different?
> There are many, many such differences. The common subset is not useful.
To expand on this, the common subset is not useful, not well-defined,
and it is not needed.
Not well-defined because neither "Python 2" nor "Python 3" are
well-defined. Most of the code I write supports Python 2.4 onwards, and
there are a lot of features (including syntax!) that exist in 2.7 but
not 2.4. Likewise there are features in 3.3 that aren't in 3.2.
But most importantly, limiting yourself to just the common subset isn't
needed to write polyglot code that works over 2.x and 3.x. For the most
part, a few conditional tests will let you write code that works across
multiple versions. I prefer to check for features than test the version
number:
try:
next
except NameError:
# Python 2.4 or 2.5
def next(obj):
return type(obj).__next__()
sort of thing.
Syntax changes are more difficult to deal with. I deal with the lack of
ternary if operator in 2.4 by just avoiding it. The other day I really,
really wanted to use a with statement, but still be compatible with 2.4.
I started off messing about with exec, but eventually rejected that in
favour of a conditional import: I lifted that one function using a with
statement into a module of its own, then tried importing it. If it
failed, I fell back to a second module which implemented the same thing
using nested try...except blocks. There's a tiny bit of duplicated
code, but less than a dozens lines including a docstring.
Given how easy it usually is to write 2/3 compatible code, I don't think
that limiting myself to a subset that works unchanged in both would be
useful to me. That would be a step backward, like going back to Python
1.5 or 2.0, where the language is still recognisably the same, but it's
missing so many features we take for granted that it's painful to work
with.
--
Steven
More information about the Python-Dev
mailing list