the Gravity of Python 2

Chris Angelico rosuav at gmail.com
Mon Jan 6 20:00:40 EST 2014


On Tue, Jan 7, 2014 at 11:27 AM, Devin Jeanpierre
<jeanpierreda at gmail.com> wrote:
> For example, I imagine that it is kind of _silly_ to have a
> __future__.disable_str_autoencoding on a per-module basis, because
> some modules' functions will fail when they are given the wrong type,
> and some won't -- but in the context of making migration easier, that
> silliness is probably OK.

At what point does the auto-encoding happen, though? If a function
calls another function calls another function, at what point do you
decide that this ought to have become a str?

I suspect there'll be quite a few problems that can't be solved
per-module. The division change is easy, because it just changes the
way code gets compiled (there's still "integer division" and "float
division", it's just that / gets compiled into the latter instead of
the former). With print_function I can imagine there might be some
interactions that are affected, but nothing too major. Deploying
new-style classes exclusively could be minorly problematic, but it'd
probably work (effectively, a future directive stipulates that
everything in this module inherits from object - technically should
work, but might cause code readability confusion). But there are much
subtler issues. Compare this code in Python 2 and Python 3:

def f1():
    return {1:2, 11:22, 111:222}

def f2(d):
    return d.keys()

def f3(k):
    return k.pop()

process_me = f2(f1())
try:
    while True:
        current = f3(process_me)
        # ....
except IndexError:
    pass

Obviously this works in Python 2, and fails in Python 3 (because
keys() returns a view). Now imagine these are four separate modules.
Somewhere along the way, something needs to pass the view through
list() to make it poppable. Or, putting it the other way, somewhere
there needs to be an alert saying that this won't work in Py3. Whose
responsibility is it?

* Is it f1's responsibility to create a different sort of dict that
has a keys() method that returns a view?
* Is it f2's responsibility to notice that it's calling keys() on a
dictionary, and that it should warn that this will change (or switch
to compatibility mode, or raise error, or whatever)? This is where the
error actually is.
* Is it f3's responsibility? This one I'm pretty sure is not so.
* Is it the main routine's job to turn process_me into a list? I don't
think so. There's nothing in that code that indicates that it's using
either a dictionary or a list.

I'd put the job either on f1 or on f2. A __future__ directive could
change the interpretation of the { } literal syntax and have it return
a dictionary with a keys view, but the fix would be better done in f2
- where it's not obvious that it's using a dictionary at all.

I'm not sure that a future directive can really solve this one. Maybe
a command-line argument could, but that doesn't help with the gradual
migration of individual modules.

ChrisA



More information about the Python-list mailing list