问题:静态方法和类方法之间的区别

@staticmethod修饰的功能和用修饰的功能有什么区别@classmethod

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


回答 0

也许有点示例代码将有助于:发现其中的差别在调用签名fooclass_foo并且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()

以下是对象实例调用方法的常用方法。对象实例,a作为第一个参数隐式传递。

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

使用classmethods时,对象实例的类作为第一个参数而不是隐式传递self

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

您也可以class_foo使用该类进行呼叫。实际上,如果您将某些东西定义为类方法,则可能是因为您打算从类而不是从类实例调用它。A.foo(1)本来会引发TypeError,但A.class_foo(1)效果很好:

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

人们发现类方法的一种用途是创建可继承的替代构造函数


使用staticmethods时self(对象实例)和 cls(类)都不会隐式传递为第一个参数。它们的行为类似于普通函数,不同之处在于您可以从实例或类中调用它们:

a.static_foo(1)
# executing static_foo(1)

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

静态方法用于对与类之间具有某种逻辑联系的函数进行分组。


foo只是一个函数,但是当您调用a.foo它时,不仅得到函数,还会得到函数的“部分应用”版本,其中对象实例a绑定为函数的第一个参数。foo期望有2个参数,而a.foo只期望有1个参数。

a势必到foo。这就是下面的术语“绑定”的含义:

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

a.class_fooa不绑定class_foo,而是与类A绑定class_foo

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

在这里,使用静态方法,即使它是一种方法,也a.static_foo只是返回一个没有绑定参数的良好的’ole函数。static_foo期望有1个参数,也 a.static_foo期望有1个参数。

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

当然,当您static_foo使用类进行调用时,也会发生同样的事情A

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

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>

回答 1

一个静态方法是一无所知,它被称为上类或实例的方法。它只是获取传递的参数,没有隐式的第一个参数。在Python中基本上没有用-您可以使用模块函数代替静态方法。

类方法,在另一方面,是获取传递的类,它被称为上,或该类的实例,它被称为上的,作为第一个参数的方法。当您希望该方法成为类的工厂时,这很有用:由于它获得了作为第一个参数调用的实际类,因此即使涉及子类,也始终可以实例化正确的类。例如dict.fromkeys(),观察在子类上调用时,类方法如何返回子类的实例:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

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

回答 2

基本上@classmethod使方法的第一个参数是从其调用的类(而不是类实例),@staticmethod它没有任何隐式参数。

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.


回答 3

官方python文档:

@classmethod

类方法将类作为隐式第一个参数接收,就像实例方法接收实例一样。要声明类方法,请使用以下惯用法:

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

@classmethod表单是一个函数 装饰器 –有关详细信息,请参见函数定义中的函数定义描述。

可以在类(如C.f())或实例(如C().f())上调用它。该实例除其类外均被忽略。如果为派生类调用类方法,则派生类对象作为隐式第一个参数传递。

类方法不同于C ++或Java静态方法。如果需要这些,请参阅staticmethod()本节。

@staticmethod

静态方法不会收到隐式的第一个参数。要声明静态方法,请使用以下惯用法:

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

@staticmethod表单是一个函数 装饰器 –有关详细信息,请参见函数定义中的函数定义描述。

可以在类(如C.f())或实例(如C().f())上调用它。该实例除其类外均被忽略。

Python中的静态方法类似于Java或C ++中的静态方法。有关更高级的概念,请参阅 classmethod()本节。

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

是关于这个问题的简短文章

@staticmethod函数不过是在类内部定义的函数。可调用而无需先实例化该类。它的定义通过继承是不可变的。

@classmethod函数也可以在不实例化类的情况下调用,但是其定义是通过继承遵循Sub类,而不是Parent类。这是因为@classmethod函数的第一个参数必须始终为cls(类)。

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

要决定使用@staticmethod还是@classmethod,您必须查看方法内部。如果您的方法访问类中的其他变量/方法,请使用@classmethod。另一方面,如果您的方法未触及类的其他任何部分,请使用@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

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

回答 6

Python中的@staticmethod和@classmethod有什么区别?

您可能已经看到了类似此伪代码的Python代码,该代码演示了各种方法类型的签名,并提供了一个文档字符串来说明每种方法:

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

普通实例方法

首先,我会解释a_normal_instance_method。这就是所谓的“ 实例方法 ”。使用实例方法时,它用作部分函数(与总函数相反,在源代码中查看时为所有值定义的总函数),即在使用时,将第一个参数预定义为具有所有给定属性的对象。它具有绑定到其对象的实例,并且必须从该对象的实例调用它。通常,它将访问实例的各种属性。

