Scope rule pecularities

Antoon Pardon apardon at forel.vub.ac.be
Thu May 13 10:32:45 EDT 2004


Op 2004-05-13, Andrew Bennetts schreef <andrew-pythonlist at puzzling.org>:
> On Thu, May 13, 2004 at 11:26:28AM +0000, Antoon Pardon wrote:
>> Op 2004-05-13, Andrew Bennetts schreef <andrew-pythonlist at puzzling.org>:

>> > Augmented assignments are still assignments, and that makes perfect sense to
>> > me -- each of those behave exactly like their obvious longer versions:
>> >
>> >     s = 'abc'
>> >     s = s + 'd'
>> >
>> >     i = 7
>> >     i = i + 3
>> >
>> >     l = [1, 2, 3]
>> >     l = l + [4, 5, 6]
>> >
>> > (Yes, there are tricky examples that do behave differently -- but I try to
>> > avoid tricky things, because they tend to be hard to read.  I almost only
>> > find I want to use augmented assignment on integers and occasionally
>> > strings.)
>> 
>> But these things are only hard to read (to you, I don't find it so) because
>> you are using constants in the expression.
>
> I didn't say those examples are hard to read.  Personally, I find both
> forms equally readable.
>
> I did say that there are cases where:
>
>     <lvalue> += x
>
> does not behave the same way as:
>
>     <lvalue> = <lvalue> + x
>
> But you need relatively tricky lvalues for this to be the case.
>
>> a += b, is just as hard to read whether a and b are lists or integers.
>> 
>> The problem is that because the behaviour with strings and lists is
>> different I can't write a program in which the behaviour of += is
>> consistent for all classes because there will always be core classes
>> for which the behaviour will be different.
>
> It seems to be that your problem isn't really with "+=" as such, it's that
> Python has immutable types at all, including in the commonly used builtins.
> Immutability of strings, numbers and tuples has worked very well for Python
> so far, so you'll have a struggle convincing many people that it should be
> otherwise.

Well I didn't have this problem when I first encounterd python. It
had no "+=" operators then. But with the introduction of these
and the inconsistencies it introduces I have began to think
differently.  You are probably right that people will be
hard to convince to change this, so I wont try. I'll just
use the language that suits me best for a particular task
and often enough it will be python, with the warts I think
it has.

>
> Personally, I like that when I do:
>
>     x = 7
>     func(x)
>
> That I know that x will still be 7 after func returns, regardless of what
> happens inside func.  It's just not possible for func to accidentally change
> the value of x in my scope, because I know that numbers are immutable in
> Python.

Well personally I like it to be that way for any object, unless func
has somehow announced that it can change the argument. I think a
copy in parameter is a far better way to assure you of that, because
it indeed works for any object, or maybe a seperate attribute that
allows any object to be mutable or immutable depending on the
needs of the moment.

> It would take some *massive* benefits to convince me to change my mind.
>
>> It is a bit like having some classes use "+" for substraction. In it self
>> that wouldn't be so bad, you just have to pay attention. But then
>> you want to write a class that will work with whatever number type
>> and it needs to do additions. Now suddenly things get difficult because
>> a + b doesn't behave consistently among the different number types. 
>
> Again, if the objects you're using don't "make sense", you're stuck with a
> difficult life.  If a library's API is hard to use, then chances are the
> library won't get used much.

Well that is my point, "+=" operators don't make sense for
immutable types.

>> You have the same kind of difficulty now if you want to write a
>> class/function/module that works with any kind of sequence.
>> 
>> Using the "+=" operator you can't guarantee any kind of consistency.
>> If I had code like this:
>> 
>>   a = b
>>   b += c
>> 
>> I would have no idea at all whether a was changed or not. So
>> writing code that can work with any sequence becomes a possible
>> problem spot if you use these kind of operators.
>
> Then take a copy of the sequence first, using list(seq) or tuple(seq), and
> then you'll know exactly what you have.

I consider that a work around.

> Or even simpler -- use: "b = b + c"
> instead.  Then you know that a is unmodified.

Right. In order to write reliable code in a function, class or module
that can work with any sequence I better not write "b += c" but
write "b = b + c" because only the latter guarantees a particual result.
So how good are those "+=" operators if you can't use them in generic
code.

I don't find it convincing that it is convenient to be able to
write "a += b" if you then learn that in generic code you better
write "a = a + b" anyway.

> If you don't know what kind of objects your functions are working with, how
> can you expect them to behave correctly?

I know what kind of objects: sequences. It is not my fault the operators
on sequence are not consistent.

> If your API assumes that a
> particular method receives a tuple, then either make sure it does by calling
> tuple(x), or document that it does in the docstring.
>
> Otherwise, a user of your library code might legitimately try to pass a
> list, a dictionary, None, or perhaps their own custom type, unaware of your
> hidden assumptions.

But I want my code to work with any sequence type, the problem is that
the core library doesn't provide a consistent behaviour for all its
sequence types. That is not my fault.

> In my experience, I've never had the issue of mutable vs. immutable sequence
> types cause the sort of problems you're worried about.  Perhaps I'm lucky,
> or subconciously careful, or it has happened and I'm just plain forgetful :)
> ... Regardless, I'm not going to start worrying about it now.  Python is
> working just fine for me despite this.

Well that doesn't surprise me much, since the += operators are
relatively new and it is the introduction of those that can
cause such problems. Yes there are workaround such as taking
a copy with tuple or list, Just as you can embed a variable
in an object if you want to change something on an intermediate
scope. I consider the needs of such workarounds as signs that
the language would better be changed in these parts. It is
not that big a deal that it will have a big influence on the
language I'll use, but I still think of these kind of things
as warts.

-- 
Antoon Pardon



More information about the Python-list mailing list