On Wed, Apr 19, 2017 at 10:19 AM, Peter Otten <__pete...@web.de> wrote: > Steven D'Aprano wrote: > >> As I said, I haven't had a chance to try Peter's code, so it's possible >> that he's solved all these problems. I'm judging by previous > > No, my simple code only "works" for read-only properties and only as long as > you don't overwrite the property by assigning to the attribute. To disallow > writing you can define a > > def __set__(*args): > raise AttributeError > > method, but that would only be invoked for instances of the class, not the > class itself. For the same reason the setter of a read/write class property > following that design would only be invoked in an instance, not in the > class. > > The other simple solution, defining a normal property in the metaclass, > works for the class (as expected, remember that the class is an instance of > the metaclass), but is invisible to the instance: > >>>> class T(type): > ... @property > ... def foo(self): return 42 > ... >>>> class Foo: > ... __metaclass__ = T > ... >>>> Foo.foo > 42 >>>> Foo.foo = "bar" > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > AttributeError: can't set attribute >>>> Foo().foo > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > AttributeError: 'Foo' object has no attribute 'foo'
This is a bit awkward, but you can take advantage of property() being a data descriptor. When the attribute is looked up on the class, the metaclass __getattribute__ or __setattr__ first searches the metaclass MRO. If it finds a data descriptor, then it uses it unconditionally. This means you can add a foo property to the class as well and have it chain to the metaclass property. For example: class T(type): @property def foo(self): return 42 class C(object): __metaclass__ = T @property def foo(self): return type(self).foo >>> C.foo 42 >>> C.foo = 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can't set attribute >>> o = C() >>> o.foo 42 >>> o.foo = 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can't set attribute _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor