Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@staticmethod with @property

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) 
like image 755
Paul Tarjan Avatar asked Nov 08 '09 18:11

Paul Tarjan


People also ask

Does @staticmethod do anything?

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.

What is the difference between @staticmethod and Classmethod?

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 does @staticmethod means in Python?

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.

When should Staticmethod be used?

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.


2 Answers

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.

like image 197
kylealanhale Avatar answered Sep 22 '22 23:09

kylealanhale


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 
like image 21
Jacky1205 Avatar answered Sep 21 '22 23:09

Jacky1205