[Tutor] @property vs @classmethod

Cameron Simpson cs at zip.com.au
Sat Jul 8 20:19:36 EDT 2017


On 08Jul2017 16:03, Evuraan <evuraan at gmail.com> wrote:
>I was hoping to learn when to use classmethod and when to use property.
>They both seem similar (to me at least..), what's the pythonic way to
>choose between them?

The core distinction is the context that the function needs. Does it depend on 
the particular instance? Or just on the instance's class?

A property is handed the instance as its first argument ("self"), like normal 
methods. It just looks like an attribute from the outside.

  class C:
    @property
    def size(self):
      return len(self.something)

  O = C()
  print("size of O is", O.size)     # no brackets

I tend to use these for "basic" attributes of an object for which a traditional 
"get_size()" method is annoying verbiage and which are cheap to compute, as if 
they were an ordinary attribute.

A classmethod is handed the class, not the instance. (So your "self" in the 
classmethod you wrote is misleading; we normally spell that "klass" or 
something like that). It is for things that do not depend on the instance, but 
do depend on the class (for example they access class attributes).

  class Base:
    TYPE = 0
    ...

  class C(Base):
    TYPE = 1
    @classmethod
    def get_type(klass):
      return klass.TYPE

And a staticmethod is not handed any default argument. It is for methods that 
are like ordinary function, with no class or instance context to their 
behaviour. A typical use might be a factory function, which is like an 
alternate constructor.

  class C:
    def __init__(self, number):
      self.number = number
    @staticmethod
    def from_word(word):
      if word == "one":
        n = 1
      elif word == "two":
        n = 2
      else:
        raise ValueError("unsupported number name: %r" % (word,))
      return C(n)

  O1 = C(3)
  O2 = C.from_word("two")

Here the staticmethod is put in the class (instead of outside) for that is 
nicely associated with the class for readability etc.

Your test code doesn't really show these differences. Try modifying each method 
to print(repr(self)) as the first thing; you should see that for a normal 
method and a property "self" is the instance, for the classmethod it is the 
class, and that it isn't supplied at all for a staticmethod.

Cheers,
Cameron Simpson <cs at zip.com.au>


More information about the Tutor mailing list