Scope rule pecularities

Josiah Carlson jcarlson at uci.edu
Wed May 19 15:54:38 EDT 2004


>>Well then, that is easy, += does whatever the object says it should do. 
>>   The only builtin type that is actually modified in place (via +=) are 
>>lists.  Everything else uses single name rebinding.  Is that a simple 
>>enough rule, because had you done /any/ sort of critical investigation, 
>>you would have discovered it yourself.  Your investigation would have 
>>turned up that immutables behave as they should, and a list's __iadd__ 
>>method is an alias for its extend method.
> 
> Well I think that if you need such a critical investigation, something
> is wrong. I could just as well write a vector and matrix module that
> uses "-" for addition and if people then complain tell them that they
> should have done a critical investigation, then they would have found
> out that the "-" works as it should.

In this case, you were talking about builtin Python datatypes. 
Considering there are a limited number of them (import 
types;dir(types)), 5 minutes of checking for yourself would have done 
the job.


>>And automatically rebinding /every/ name that references an object is 
>>more explicit?  I don't think so.
> 
> I didn't say that. I just want to point out that python does enough
> things implicitly so that the "explicit is better than implicit"
> argument is invalid.

Everything in Python is passed by reference.  This makes passing any 
kind of value quick and easy.  However, how those references are handled 
differs depending on the object.  What seems to be happening is that we 
are arguing over what is the best way to handle those references, after 
we know that they are references.

As you mentioned later, in C, you can use *a = 1 to modify a single 
instance of 'a'.  However, immutables in Python never do the *a = 1 
assignment.  Mutables do so, which is why the final line of...
   m = n = []
   m.append(7)
   m == n
...is true.

For immutables, on modification, a new instance of the immutable is 
created, the value being set accordingly.


 > IMO python being the language that it is with immutable objects, the
 > only consistant solution would have been to just translate a += b
 > into something equivalent to a = a + b and leave it at that.
 > No __ixxx__ methods, no inplace modifications.


Now, whether or not list.__iadd__ should do the rough equivalent of 
list.extend with a return, I would lean towards yes.  += implies an 
object modification, where object modifications make sense.  In the case 
of lists, it does make sense, because they are mutable.  For immutables, 
it doesn't make sense, because the objects themselves are immutable.

Now that we've gotten to the point, __iadd__ and friends, we know we 
disagree.  If you feel terribly strongly about it, post a bug report or 
feature requrest to SF.  I would venture a guess that within a week it 
will be closed with a message stating, "yeah, we like it the way it is".


>>Hmmm, dictionaries.  Dictionaries are hash tables that contain a key and 
>>value pair.  In order to handle dynamic expansion of the hash table, we 
>>must keep the key (Python keeps a pointer to the key, it is much faster 
>>that way).
> 
> I doubt it is much faster overall. The faster dictionary expansion
> is at the expense of having to turn your mutable objects you
> want to use as a key into an immutable equivallent.

Except Python doesn't allow mutables as keys!  Go ahead, try using a 
mutable builtin Python datatype as a key.  Notice how it doesn't work? 
Yeah, that's because Python doesn't do it.  One reason, as you mention, 
is that the only practical thing to do when given a mutable is to 
translate it (somehow) into an immutable object.  Such a translation 
would need to occur any time you wanted to use a mutable as a key, which 
is one reason why Python doesn't allow such things.


>>Right now, only immutables are able to be keys.  Why is this 
>>so?  Let us imagine that we use a mutable string as a key in a 
>>dictionary.  Everything is fine and dandy, until we modify the string. 
>>At that point, in order for the dictionary to stay consistant, we must 
>>make a copy of that string to keep it as a key.  No big deal, right? 
>>Wrong.  What if that string were 500k?  500M?  It becomes a big deal.
> 
> It already is a big deal. Because you can't mutate strings, that means
> that every time you need a minor change to one a lot of copying will
> go on instead of inplace modifications.
> 
> Each time you need to do something like name = name[:-3] + newsuffix
> you make a copy, with strings that are 500k or 500M that is just
> as big an issue.
 >
> So either you work with mutable values and then you need to copy
> them into an immutable before they can be used as a key or you
> work with immutables and then all manipulations you do on them
> will involve copying. So Python uses immutables as key because
> that is faster, is irrelevant to me because it is just a deviation
> of the cost, not a reduction within the whole program.

People who mutate large strings repeatedly, and know what the hell they 
are doing, tend to use either the array or cStringIO module.  For 
repeated string manipulations, they tend to be quite fast (a few 
encryption algorithms in Python use array).


> And besides you can have muttable objects within immutables.

Python already covers this case.  Immutable objects (that are 
containers) recursively hash their contents.

 >>> d = {}
 >>> d[([],)] = 1
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
TypeError: list objects are unhashable


>>No, Guido is not above criticism.  The mistakes he believes he has made 
>>will be fixed in the 3.0 release.  If you can't wait for it, then 
>>perhaps you should write the interpreter/compiler for the language you 
>>want to use.  It seems to be in vogue these days.
> 
> I sometimes dream about that, but I fear I don't have the time
> nor the motivation to finish such a project properly. I'll
> just make a choice among the languages that are available.
> In general I like python, the warts sometimes frustrate me,
> but I see that as a token of affection, e.g. I don't care
> about the warts of C++, because I find it so ugly and
> complicated I avoid using it. So I'll wait what 3.0
> has is store and see what I like about it.

Don't hold your breath, 3.0 (by the sounds of it) is roughly 6+ years 
off.  Once you get used to the "warts", I think you'll find they 
dissappear in Python quite quickly.

  - Josiah



More information about the Python-list mailing list