Python dot-equals (syntax proposal)

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun May 2 06:08:55 EDT 2010


On Sun, 02 May 2010 04:04:11 -0400, Terry Reedy wrote:

> On 5/2/2010 1:05 AM, Alf P. Steinbach wrote:
>> On 02.05.2010 06:06, * Aahz:
> 
>>> and sometimes
>>> they rebind the original target to the same object.
>>
>> At the Python level that seems to be an undetectable null-operation.
> 
> If you try t=(1,2,3); t[1]+=3, if very much matters that a rebind
> occurs.
> 
>> Granted one could see something going on in a machine code or byte code
>> debugger. But making that distinction (doing nothing versus
>> self-assignment) at the Python level seems, to me, to be meaningless.
> 
> Please do not confuse things. Augmented *assignment* must be understood
> as assignment. Failure to do so leads (and has lead) newbies into
> confusion, and puzzled posts on this list.

I think that if you think *only* about Python's standard namespaces, self-
assignment is more or less a no-op. I can't think of any way that x = x 
could do anything other than use CPU cycles, *if* you limit yourself to 
the standard global or function local namespaces.

But if you think about custom namespace types, and item assignment (e.g. 
the example you gave with a tuple), the situation becomes different. 
Here's a nice example, using Python 3.1:

>>> class B(A):  # class A defined elsewhere -- see below.
...     x = 1
...     x = x
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in B
  File "<stdin>", line 4, in __setitem__
TypeError: can't rebind constants

Thus proving that self-assignment is not necessarily a no-op. How did I 
make that work? It takes a custom dict and a bit of metaclass magic:


class ConstantNamespace(dict):
    def __setitem__(self, key, value):
        if key in self:
            raise TypeError("can't rebind constants")
        super(ConstantNamespace, self).__setitem__(key, value)

class WriteOnceClass(type):
    @classmethod
    def __prepare__(metacls, name, bases):
        return ConstantNamespace()
    def __new__(cls, name, bases, classdict):
        return type.__new__(cls, name, bases, classdict)

class A(metaclass=WriteOnceClass):
    pass



-- 
Steven



More information about the Python-list mailing list