csdnceshi60
2008-09-25 21:01 阅读 653

@ staticmethod 和@classmethod 的区别是什么?

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

转载于:https://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

23条回答 默认 最新

  • 已采纳
    csdnceshi60 ℡Wang Yan 2009-11-03 19:13

    Maybe a bit of example code will help: Notice the difference in the call signatures of foo, class_foo and static_foo:

    class A(object):
        def foo(self,x):
            print "executing foo(%s,%s)"%(self,x)
    
        @classmethod
        def class_foo(cls,x):
            print "executing class_foo(%s,%s)"%(cls,x)
    
        @staticmethod
        def static_foo(x):
            print "executing static_foo(%s)"%x    
    
    a=A()
    

    Below is the usual way an object instance calls a method. The object instance, a, is implicitly passed as the first argument.

    a.foo(1)
    # executing foo(<__main__.A object at 0xb7dbef0c>,1)
    

    With classmethods, the class of the object instance is implicitly passed as the first argument instead of self.

    a.class_foo(1)
    # executing class_foo(<class '__main__.A'>,1)
    

    You can also call class_foo using the class. In fact, if you define something to be a classmethod, it is probably because you intend to call it from the class rather than from a class instance. A.foo(1) would have raised a TypeError, but A.class_foo(1) works just fine:

    A.class_foo(1)
    # executing class_foo(<class '__main__.A'>,1)
    

    One use people have found for class methods is to create inheritable alternative constructors.


    With staticmethods, neither self (the object instance) nor cls (the class) is implicitly passed as the first argument. They behave like plain functions except that you can call them from an instance or the class:

    a.static_foo(1)
    # executing static_foo(1)
    
    A.static_foo('hi')
    # executing static_foo(hi)
    

    Staticmethods are used to group functions which have some logical connection with a class to the class.


    foo is just a function, but when you call a.foo you don't just get the function, you get a "partially applied" version of the function with the object instance a bound as the first argument to the function. foo expects 2 arguments, while a.foo only expects 1 argument.

    a is bound to foo. That is what is meant by the term "bound" below:

    print(a.foo)
    # <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
    

    With a.class_foo, a is not bound to class_foo, rather the class A is bound to class_foo.

    print(a.class_foo)
    # <bound method type.class_foo of <class '__main__.A'>>
    

    Here, with a staticmethod, even though it is a method, a.static_foo just returns a good 'ole function with no arguments bound. static_foo expects 1 argument, and a.static_foo expects 1 argument too.

    print(a.static_foo)
    # <function static_foo at 0xb7d479cc>
    

    And of course the same thing happens when you call static_foo with the class A instead.

    print(A.static_foo)
    # <function static_foo at 0xb7d479cc>
    
    点赞 26 评论 复制链接分享
  • csdnceshi51 旧行李 2008-09-25 21:07

    Basically @classmethod makes a method whose first argument is the class it's called from (rather than the class instance), @staticmethod does not have any implicit arguments.

    点赞 29 评论 复制链接分享
  • csdnceshi66 必承其重 | 欲带皇冠 2008-09-25 21:05

    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
    >>> 
    
    点赞 23 评论 复制链接分享
  • csdnceshi77 狐狸.fox 2015-12-13 19:37

    @classmethod means: when this method is called, we pass the class as the first argument instead of the instance of that class (as we normally do with methods). This means you can use the class and its properties inside that method rather than a particular instance.

    @staticmethod means: when this method is called, we don't pass an instance of the class to it (as we normally do with methods). This means you can put a function inside a class but you can't access the instance of that class (this is useful when your method does not use the instance).

    点赞 10 评论 复制链接分享
  • csdnceshi80 胖鸭 2016-09-20 09:03

    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.

    点赞 10 评论 复制链接分享
  • weixin_41568174 from.. 2017-09-20 16:57

    @classmethod : can be used to create a shared global access to all the instances created of that class..... like updating a record by multiple users.... I particulary found it use ful when creating singletons as well..:)

    @static method: has nothing to do with the class or instance being associated with ...but for readability can use static method

    点赞 10 评论 复制链接分享
  • csdnceshi52 妄徒之命 2017-12-01 10:38

    Class methods, as the name suggests, are used to make changes to classes and not the objects. To make changes to classes, they will modify the class attributes(not object attributes), since that is how you update classes. This is the reason that class methods take the class(conventionally denoted by 'cls') as the first argument.

    class A(object):
        m=54
    
        @classmethod
        def class_method(cls):
            print "m is %d" % cls.m
    

    Static methods on the other hand, are used to perform functionalities that are not bound to the class i.e. they will not read or write class variables. Hence, static methods do not take classes as arguments. They are used so that classes can perform functionalities that are not directly related to the purpose of the class.

    class X(object):
        m=54 #will not be referenced
    
        @staticmethod
        def static_method():
            print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."
    
    点赞 9 评论 复制链接分享
  • csdnceshi67 bug^君 2008-09-25 21:24

    @staticmethod just disables the default function as method descriptor. classmethod wraps your function in a container callable that passes a reference to the owning class as first argument:

    >>> class C(object):
    ...  pass
    ... 
    >>> def f():
    ...  pass
    ... 
    >>> staticmethod(f).__get__(None, C)
    <function f at 0x5c1cf0>
    >>> classmethod(f).__get__(None, C)
    <bound method type.f of <class '__main__.C'>>
    

    As a matter of fact, classmethod has a runtime overhead but makes it possible to access the owning class. Alternatively I recommend using a metaclass and putting the class methods on that metaclass:

    >>> class CMeta(type):
    ...  def foo(cls):
    ...   print cls
    ... 
    >>> class C(object):
    ...  __metaclass__ = CMeta
    ... 
    >>> C.foo()
    <class '__main__.C'>
    
    点赞 8 评论 复制链接分享
  • weixin_41568174 from.. 2012-02-24 09:32

    @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.

    点赞 8 评论 复制链接分享
  • csdnceshi72 谁还没个明天 2015-05-19 15:27

    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.

    点赞 7 评论 复制链接分享
  • weixin_41568183 零零乙 2018-01-14 14:07

    Let me first tell the similarity between a method decorated with @classmethod vs @staticmethod first.

    Similarity: Both of them can be called on the Class itself, rather than just the instance of the class. So, both of them in a sense are Class's methods.

    Difference: A classmethod will receive the class itself as the first argument, while a staticmethod does not.

    So a static method is, in a sense, not bound to the Class itself and is just hanging in there just because it may have a related functionality.

    >>> class Klaus:
            @classmethod
            def classmthd(*args):
                return args
    
            @staticmethod
            def staticmthd(*args):
                return args
    
    # 1. Call classmethod without any arg
    >>> Klaus.classmthd()  
    (__main__.Klaus,)  # the class gets passed as the first argument
    
    # 2. Call classmethod with 1 arg
    >>> Klaus.classmthd('chumma')
    (__main__.Klaus, 'chumma')
    
    # 3. Call staticmethod without any arg
    >>> Klaus.staticmthd()  
    ()
    
    # 4. Call staticmethod with 1 arg
    >>> Klaus.staticmthd('chumma')
    ('chumma',)
    
    点赞 7 评论 复制链接分享
  • csdnceshi61 derek5. 2018-01-22 20:11

    class method vs static method in Python

    Class Method

    The @classmethod decorator, is a builtin function decorator that is an expression that gets evaluated after your function is defined. The result of that evaluation shadows your function definition.

    A class method receives the class as implicit first argument, just like an instance method receives the instance

    Syntax:

    class C(object):
        @classmethod
        def fun(cls, arg1, arg2, ...):
           ....
    
    fun: function that needs to be converted into a class method
    returns: a class method for function.
    
    • A class method is a method which is bound to the class and not the object of the class.
    • They have the 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.

    Static Method

    A static method does not receive an implicit first argument.

    Syntax:

    class C(object):
        @staticmethod
        def fun(arg1, arg2, ...):
            ...
    returns: a static method for function fun.
    
    • A static method is also a method which is bound to the class and not the object of the class.
    • A static method can’t access or modify class state.
    • It is present in a class because it makes sense for the method to be present in class.

    Class method vs Static Method

    • A class method takes cls as first parameter while a static method needs no specific parameters.
    • A class method can access or modify class state while a static method can’t access or modify it.
    • We use @classmethod decorator in python to create a class method and we use @staticmethod decorator to create a static method in python.

    When to use what?

    • We generally use class method to create factory methods. Factory methods return class object ( similar to a constructor ) for different use cases.
    • We generally use static methods to create utility functions.

    How to define a class method and a static method?

    To define a class method in python, we use @classmethod decorator and to define a static method we use @staticmethod decorator.

    Let us look at an example to understand the difference between both of them. Let us say we want to create a class Person. Now, python doesn’t support method overloading like C++ or Java so we use class methods to create factory methods. In the below example we use a class method to create a person object from birth year.

    As explained above we use static methods to create utility functions. In the below example we use a static method to check if a person is adult or not.

    Implementation

    # Python program to demonstrate 
    # use of class method and static method.
    from datetime import date
    
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        # a class method to create a Person object by birth year.
        @classmethod
        def fromBirthYear(cls, name, year):
            return cls(name, date.today().year - year)
    
        # a static method to check if a Person is adult or not.
        @staticmethod
        def isAdult(age):
            return age > 18
    
    person1 = Person('mayank', 21)
    person2 = Person.fromBirthYear('mayank', 1996)
    
    print person1.age
    print person2.age
    
    # print the result
    print Person.isAdult(22)
    

    Output

    21
    21
    True
    

    Reference

    点赞 6 评论 复制链接分享
  • csdnceshi52 妄徒之命 2018-06-25 02:38

    My contribution demonstrates the difference amongst @classmethod, @staticmethod, and instance methods, including how an instance can indirectly call a @staticmethod. But instead of indirectly calling a @staticmethod from an instance, making it private may be more "pythonic." Getting something from a private method isn't demonstrated here but it's basically the same concept.

    #!python3
    
    from os import system
    system('cls')
    # %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %
    
    class DemoClass(object):
        # instance methods need a class instance and
        # can access the instance through 'self'
        def instance_method_1(self):
            return 'called from inside the instance_method_1()'
    
        def instance_method_2(self):
            # an instance outside the class indirectly calls the static_method
            return self.static_method() + ' via instance_method_2()'
    
        # class methods don't need a class instance, they can't access the
        # instance (self) but they have access to the class itself via 'cls'
        @classmethod
        def class_method(cls):
            return 'called from inside the class_method()'
    
        # static methods don't have access to 'cls' or 'self', they work like
        # regular functions but belong to the class' namespace
        @staticmethod
        def static_method():
            return 'called from inside the static_method()'
    # %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %
    
    # works even if the class hasn't been instantiated
    print(DemoClass.class_method() + '\n')
    ''' called from inside the class_method() '''
    
    # works even if the class hasn't been instantiated
    print(DemoClass.static_method() + '\n')
    ''' called from inside the static_method() '''
    # %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %
    
    # >>>>> all methods types can be called on a class instance <<<<<
    # instantiate the class
    democlassObj = DemoClass()
    
    # call instance_method_1()
    print(democlassObj.instance_method_1() + '\n')
    ''' called from inside the instance_method_1() '''
    
    # # indirectly call static_method through instance_method_2(), there's really no use
    # for this since a @staticmethod can be called whether the class has been
    # instantiated or not
    print(democlassObj.instance_method_2() + '\n')
    ''' called from inside the static_method() via instance_method_2() '''
    
    # call class_method()
    print(democlassObj.class_method() + '\n')
    '''  called from inside the class_method() '''
    
    # call static_method()
    print(democlassObj.static_method())
    ''' called from inside the static_method() '''
    
    """
    # whether the class is instantiated or not, this doesn't work
    print(DemoClass.instance_method_1() + '\n')
    '''
    TypeError: TypeError: unbound method instancemethod() must be called with
    DemoClass instance as first argument (got nothing instead)
    '''
    """
    
    点赞 6 评论 复制链接分享
  • csdnceshi57 perhaps? 2009-11-03 19:02

    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).

    点赞 5 评论 复制链接分享
  • weixin_41568110 七度&光 2009-11-03 19:23

    Official python docs:

    @classmethod

    A class method receives the class as implicit first argument, just like an instance method receives the instance. To declare a class method, use this idiom:

    class C:
        @classmethod
        def f(cls, arg1, arg2, ...): ... 
    

    The @classmethod form is a function decorator – see the description of function definitions in Function definitions for details.

    It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class. If a class method is called for a derived class, the derived class object is passed as the implied first argument.

    Class methods are different than C++ or Java static methods. If you want those, see staticmethod() in this section.

    @staticmethod

    A static method does not receive an implicit first argument. To declare a static method, use this idiom:

    class C:
        @staticmethod
        def f(arg1, arg2, ...): ... 
    

    The @staticmethod form is a function decorator – see the description of function definitions in Function definitions for details.

    It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.

    Static methods in Python are similar to those found in Java or C++. For a more advanced concept, see classmethod() in this section.

    点赞 4 评论 复制链接分享
  • csdnceshi54 hurriedly% 2017-10-10 10:10

    I started learning programming language with C++ and then Java and then Python and so this question bothered me a lot as well, until I understood the simple usage of each.

    Class Method: Python unlike Java and C++ doesn't have constructor overloading. And so to achieve this you could use classmethod. Following example will explain this

    Let's consider we have a Person class which takes two arguments first_name and last_name and creates the instance of Person.

    class Person(object):
    
        def __init__(self, first_name, last_name):
            self.first_name = first_name
            self.last_name = last_name
    

    Now, if the requirement comes where you need to create a class using a single name only, just a first_name, you can't do something like this in python.

    This will give you an error when you will try to create an object (instance).

    class Person(object):
    
        def __init__(self, first_name, last_name):
            self.first_name = first_name
            self.last_name = last_name
    
        def __init__(self, first_name):
            self.first_name = first_name
    

    However, you could achieve the same thing using @classmethod as mentioned below

    class Person(object):
    
        def __init__(self, first_name, last_name):
            self.first_name = first_name
            self.last_name = last_name
    
        @classmethod
        def get_person(cls, first_name):
            return cls(first_name, "")
    

    Static Method:: This is rather simple, it's not bound to instance or class and you can simply call that using class name.

    So let's say in above example you need a validation that first_name should not exceed 20 characters, you can simply do this.

    @staticmethod  
    def validate_name(name):
        return len(name) <= 20
    

    and you could simply call using Class Name

    Person.validate_name("Gaurang Shah")
    
    点赞 4 评论 复制链接分享
  • csdnceshi71 Memor.の 2017-12-12 09:40

    Analyze @staticmethod literally providing different insights.

    A normal method of a class is an implicit dynamic method which takes the instance as first argument.
    In contrast, a staticmethod does not take the instance as first argument, so is called 'static'.

    A staticmethod is indeed such a normal function the same as those outside a class definition.
    It is luckily grouped into the class just in order to stand closer where it is applied, or you might scroll around to find it.

    点赞 4 评论 复制链接分享
  • csdnceshi76 斗士狗 2015-11-16 02:00

    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
    点赞 2 评论 复制链接分享
  • csdnceshi59 ℙℕℤℝ 2016-09-29 17:02

    Another consideration with respect to staticmethod vs classmethod comes up with inheritance. Say you have the following class:

    class Foo(object):
        @staticmethod
        def bar():
            return "In Foo"
    

    And you then want to override bar() in a child class:

    class Foo2(Foo):
        @staticmethod
        def bar():
            return "In Foo2"
    

    This works, but note that now the bar() implementation in the child class (Foo2) can no longer take advantage of anything specific to that class. For example, say Foo2 had a method called magic() that you want to use in the Foo2 implementation of bar():

    class Foo2(Foo):
        @staticmethod
        def bar():
            return "In Foo2"
        @staticmethod
        def magic():
            return "Something useful you'd like to use in bar, but now can't" 
    

    The workaround here would be to call Foo2.magic() in bar(), but then you're repeating yourself (if the name of Foo2 changes, you'll have to remember to update that bar() method).

    To me, this is a slight violation of the open/closed principle, since a decision made in Foo is impacting your ability to refactor common code in a derived class (ie it's less open to extension). If bar() were a classmethod we'd be fine:

    class Foo(object):
        @classmethod
        def bar(cls):
            return "In Foo"
    
    class Foo2(Foo):
        @classmethod
        def bar(cls):
            return "In Foo2 " + cls.magic()
        @classmethod
        def magic(cls):
            return "MAGIC"
    
    print Foo2().bar()
    

    Gives: In Foo2 MAGIC

    点赞 2 评论 复制链接分享
  • csdnceshi61 derek5. 2016-04-22 15:40

    To decide whether to use @staticmethod or @classmethod you have to look inside your method. If your method accesses other variables/methods in your class then use @classmethod. On the other hand, if your method does not touches any other parts of the class then use @staticmethod.

    class Apple:
    
        _counter = 0
    
        @staticmethod
        def about_apple():
            print('Apple is good for you.')
    
            # note you can still access other member of the class
            # but you have to use the class instance 
            # which is not very nice, because you have repeat yourself
            # 
            # For example:
            # @staticmethod
            #    print('Number of apples have been juiced: %s' % Apple._counter)
            #
            # @classmethod
            #    print('Number of apples have been juiced: %s' % cls._counter)
            #
            #    @classmethod is especially useful when you move your function to other class,
            #       you don't have to rename the class reference 
    
        @classmethod
        def make_apple_juice(cls, number_of_apples):
            print('Make juice:')
            for i in range(number_of_apples):
                cls._juice_this(i)
    
        @classmethod
        def _juice_this(cls, apple):
            print('Juicing %d...' % apple)
            cls._counter += 1
    
    点赞 1 评论 复制链接分享
  • csdnceshi62 csdnceshi62 2016-10-03 10:41

    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
      
    点赞 1 评论 复制链接分享
  • csdnceshi72 谁还没个明天 2012-12-17 18:51

    A quick hack-up ofotherwise identical methods in iPython reveals that @staticmethod yields marginal performance gains (in the nanoseconds), but otherwise it seems to serve no function. Also, any performance gains will probably be wiped out by the additional work of processing the method through staticmethod() during compilation (which happens prior to any code execution when you run a script).

    For the sake of code readability I'd avoid @staticmethod unless your method will be used for loads of work, where the nanoseconds count.

    点赞 评论 复制链接分享
  • csdnceshi75 衫裤跑路 2013-11-18 05:53
    #!/usr/bin/python
    #coding:utf-8
    
    class Demo(object):
        def __init__(self,x):
            self.x = x
    
        @classmethod
        def addone(self, x):
            return x+1
    
        @staticmethod
        def addtwo(x):
            return x+2
    
        def addthree(self, x):
            return x+3
    
    def main():
        print Demo.addone(2)
        print Demo.addtwo(2)
    
        #print Demo.addthree(2) #Error
        demo = Demo(2)
        print demo.addthree(2)
    
    
    if __name__ == '__main__':
        main()
    
    点赞 评论 复制链接分享

相关推荐