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