[Tutor] set locals
eryksun
eryksun at gmail.com
Thu Dec 19 07:48:52 CET 2013
On Wed, Dec 18, 2013 at 6:16 AM, spir <denis.spir at gmail.com> wrote:
> On 12/18/2013 12:07 PM, eryksun wrote:
>>
>> You need __setattr__ from the metaclass:
>>
>> >>> class C: pass
>> ...
>> >>> type(C).__setattr__(C, "baz", "BAZ")
>> >>> C.baz
>> 'BAZ'
>
> Oh, that makes sense: so, __setattr__ on a class is for its instances,
> right? (thus, to set attrs on a class itself, we need ___setattr__ from its
> own class, if I understand rightly?)
Note that vars(type)['__dict__'] is a data descriptor, so the lookup
gives it precedence. There actually is a vars(C)['__dict__'], the
descriptor meant for instances of C, but the lookup stops before it
gets there. On the other hand, vars(type)['__setattr__'] is a non-data
descriptor (i.e. no __set__ method), so the lookup for C.__setattr__
skips it to bind and return vars(object)['__setattr__'] instead.
That's akin to shadowing a method with instance data. For example:
>>> c = C()
>>> c.__setattr__ = 'spam'
>>> vars(c)
{'__setattr__': 'spam'}
>>> c.__setattr__
'spam'
Here are 2 reasons why object.__setattr__ is wrong for a CPython type object:
type.__setattr__ includes a check to prevent setting
and deleting attributes of built-in types.
type.__setattr__ updates the affected slot (C struct
field) in the type and its subclasses. This also
invalidates the method cache for the affected types.
For example, if you just modify a type's dict entry for '__len__',
this doesn't update the sq_length and mp_length slots in the
PyHeapTypeObject, so built-in len() called on an instance will raise a
TypeError. Hence also the reason that modifying the dict directly is
disallowed by the __dict__ proxy.
More information about the Tutor
mailing list