On Wed, Dec 18, 2013 at 6:16 AM, spir <denis.s...@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.
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to