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)
The @staticmethod is a built-in decorator that defines a static method in the class in Python. A static method doesn't receive any reference argument whether it is called by an instance of a class or by the class itself.
Class method can access and modify the class state. Static Method cannot access or modify the class state. The class method takes the class as parameter to know about the state of that class. Static methods do not know about class state.
What is a static method? Static methods, much like class methods, are methods that are bound to a class rather than its object. They do not require a class instance creation. So, they are not dependent on the state of the object.
staticmethods can be used when the code that belongs to a class doesn't use the object itself at all. Python doesn't have to instantiate a bound method for each object we instantiate. Bound methods are objects too, and creating them has a cost. Having a static method avoids that.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With