例如,这是一个字符串的实例:

', '

如果我们join在该字符串上使用实例方法来连接另一个可迭代对象,则很明显,它是实例的功能,除了是可迭代列表的功能之外,还['a', 'b', 'c']

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

绑定方法

可以通过点分查找来绑定实例方法,以备后用。

例如,这将str.join方法绑定到':'实例:

>>> join_with_colons = ':'.join 

之后,我们可以将其用作已绑定第一个参数的函数。这样,它就像实例上的部分函数一样工作:

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

静态方法

静态方法并没有把实例作为参数。

它与模块级功能非常相似。

但是,模块级功能必须存在于模块中,并且必须专门导入到其他使用该功能的地方。

但是,如果将其附加到对象上,它也将通过导入和继承方便地跟随对象。

静态方法的一个示例是str.maketransstringPython 3 的模块中移出的。它使转换表适合由占用str.translate。从字符串的实例使用时,看起来确实很愚蠢,如下所示,但是从string模块导入函数相当笨拙,并且能够从类中调用它很好,例如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}

在python 2中,您必须从越来越少用的字符串模块中导入此函数:

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

类方法

类方法与实例方法类似,因为它采用了隐式的第一个参数,但是它采用了类,而不是采用实例。通常,它们被用作替代构造函数以更好地使用语义,并且它将支持继承。

内建类方法的最典型示例是dict.fromkeys。它用作dict的替代构造函数(非常适合当您知道键是什么并且想要它们的默认值时)。

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

当我们对dict进行子类化时,可以使用相同的构造函数,该构造函数创建子类的实例。

>>> 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'>

看到熊猫的源代码的替代构造其它类似的例子,同时也看到了官方的Python文档classmethodstaticmethod

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.


回答 7

我开始使用C ++,Java和Python学习编程语言,所以这个问题也困扰着我,直到我理解了每种语言的简单用法。

类方法:与Java和C ++不同,Python没有构造函数重载。因此,可以使用实现此目的classmethod。以下示例将对此进行解释

让我们考虑,我们有一个Person类,它有两个参数first_name,并last_name与创建的实例Person

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

现在,如果您只需要使用一个名称创建一个类(仅使用一个名称)first_name,那么您将无法在Python中执行类似的操作。

当您尝试创建对象(实例)时,这将给您一个错误。

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

但是,您可以使用@classmethod以下方法实现相同的目的

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, "")

静态方法:这很简单,它不受实例或类的约束,您可以使用类名简单地调用它。

因此,假设在上面的示例中,您需要一个first_name不超过20个字符的验证,您只需执行此操作即可。

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

你可以简单地使用 class name

Person.validate_name("Gaurang Shah")

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

回答 8

我认为一个更好的问题是“何时使用@classmethod与@staticmethod?”

@classmethod允许您轻松访问与类定义关联的私有成员。这是完成单例或工厂类的一种好方法,该类控制已创建对象的实例数量。

@staticmethod可以提供少量的性能提升,但是我还没有看到在类中有效地使用静态方法,而该方法不能作为类外的独立函数来实现。

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.


回答 9

@decorators是在python 2.4中添加的。如果您使用的是python <2.4,则可以使用classmethod()和staticmethod()函数。

例如,如果您想创建一个工厂方法(一个函数根据得到的参数返回一个类的不同实现的实例),您可以执行以下操作:

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)

还要注意,这是使用类方法和静态方法的一个很好的例子。静态方法显然属于该类,因为它在内部使用类Cluster。类方法仅需要有关类的信息,而无需对象的实例。

_is_cluster_for方法设为类方法的另一个好处是,子类可以决定更改其实现,这可能是因为它非常通用并且可以处理多种类型的集群,因此仅检查类的名称是不够的。

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


回答 10

静态方法:

  • 没有自变量的简单函数。
  • 处理类属性;不在实例属性上。
  • 可以通过类和实例调用。
  • 内置函数staticmethod()用于创建它们。

静态方法的好处:

  • 它在类范围内本地化函数名称
  • 它将功能代码移近使用位置
  • 与模块级函数相比,导入更方便,因为不必专门导入每种方法

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

类方法:

  • 具有第一个参数作为类名的函数。
  • 可以通过类和实例调用。
  • 这些是使用classmethod内置函数创建的。

     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass

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
    

回答 11

@staticmethod只是禁用默认函数作为方法描述符。classmethod将函数包装在可调用的容器中,该容器将对拥有类的引用作为第一个参数传递:

>>> 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'>>

实际上,classmethod它具有运行时开销,但可以访问拥有的类。另外,我建议使用元类并将类方法放在该元类上:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>

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

