@staticmethod with @property

Paul Tarjan picture Paul Tarjan · Nov 8, 2009 · Viewed 34.6k times · Source

I want

Stats.singleton.twitter_count += 1

and I thought I could do

class Stats:
    singleton_object = None

    @property
    @staticmethod
    def singleton():
        if Stats.singleton_object:
            return Stats.singleton_object
        Stats.singleton_object = Stats()
        return Stats.singleton()

But it throws an exception:

>>> Stats.singleton.a = "b"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'property' object has only read-only attributes (assign to .a)

Answer

kylealanhale picture kylealanhale · Oct 23, 2011

User kaizer.se was onto something as far as the original question goes. I took it a step further in terms of simplicity, so that it now requires only a single decorator:

class classproperty(property):
    def __get__(self, cls, owner):
        return classmethod(self.fget).__get__(None, owner)()

Usage:

class Stats:
    _current_instance = None

    @classproperty
    def singleton(cls):
        if cls._current_instance is None:
            cls._current_instance = Stats()
        return cls._current_instance

As noted, this way of creating a singleton is not a good design pattern; if that must be done, a metaclass factory is a much better way to do it. I was just excited about the prospect of a class property though, so, there it is.