@staticmethod with @property @staticmethod with @property python python

@staticmethod with @property


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.


Following up with what KyleAlanHale wrote:

His example works great, until you try and do:

Stats.singleton = 5

This won't give you an error, it will overwrite the function, so that when you type next

single = Stats.singletonprint single

You'll get

5

I think you're best off using Kyle's answer without the @classproperties decoration.


I guess giving a Python code snippet to show how do property and staticmethod work would be helpful.

Both of them are descriptors which implements __get__ or __set__

property is a data descriptor

class Property(object):    "Emulate PyProperty_Type() in Objects/descrobject.c"    def __init__(self, fget=None, fset=None, fdel=None, doc=None):        self.fget = fget        self.fset = fset        self.fdel = fdel        if doc is None and fget is not None:            doc = fget.__doc__        self.__doc__ = doc    def __get__(self, obj, objtype=None):        if obj is None:            return self        if self.fget is None:            raise AttributeError("unreadable attribute")        return self.fget(obj)    def __set__(self, obj, value):        if self.fset is None:            raise AttributeError("can't set attribute")        self.fset(obj, value)    def __delete__(self, obj):        if self.fdel is None:            raise AttributeError("can't delete attribute")        self.fdel(obj)    def getter(self, fget):        return type(self)(fget, self.fset, self.fdel, self.__doc__)    def setter(self, fset):        return type(self)(self.fget, fset, self.fdel, self.__doc__)    def deleter(self, fdel):        return type(self)(self.fget, self.fset, fdel, self.__doc__)

And staticmethod is a non-data descriptor

class StaticMethod(object):    "Emulate PyStaticMethod_Type() in Objects/funcobject.c"    def __init__(self, f):        self.f = f    def __get__(self, obj, objtype=None):        return self.f