回答 12

关于如何在Python中使用静态,类或抽象方法的权威指南是该主题的一个很好的链接,并总结如下。

@staticmethod函数不过是在类内部定义的函数。可调用而无需先实例化该类。它的定义通过继承是不可变的。

  • Python不必实例化对象的绑定方法。
  • 它简化了代码的可读性,并且不依赖于对象本身的状态。

函数也可以在不实例化该类的情况下调用,但是其定义遵循子类,而不是父类,通过继承可以被子类覆盖。这是因为@classmethodfunction 的第一个参数必须始终为cls(类)。

  • 工厂方法,用于使用例如某种预处理为类创建实例。
  • 静态方法调用静态方法:如果将静态方法拆分为多个静态方法,则不应硬编码类名,而应使用类方法

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;

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

回答 13

只有第一个参数不同

  • 普通方法:当前对象(如果自动作为(附加)第一个参数传递)
  • classmethod:当前对象的类作为(附加)fist参数自动传递
  • 静态方法:不会自动传递其他参数。您传递给该函数的就是所得到的。

更详细地…

普通方法

调用对象的方法时,它会自动获得一个额外的参数self作为其第一个参数。即方法

def f(self, x, y)

必须使用2个参数调用。self是自动传递的,它是对象本身

类方法

装饰方法时

@classmethod
def f(cls, x, y)

自动提供的参数不是 self,而是的类 self

静态方法

装饰方法时

@staticmethod
def f(x, y)

该方法根本没有任何自动参数。仅提供调用它的参数。

用法

  • classmethod 主要用于替代构造函数。
  • staticmethod不使用对象的状态。它可能是类外部的函数。它仅放在类中以将具有相似功能的功能分组(例如,类似于Java的Math类静态方法)
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)

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)


回答 14

让我先说一下用@classmethod装饰的方法与@staticmethod装饰的方法之间的相似性。

相似:两者都可以在本身上调用,而不仅仅是类的实例。因此,从某种意义上来说,它们都是Class的方法

区别:类方法将接收类本身作为第一个参数,而静态方法则不接收。

因此,从某种意义上说,静态方法并不绑定于Class本身,而只是因为它可能具有相关的功能而挂在这里。

>>> 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',)

Let me 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',)

回答 15

关于静态方法与类方法的另一个考虑是继承。假设您有以下类:

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

然后,您想覆盖bar()一个子类:

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

这是可行的,但是请注意,现在bar()子类(Foo2)中的实现不再可以利用该类的任何特定优势。例如,假设Foo2有一个magic()要在Foo2实现中使用的名为的方法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" 

这里的解决办法是打电话Foo2.magic()bar(),但此时你重复自己(如果名称Foo2的改变,你必须记住要更新bar()方法)。

对我来说,这有点违反开放式/封闭式原则,因为做出的决定Foo会影响您在派生类中重构通用代码的能力(即扩展性较小)。如果bar()是a,classmethod我们会没事的:

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

给出: In Foo2 MAGIC

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


回答 16

我将尝试通过一个示例来说明基本区别。

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-我们可以直接调用静态方法和类方法而无需初始化

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

2-静态方法不能调用self方法,但可以调用其他static和classmethod

3-静态方法属于类,根本不会使用对象。

4-类方法不绑定到对象而是绑定到类。

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.


回答 17

@classmethod:可用于创建对该类创建的所有实例的共享全局访问……例如由多个用户更新记录….我特别发现创建单例时它也很有效..: )

@static方法:与与…相关联的类或实例无关,但出于可读性考虑,可以使用static方法

@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


回答 18

您可能需要考虑以下两者之间的区别:

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

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

这在python2和python3之间发生了变化:

python2:

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

python3:

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

因此@staticmethod,仅在类中直接使用 for方法已成为python3中的可选方法。如果要从类和实例中调用它们,则仍需要使用@staticmethod装饰器。

unutbus的答案很好地涵盖了其他情况。

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.


回答 19

我的贡献演示之间的差异@classmethod@staticmethod以及实例方法,包括如何实例可以间接调用@staticmethod。但是@staticmethod与其从实例中间接调用a ,不如将其设为私有可能更像是“ pythonic”。这里没有演示从私有方法获取某些东西,但是基本上是相同的概念。

