@property; @classmethod; def f()

  • Thread starter K. Richard Pixley
  • Start date
K

K. Richard Pixley

Can anyone explain to me why this doesn't work?

class Foo(object):
@property
@classmethod
def f(cls):
return 4

I mean, I think it seems to be syntactically clear what I'm trying to
accomplish. What am I missing?

--rich
 
I

Ian Kelly

Can anyone explain to me why this doesn't work?

class Foo(object):
@property
@classmethod
def f(cls):
return 4

I mean, I think it seems to be syntactically clear what I'm trying to
accomplish. What am I missing?

First, because classmethod returns a classmethod instance, not a
function, so what gets passed to property is the classmethod descriptor,
not an actual callable.

Second, because a property descriptor just returns itself when accessed
on the class. It only works on instances.

To do what you want, I think you would need to write your own descriptor
class. Something like this:

class classproperty(object):

def __init__(self, getter):
self._getter = getter

def __get__(self, instance, owner):
return self._getter(owner)

class Foo(object):
@classproperty
def f(cls):
return 4

Modify as needed if you want to accomodate setters and deleters as well.

Cheers,
Ian
 
S

Steven D'Aprano

Can anyone explain to me why this doesn't work?

class Foo(object):
@property
@classmethod
def f(cls):
return 4

What does "doesn't work" mean? It works for me:

.... @property
.... @classmethod
.... def f(cls):
.... return 4
....
There is no syntax error, the class is created, it works fine. What were
you expecting to happen?


If you instantiate the class and try accessing the property, you get the
expected runtime error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'classmethod' object is not callable

(Admittedly, *you* might not have expected it, but nevertheless...)

property() expects a callable object, not a classmethod object, so
naturally it fails. Admittedly, it's a little unexpected that
classmethods aren't callable, but they're not:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'classmethod' object is not callable


Don't confuse the classmethod object with a class method (note the
space!). Class methods are what you get once the descriptor mechanism
kicks into action behind the scenes. classmethod objects are the
descriptors that create class methods (note space) when required:
42


I mean, I think it seems to be syntactically clear what I'm trying to
accomplish. What am I missing?

An understanding of the dark and murky waters of descriptor black magic :)

http://docs.python.org/howto/descriptor.html

(It's not really that dark and murky. It's actually amazingly simple.)

My recommendation is, forget the classmethod. A combination of property
with class attributes and self.__class__ will get you what you want.

Otherwise, just create your own descriptor object. The How To above shows
pure-python versions of classmethod and staticmethod.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,166
Messages
2,570,903
Members
47,446
Latest member
Pycoder

Latest Threads

Top