[Python-ideas] If branch merging

Steven D'Aprano steve at pearwood.info
Mon Jun 8 14:12:28 CEST 2015


On Mon, Jun 08, 2015 at 04:24:33AM -0700, Andrew Barnert via Python-ideas wrote:
[...]
> > For if/elif clauses and while loops, the leaking would be a desired
> > feature in order to make the subexpression available for use inside
> > the following suite body.
> 
> Except it would also make the subexpression available for use _after_ 
> the suite body. And it would give you a way to accidentally replace 
> rather than shadow a variable from earlier in the function. So it 
> really is just as bad as any other assignment or other mutation inside 
> a condition.

I don't know why you think this will be a bad thing. Or rather, even if 
it is a bad thing, it's the Python Way. Apart from classes and functions 
themselves, indented blocks are *not* new scopes as they may be in some 
other languages. They are part of the existing scope, and the issues you 
raise above are already true today:

    x = 1
    if some_condition():
        x = 2  # replaces, rather than shadow, the earlier x
        y = 3  # y may be available for use after the suite body

So I don't see the following as any more of a problem:

    x = 1
    if (some_condition() as x) or (another_condition() as y):
        ...
    # x is replaced, and y is available


The solution to replacing a variable is, use another name. And if you 
really care about y escaping from the if-block, just use del y at the 
end of the block. (I can't imagine why anyone would bother.)


[...]
> > The other possibility that comes to mind is to ask the question: "What
> > happens when a named subexpression appears as part of an argument list
> > to a function call, or as part of a subscript operation, or as part of
> > a container display?", as in:
> > 
> >    x = func(b if (a.b as b) else a.c)
> >    x = y[b if (a.b as b) else a.c]
> >    x = (b if (a.b as b) else a.c),
> >    x = [b if (a.b as b) else a.c]
> >    x = {b if (a.b as b) else a.c}
> >    x = {'k': b if (a.b as b) else a.c}
> > 
> > Having *those* subexpressions leak seems highly questionable,

I agree with that in regard to the function call. It just feels wrong 
and icky for a binding to occur inside a function call like that. But 
I don't think I agree with respect to the rest. To answer Andrew's later 
question:

> What does "x[(a.b as b)] = b" mean

surely it simply means the same as:

    b = a.b
    x[b] = b

Now we could apply the same logic to a function call:

    # func(a.b as b)
    b = a.b
    func(b)

but I think the reason this feels wrong for function calls is that it 
looks like the "as b" binding should be inside the function's scope 
rather than in the caller's scope. (At least that's what it looks like 
to me.) But that doesn't apply to the others. (At least for me.)

But frankly, I think I would prefer to have b escape from the function 
call than to have to deal with a bunch of obscure, complicated and 
unintuitive "as" scoping rules. Simplicity and predictability counts for 
a lot.


-- 
Steve


More information about the Python-ideas mailing list