The following doesn't work for some reason:
>>> class foo(object):
... @property
... @classmethod
... def bar(cls):
... return "asdf"
...
>>> foo.bar
<property object at 0x1da8d0>
>>> foo.bar + '\n'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'property' and 'str'
Is there a way to do this, or is my only alternative to resort to some kind of metaclass trickery?
If you want the descriptor property
to trigger when you get an attribute from object X, then you must put the descriptor in type(X)
. So if X is a class, the descriptor must go in the class's type, also known as the class's metaclass -- no "trickery" involved, it's just a matter of completely general rules.
Alternatively, you might write your own special-purpose descriptor. See here for an excellent "how-to" treaty on descriptors. Edit for example:
class classprop(object):
def __init__(self, f):
self.f = classmethod(f)
def __get__(self, *a):
return self.f.__get__(*a)()
class buh(object):
@classprop
def bah(cls): return 23
print buh.bah
emits 23
, as desired.