Difference between staticmethod and classmethod

后端 未结 28 2139
一整个雨季
一整个雨季 2020-11-21 06:11

What is the difference between a function decorated with @staticmethod and one decorated with @classmethod?

相关标签:
28条回答
  • 2020-11-21 06:39

    Static Methods:

    • Simple functions with no self argument.
    • Work on class attributes; not on instance attributes.
    • Can be called through both class and instance.
    • The built-in function staticmethod()is used to create them.

    Benefits of Static Methods:

    • It localizes the function name in the classscope
    • It moves the function code closer to where it is used
    • More convenient to import versus module-level functions since each method does not have to be specially imported

      @staticmethod
      def some_static_method(*args, **kwds):
          pass
      

    Class Methods:

    • Functions that have first argument as classname.
    • Can be called through both class and instance.
    • These are created with classmethod in-built function.

       @classmethod
       def some_class_method(cls, *args, **kwds):
           pass
      
    0 讨论(0)
  • 2020-11-21 06:40

    A staticmethod is a method that knows nothing about the class or instance it was called on. It just gets the arguments that were passed, no implicit first argument. It is basically useless in Python -- you can just use a module function instead of a staticmethod.

    A classmethod, on the other hand, is a method that gets passed the class it was called on, or the class of the instance it was called on, as first argument. This is useful when you want the method to be a factory for the class: since it gets the actual class it was called on as first argument, you can always instantiate the right class, even when subclasses are involved. Observe for instance how dict.fromkeys(), a classmethod, returns an instance of the subclass when called on a subclass:

    >>> class DictSubclass(dict):
    ...     def __repr__(self):
    ...         return "DictSubclass"
    ... 
    >>> dict.fromkeys("abc")
    {'a': None, 'c': None, 'b': None}
    >>> DictSubclass.fromkeys("abc")
    DictSubclass
    >>> 
    
    0 讨论(0)
  • 2020-11-21 06:40

    Only the first argument differs:

    • normal method: the current object if automatically passed as an (additional) first argument
    • classmethod: the class of the current object is automatically passed as an (additional) fist argument
    • staticmethod: no extra arguments are automatically passed. What you passed to the function is what you get.

    In more detail...

    normal method

    When an object's method is called, it is automatically given an extra argument self as its first argument. That is, method

    def f(self, x, y)
    

    must be called with 2 arguments. self is automatically passed, and it is the object itself.

    class method

    When the method is decorated

    @classmethod
    def f(cls, x, y)
    

    the automatically provided argument is not self, but the class of self.

    static method

    When the method is decorated

    @staticmethod
    def f(x, y)
    

    the method is not given any automatic argument at all. It is only given the parameters that it is called with.

    usages

    • classmethod is mostly used for alternative constructors.
    • staticmethod does not use the state of the object. It could be a function external to a class. It only put inside the class for grouping functions with similar functionality (for example, like Java's Math class static methods)
    class Point
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
        @classmethod
        def frompolar(cls, radius, angle):
            """The `cls` argument is the `Point` class itself"""
            return cls(radius * cos(angle), radius * sin(angle))
    
        @staticmethod
        def angle(x, y):
            """this could be outside the class, but we put it here 
    just because we think it is logically related to the class."""
            return atan(y, x)
    
    
    p1 = Point(3, 2)
    p2 = Point.frompolar(3, pi/4)
    
    angle = Point.angle(3, 2)
    
    
    0 讨论(0)
  • 2020-11-21 06:41

    @decorators were added in python 2.4 If you're using python < 2.4 you can use the classmethod() and staticmethod() function.

    For example, if you want to create a factory method (A function returning an instance of a different implementation of a class depending on what argument it gets) you can do something like:

    class Cluster(object):
    
        def _is_cluster_for(cls, name):
            """
            see if this class is the cluster with this name
            this is a classmethod
            """ 
            return cls.__name__ == name
        _is_cluster_for = classmethod(_is_cluster_for)
    
        #static method
        def getCluster(name):
            """
            static factory method, should be in Cluster class
            returns a cluster object for the given name
            """
            for cls in Cluster.__subclasses__():
                if cls._is_cluster_for(name):
                    return cls()
        getCluster = staticmethod(getCluster)
    

    Also observe that this is a good example for using a classmethod and a static method, The static method clearly belongs to the class, since it uses the class Cluster internally. The classmethod only needs information about the class, and no instance of the object.

    Another benefit of making the _is_cluster_for method a classmethod is so a subclass can decide to change it's implementation, maybe because it is pretty generic and can handle more than one type of cluster, so just checking the name of the class would not be enough.

    0 讨论(0)
  • 2020-11-21 06:41

    A class method receives the class as implicit first argument, just like an instance method receives the instance. It is a method which is bound to the class and not the object of the class.It has access to the state of the class as it takes a class parameter that points to the class and not the object instance. It can modify a class state that would apply across all the instances of the class. For example it can modify a class variable that will be applicable to all the instances.

    On the other hand, a static method does not receive an implicit first argument, compared to class methods or instance methods. And can’t access or modify class state. It only belongs to the class because from design point of view that is the correct way. But in terms of functionality is not bound, at runtime, to the class.

    as a guideline, use static methods as utilities, use class methods for example as factory . Or maybe to define a singleton. And use instance methods to model the state and behavior of instances.

    Hope I was clear !

    0 讨论(0)
  • 2020-11-21 06:42

    I will try to explain the basic difference using an example.

    class A(object):
        x = 0
    
        def say_hi(self):
            pass
    
        @staticmethod
        def say_hi_static():
            pass
    
        @classmethod
        def say_hi_class(cls):
            pass
    
        def run_self(self):
            self.x += 1
            print self.x # outputs 1
            self.say_hi()
            self.say_hi_static()
            self.say_hi_class()
    
        @staticmethod
        def run_static():
            print A.x  # outputs 0
            # A.say_hi() #  wrong
            A.say_hi_static()
            A.say_hi_class()
    
        @classmethod
        def run_class(cls):
            print cls.x # outputs 0
            # cls.say_hi() #  wrong
            cls.say_hi_static()
            cls.say_hi_class()
    

    1 - we can directly call static and classmethods without initializing

    # A.run_self() #  wrong
    A.run_static()
    A.run_class()
    

    2- Static method cannot call self method but can call other static and classmethod

    3- Static method belong to class and will not use object at all.

    4- Class method are not bound to an object but to a class.

    0 讨论(0)
提交回复
热议问题