Difference between staticmethod and classmethod

后端 未结 28 2138
一整个雨季
一整个雨季 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:31

    Here is a short article on this question

    @staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.

    @classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance. That’s because the first argument for @classmethod function must always be cls (class).

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

    You might want to consider the difference between:

    class A:
        def foo():  # no self parameter, no decorator
            pass
    

    and

    class B:
        @staticmethod
        def foo():  # no self parameter
            pass
    

    This has changed between python2 and python3:

    python2:

    >>> A.foo()
    TypeError
    >>> A().foo()
    TypeError
    >>> B.foo()
    >>> B().foo()
    

    python3:

    >>> A.foo()
    >>> A().foo()
    TypeError
    >>> B.foo()
    >>> B().foo()
    

    So using @staticmethod for methods only called directly from the class has become optional in python3. If you want to call them from both class and instance, you still need to use the @staticmethod decorator.

    The other cases have been well covered by unutbus answer.

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

    Instance Method:

    + Can modify object instance state

    + Can modify class state

    Class Method:

    - Can't modify object instance state

    + Can modify class state

    Static Method:

    - Can't modify object instance state

    - Can't modify class state

    class MyClass:
        ''' 
        Instance method has a mandatory first attribute self which represent the instance itself. 
        Instance method must be called by a instantiated instance.
        '''
        def method(self):
            return 'instance method called', self
        
        '''
        Class method has a mandatory first attribute cls which represent the class itself. 
        Class method can be called by an instance or by the class directly. 
        Its most common using scenario is to define a factory method.
        '''
        @classmethod
        def class_method(cls):
            return 'class method called', cls
        
        '''
        Static method doesn’t have any attributes of instances or the class. 
        It also can be called by an instance or by the class directly. 
        Its most common using scenario is to define some helper or utility functions which are closely relative to the class.
        '''
        @staticmethod
        def static_method():
            return 'static method called'
    
    
    obj = MyClass()
    print(obj.method())
    print(obj.class_method()) # MyClass.class_method()
    print(obj.static_method()) # MyClass.static_method()
    

    output:

    ('instance method called', <__main__.MyClass object at 0x100fb3940>)
    ('class method called', <class '__main__.MyClass'>)
    static method called
    

    The instance method we actually had access to the object instance , right so this was an instance off a my class object whereas with the class method we have access to the class itself. But not to any of the objects, because the class method doesn't really care about an object existing. However you can both call a class method and static method on an object instance. This is going to work it doesn't really make a difference, so again when you call static method here it's going to work and it's going to know which method you want to call.

    The Static methods are used to do some utility tasks, and class methods are used for factory methods. The factory methods can return class objects for different use cases.

    And finally, a short example for better understanding:

    class Student:
        def __init__(self, first_name, last_name):
            self.first_name = first_name
            self.last_name = last_name
    
        @classmethod
        def get_from_string(cls, name_string: str):
            first_name, last_name = name_string.split()
            if Student.validate_name(first_name) and Student.validate_name(last_name):
                return cls(first_name, last_name)
            else:
                print('Invalid Names')
    
        @staticmethod
        def validate_name(name):
            return len(name) <= 10
    
    
    stackoverflow_student = Student.get_from_string('Name Surname')
    print(stackoverflow_student.first_name) # Name
    print(stackoverflow_student.last_name) # Surname
    
    0 讨论(0)
  • I think a better question is "When would you use @classmethod vs @staticmethod?"

    @classmethod allows you easy access to private members that are associated to the class definition. this is a great way to do singletons, or factory classes that control the number of instances of the created objects exist.

    @staticmethod provides marginal performance gains, but I have yet to see a productive use of a static method within a class that couldn't be achieved as a standalone function outside the class.

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

    The definitive guide on how to use static, class or abstract methods in Python is one good link for this topic, and summary it as following.

    @staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.

    • Python does not have to instantiate a bound-method for object.
    • It eases the readability of the code, and it does not depend on the state of object itself;

    @classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance, can be overridden by subclass. That’s because the first argument for @classmethod function must always be cls (class).

    • Factory methods, that are used to create an instance for a class using for example some sort of pre-processing.
    • Static methods calling static methods: if you split a static methods in several static methods, you shouldn't hard-code the class name but use class methods
    0 讨论(0)
  • 2020-11-21 06:39

    What is the difference between @staticmethod and @classmethod in Python?

    You may have seen Python code like this pseudocode, which demonstrates the signatures of the various method types and provides a docstring to explain each:

    class Foo(object):
    
        def a_normal_instance_method(self, arg_1, kwarg_2=None):
            '''
            Return a value that is a function of the instance with its
            attributes, and other arguments such as arg_1 and kwarg2
            '''
    
        @staticmethod
        def a_static_method(arg_0):
            '''
            Return a value that is a function of arg_0. It does not know the 
            instance or class it is called from.
            '''
    
        @classmethod
        def a_class_method(cls, arg1):
            '''
            Return a value that is a function of the class and other arguments.
            respects subclassing, it is called with the class it is called from.
            '''
    

    The Normal Instance Method

    First I'll explain a_normal_instance_method. This is precisely called an "instance method". When an instance method is used, it is used as a partial function (as opposed to a total function, defined for all values when viewed in source code) that is, when used, the first of the arguments is predefined as the instance of the object, with all of its given attributes. It has the instance of the object bound to it, and it must be called from an instance of the object. Typically, it will access various attributes of the instance.

    For example, this is an instance of a string:

    ', '
    

    if we use the instance method, join on this string, to join another iterable, it quite obviously is a function of the instance, in addition to being a function of the iterable list, ['a', 'b', 'c']:

    >>> ', '.join(['a', 'b', 'c'])
    'a, b, c'
    

    Bound methods

    Instance methods can be bound via a dotted lookup for use later.

    For example, this binds the str.join method to the ':' instance:

    >>> join_with_colons = ':'.join 
    

    And later we can use this as a function that already has the first argument bound to it. In this way, it works like a partial function on the instance:

    >>> join_with_colons('abcde')
    'a:b:c:d:e'
    >>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
    'FF:FF:FF:FF:FF:FF'
    

    Static Method

    The static method does not take the instance as an argument.

    It is very similar to a module level function.

    However, a module level function must live in the module and be specially imported to other places where it is used.

    If it is attached to the object, however, it will follow the object conveniently through importing and inheritance as well.

    An example of a static method is str.maketrans, moved from the string module in Python 3. It makes a translation table suitable for consumption by str.translate. It does seem rather silly when used from an instance of a string, as demonstrated below, but importing the function from the string module is rather clumsy, and it's nice to be able to call it from the class, as in str.maketrans

    # demonstrate same function whether called from instance or not:
    >>> ', '.maketrans('ABC', 'abc')
    {65: 97, 66: 98, 67: 99}
    >>> str.maketrans('ABC', 'abc')
    {65: 97, 66: 98, 67: 99}
    

    In python 2, you have to import this function from the increasingly less useful string module:

    >>> import string
    >>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
    'abcDEFG'
    

    Class Method

    A class method is a similar to an instance method in that it takes an implicit first argument, but instead of taking the instance, it takes the class. Frequently these are used as alternative constructors for better semantic usage and it will support inheritance.

    The most canonical example of a builtin classmethod is dict.fromkeys. It is used as an alternative constructor of dict, (well suited for when you know what your keys are and want a default value for them.)

    >>> dict.fromkeys(['a', 'b', 'c'])
    {'c': None, 'b': None, 'a': None}
    

    When we subclass dict, we can use the same constructor, which creates an instance of the subclass.

    >>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
    >>> md = MyDict.fromkeys(['a', 'b', 'c'])
    >>> md
    {'a': None, 'c': None, 'b': None}
    >>> type(md)
    <class '__main__.MyDict'>
    

    See the pandas source code for other similar examples of alternative constructors, and see also the official Python documentation on classmethod and staticmethod.

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