#!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)
'''
"""

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)
'''
"""

回答 20

类方法将类作为隐式第一个参数接收,就像实例方法接收实例一样。它是绑定到类而不是类对象的方法,因为它使用指向类而不是对象实例的类参数,所以可以访问类的状态。它可以修改适用于该类所有实例的类状态。例如,它可以修改将适用于所有实例的类变量。

另一方面,与类方法或实例方法相比,静态方法不接收隐式的第一个参数。并且无法访问或修改类状态。它仅属于该类,因为从设计的角度来看这是正确的方法。但是就功能而言,在运行时未绑定到该类。

作为准则,请将静态方法用作实用程序,将类方法用作例如factory。或定义一个单例。并使用实例方法对实例的状态和行为进行建模。

希望我很清楚!

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 !


回答 21

顾名思义,类方法用于更改类而不是对象。为了更改类,他们将修改类属性(而不是对象属性),因为这是更新类的方式。这就是类方法将类(通常用“ cls”表示)作为第一个参数的原因。

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m

另一方面,静态方法用于执行未绑定到类的功能,即它们不会读取或写入类变量。因此,静态方法不将类作为参数。使用它们是为了使类执行与该类目的不直接相关的功能。

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

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

回答 22

从字面上分析@staticmethod可以提供不同的见解。

类的常规方法是隐式动态方法,该方法将实例作为第一个参数。
相反,静态方法不将实例作为第一个参数,因此称为“静态”

静态方法确实是一种正常的功能,与类定义之外的功能相同。
幸运的是,将它分组在类中只是为了靠近它的应用位置,或者您可以滚动查找它。

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.


回答 23

我认为给出一个纯Python版本的staticmethodclassmethod将有助于在语言级别上理解它们之间的区别。

它们都是非数据描述符(如果您先熟悉描述符,会更容易理解它们)。

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


class ClassMethod(object):
    "Emulate PyClassMethod_Type() in Objects/funcobject.c"
    def __init__(self, f):
        self.f = f

    def __get__(self, obj, cls=None):
        def inner(*args, **kwargs):
            if cls is None:
                cls = type(obj)
            return self.f(cls, *args, **kwargs)
        return inner

I think giving a purely Python version of staticmethod and classmethod would help to understand the difference between them at language level.

Both of them are non-data descriptors (It would be easier to understand them if you are familiar with descriptors first).

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


class ClassMethod(object):
    "Emulate PyClassMethod_Type() in Objects/funcobject.c"
    def __init__(self, f):
        self.f = f

    def __get__(self, obj, cls=None):
        def inner(*args, **kwargs):
            if cls is None:
                cls = type(obj)
            return self.f(cls, *args, **kwargs)
        return inner

回答 24

静态方法无法访问继承层次结构中的对象,类或父类的服装。可以直接在类上调用它(无需创建对象)。

classmethod无法访问该对象的属性。但是,它可以访问继承层次结构中的类和父类的属性。可以直接在类上调用它(无需创建对象)。如果在该对象上调用,则它与普通方法相同,后者不会访问self.<attribute(s)>并且self.__class__.<attribute(s)>只能访问。

认为我们有一个带有的类b=2,我们将创建一个对象并将其重新设置为b=4其中。静态方法无法访问以前的任何内容。Classmethod .b==2只能通过进行访问cls.b。:普通方法可以同时访问.b==4通过self.b.b==2通过self.__class__.b

我们可以遵循KISS风格(保持简单,愚蠢):不要使用静态方法和类方法,不要在未实例化它们的情况下使用类,仅访问对象的属性self.attribute(s)。在某些语言中,以这种方式实现了OOP,我认为这不是一个坏主意。:)

staticmethod has no access to attibutes of the object, of the class, or of parent classes in the inheritance hierarchy. It can be called at the class directly (without creating an object).

classmethod has no access to attributes of the object. It however can access attributes of the class and of parent classes in the inheritance hierarchy. It can be called at the class directly (without creating an object). If called at the object then it is the same as normal method which doesn’t access self.<attribute(s)> and accesses self.__class__.<attribute(s)> only.

Think we have a class with b=2, we will create an object and re-set this to b=4 in it. Staticmethod cannot access nothing from previous. Classmethod can access .b==2 only, via cls.b. Normal method can access both: .b==4 via self.b and .b==2 via self.__class__.b.

We could follow the KISS style (keep it simple, stupid): Don’t use staticmethods and classmethods, don’t use classes without instantiating them, access only the object’s attributes self.attribute(s). There are languages where the OOP is implemented that way and I think it is not bad idea. :)


回答 25

在iPython中对其他相同方法的快速分析表明,该方法会@staticmethod产生少量的性能提升(以纳秒为单位),但否则似乎无济于事。另外,staticmethod()在编译过程中(通过运行脚本执行任何代码之前),通过处理该方法的其他工作可能会消除所有性能提升。

出于代码可读性的考虑,@staticmethod除非您的方法用于纳秒级的工作负载,否则我将避免使用。

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.


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。