[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