Python中@staticmethod和@classmethod有什么区别?
装饰与 @staticmethod
和一个用 @classmethod
?
What is the difference between a method decorated with @staticmethod
and one decorated with @classmethod
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
也许一些示例代码会有所帮助:请注意
foo
、class_foo
和static_foo
的调用签名的差异:下面是通常的方法对象实例调用方法。 对象实例
a
作为第一个参数隐式传递。使用类方法,对象实例的类将作为第一个参数隐式传递,而不是
self
。您还可以使用该类调用
class_foo
。 事实上,如果你定义某件事一个类方法,这可能是因为您打算从类而不是从类实例调用它。
A.foo(1)
会引发 TypeError,但A.class_foo(1)
工作得很好:人们发现类方法的一个用途是创建 可继承的替代构造函数。
使用静态方法,
self
(对象实例)和cls
(类)都不会作为第一个参数隐式传递。 它们的行为类似于普通函数,只不过您可以从实例或类调用它们:静态方法用于将与类有某种逻辑联系的函数分组到类中。
foo
只是一个函数,但是当你调用a.foo
时,你得到的不仅仅是函数,您将获得该函数的“部分应用”版本,其中对象实例
a
绑定为该函数的第一个参数。foo
需要 2 个参数,而a.foo
仅需要 1 个参数。a
绑定到foo
。 这就是下面术语“绑定”的含义:对于
a.class_foo
,a
并未绑定到class_foo
,而是绑定到类 < code>A 绑定到class_foo
。在这里,使用 staticmethod,即使它是一个方法,
a.static_foo
也只是返回一个很好的 'ole 函数,没有参数绑定。
static_foo
需要 1 个参数,并且a.static_foo
也需要 1 个参数。当然,当您使用类
A
调用static_foo
时,也会发生同样的情况。Maybe a bit of example code will help: Notice the difference in the call signatures of
foo
,class_foo
andstatic_foo
:Below is the usual way an object instance calls a method. The object instance,
a
, is implicitly passed as the first argument.With classmethods, the class of the object instance is implicitly passed as the first argument instead of
self
.You can also call
class_foo
using the class. In fact, if you define something to bea 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, butA.class_foo(1)
works just fine:One use people have found for class methods is to create inheritable alternative constructors.
With staticmethods, neither
self
(the object instance) norcls
(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: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 calla.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, whilea.foo
only expects 1 argument.a
is bound tofoo
. That is what is meant by the term "bound" below:With
a.class_foo
,a
is not bound toclass_foo
, rather the classA
is bound toclass_foo
.Here, with a staticmethod, even though it is a method,
a.static_foo
just returnsa good 'ole function with no arguments bound.
static_foo
expects 1 argument, anda.static_foo
expects 1 argument too.And of course the same thing happens when you call
static_foo
with the classA
instead.静态方法是一种对调用它的类或实例一无所知的方法。 它只是获取传递的参数,没有隐式的第一个参数。
另一方面,类方法是一种将调用它的类或调用它的实例的类作为第一个参数传递的方法。 当您希望该方法成为类的工厂时,这非常有用:因为它获取作为第一个参数调用的实际类,所以您始终可以实例化正确的类,即使涉及子类也是如此。 例如,观察类方法 dict.fromkeys() 在子类上调用时如何返回子类的实例:
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.
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:基本上,
@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.决定是否使用 @staticmethod 或 @classmethod 你必须查看你的方法内部。 如果您的方法访问类中的其他变量/方法,则使用@classmethod。 另一方面,如果您的方法不涉及类的任何其他部分,则使用@staticmethod。
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.
官方 python 文档:
@classmethod
@staticmethod
Official python docs:
@classmethod
@staticmethod
这里是关于这个问题的一篇简短文章
Here is a short article on this question
您可能已经看过像这样的伪代码的 Python 代码,它演示了各种方法类型的签名,并提供了文档字符串来解释每种方法类型:
普通实例方法
首先我将解释
a_normal_instance_method
。 这准确地称为“实例方法”。 当使用实例方法时,它被用作部分函数(与在源代码中查看时为所有值定义的总函数相反),也就是说,在使用时,第一个参数被预定义为该实例的实例。对象,及其所有给定的属性。 它绑定了对象的实例,并且必须从对象的实例调用它。 通常,它将访问实例的各种属性。例如,这是一个字符串的实例:
如果我们在此字符串上使用实例方法
join
来连接另一个可迭代对象,很明显,它是实例的函数,除了是可迭代列表的函数之外,
['a', 'b', 'c']
:绑定方法
实例方法可以通过以下方式绑定点式查找供稍后使用。
例如,这将
str.join
方法绑定到':'
实例:稍后我们可以将其用作已绑定第一个参数的函数。 通过这种方式,它的工作方式就像实例上的部分函数:
静态方法
静态方法不将实例作为参数。
它与模块级功能非常相似。
但是,模块级函数必须存在于模块中,并专门导入到使用它的其他地方。
但是,如果它附加到对象,它也将通过导入和继承方便地跟随对象。
静态方法的一个示例是
str.maketrans
,它是从 Python 3 中的string
模块移出的。它使翻译表适合str.translate< 使用/代码>。 当从字符串实例使用时,它看起来确实相当愚蠢,如下所示,但是从
string
模块导入该函数相当笨拙,并且能够从类中调用它真是太好了,如str.maketrans
在 python 2 中,您必须从越来越不那么有用的字符串模块中导入此函数:
类方法
类方法与实例方法类似,因为它采用隐式第一个参数,但它不是采用实例,而是采用类。 它们经常被用作替代构造函数以获得更好的语义使用,并且它将支持继承。
内置类方法最典型的示例是 dict.fromkeys。 它被用作 dict 的替代构造函数(非常适合当您知道键是什么并且想要它们的默认值时。)
当我们子类 dict 时,我们可以使用相同的构造函数,它创建子类的实例。
有关其他类似的替代示例,请参阅 pandas 源代码构造函数,另请参阅有关
classmethod
和staticmethod
。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:
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']
: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: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:
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 thestring
module in Python 3. It makes a translation table suitable for consumption bystr.translate
. It does seem rather silly when used from an instance of a string, as demonstrated below, but importing the function from thestring
module is rather clumsy, and it's nice to be able to call it from the class, as instr.maketrans
In python 2, you have to import this function from the increasingly less useful string module:
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.)When we subclass dict, we can use the same constructor, which creates an instance of the subclass.
See the pandas source code for other similar examples of alternative constructors, and see also the official Python documentation on
classmethod
andstaticmethod
.我开始学习 C++ 编程语言,然后是 Java,然后是 Python,所以这个问题也让我很困扰,直到我理解了每种语言的简单用法。
类方法:与 Java 和 C++ 不同,Python 没有构造函数重载。 因此,要实现此目的,您可以使用
classmethod
。 下面的示例将解释这一点让我们假设我们有一个
Person
类,它接受两个参数first_name
和last_name
并创建Person< 的实例/代码>。
现在,如果您需要仅使用单个名称(即
first_name
)创建一个类,那么您不能在 Python 中执行类似的操作。当您尝试创建对象(实例)时,这会给您带来错误。
但是,您可以使用
@classmethod
实现相同的效果,如下所述静态方法: 这相当简单,它不绑定到实例或类,您可以简单地使用班级名称。
因此,假设在上面的示例中,您需要验证
first_name
不应超过 20 个字符,您可以简单地执行此操作。您可以简单地使用
类名
进行调用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 thisLet's consider we have a
Person
class which takes two argumentsfirst_name
andlast_name
and creates the instance ofPerson
.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).
However, you could achieve the same thing using
@classmethod
as mentioned belowStatic 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.and you could simply call using
class name
只有第一个参数不同:
更详细地说...
普通方法
“标准”方法,就像在每种面向对象语言中一样。 当调用对象的方法时,会自动为其提供一个额外的参数
self
作为其第一个参数。 也就是说,必须使用 2 个参数调用方法。
self
是自动传递的,它是对象本身。 类似于神奇地出现在eg中的this
。 java/c++,仅在python中明确显示。类方法
当方法被装饰时
自动提供的参数不是
self
,而是self
的类。静态方法
当该方法被修饰时,
该方法根本不会被赋予任何自动参数。 仅给出调用它时使用的参数。
用法
classmethod
主要用于替代构造函数。staticmethod
不使用对象的状态,甚至不使用类本身的结构。 它可以是类的外部函数。 它只放在类内部,用于对具有相似功能的函数进行分组(例如,像 Java 的Math
类静态方法)Only the first argument differs:
In more detail...
normal method
The "standard" method, as in every object oriented language. When an object's method is called, it is automatically given an extra argument
self
as its first argument. That is, methodmust be called with 2 arguments.
self
is automatically passed, and it is the object itself. Similar to thethis
that magically appears in eg. java/c++, only in python it is shown explicitly.class method
When the method is decorated
the automatically provided argument is not
self
, but the class ofself
.static method
When the method is decorated
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, or even the structure of the class itself. 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'sMath
class static methods)我认为更好的问题是“你什么时候使用
@classmethod
vs@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.静态方法:
静态方法的好处:
与模块级函数相比,导入更方便,因为每个方法都不必专门进口
<前><代码>@staticmethod
def some_static_method(*args, **kwds):
经过
类方法:
这些是使用 classmethod 内置函数创建的。
<前><代码> @classmethod
def some_class_method(cls, *args, **kwds):
经过
Static Methods:
Benefits of Static Methods:
More convenient to import versus module-level functions since each method does not have to be specially imported
Class Methods:
These are created with classmethod in-built function.
@decorators 是在 python 2.4 中添加的如果你使用的是 python < 2.4 可以使用classmethod()和staticmethod()函数。
例如,如果您想创建一个工厂方法(一个函数,根据它获取的参数返回类的不同实现的实例),您可以执行以下操作:
另请注意,这是使用类方法的一个很好的示例,并且静态方法,
静态方法显然属于该类,因为它在内部使用类 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:
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.我先说说@classmethod和@staticmethod修饰的方法之间的相似之处。
相似之处:它们都可以在类本身上调用,而不仅仅是类的实例。 所以,从某种意义上说,它们都是类的方法。
区别:类方法将接收类本身作为第一个参数,而静态方法则不会。
因此,从某种意义上说,静态方法并不绑定到类本身,只是因为它可能具有相关功能而挂在那里。
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.
@staticmethod
只是禁用默认函数作为方法描述符。 classmethod 将您的函数包装在一个可调用容器中,该容器可调用对象传递对所属类的引用作为第一个参数:事实上,
classmethod
具有运行时开销,但可以访问所属类。 或者,我建议使用元类并将类方法放在该元类上:@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: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:有关如何在 Python 中使用静态、类或抽象方法的权威指南是该主题的一个很好的链接,并将其总结如下。
@staticmethod
函数只不过是在类内部定义的函数。 无需先实例化该类即可调用它。 它的定义通过继承是不可变的。@classmethod
函数也可以在不实例化类的情况下调用,但它的定义遵循子类,而不是父类,通过继承,可以被子类覆盖。 这是因为@classmethod
函数的第一个参数必须始终是 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.@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).关于静态方法与类方法的另一个考虑因素是继承。 假设您有以下类:
然后您想在子类中重写
bar()
:这可行,但请注意,现在子类中的
bar()
实现类 (Foo2
) 无法再利用该类特有的任何内容。 例如,假设Foo2
有一个名为magic()
的方法,您希望在bar()< 的
Foo2
实现中使用该方法。 /code>:这里的解决方法是在
bar()
中调用Foo2.magic()
,但随后您会重复自己(如果的名称Foo2
发生变化,您必须记住更新该bar()
方法)。对我来说,这稍微违反了开放/封闭原则,因为做出了决定in
Foo
正在影响您在派生类中重构公共代码的能力(即它对扩展的开放程度较低)。 如果bar()
是一个classmethod
我们就可以了:给出:
In Foo2 MAGIC
另外:历史记录:Guido Van Rossum(Python 的创建者) )曾经将
staticmethod
称为“意外”:https://mail.python.org/pipermail/python-ideas/2012-May/014969.htmlhttps ://mail.python.org/pipermail/python-ideas/2016-July/041189.html
Another consideration with respect to staticmethod vs classmethod comes up with inheritance. Say you have the following class:
And you then want to override
bar()
in a child class: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, sayFoo2
had a method calledmagic()
that you want to use in theFoo2
implementation ofbar()
:The workaround here would be to call
Foo2.magic()
inbar()
, but then you're repeating yourself (if the name ofFoo2
changes, you'll have to remember to update thatbar()
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). Ifbar()
were aclassmethod
we'd be fine:Gives:
In Foo2 MAGIC
Also: historical note: Guido Van Rossum (Python's creator) once referred to
staticmethod
's as "an accident": https://mail.python.org/pipermail/python-ideas/2012-May/014969.htmlAlso: https://mail.python.org/pipermail/python-ideas/2016-July/041189.html
当存在继承时就会出现差异。
假设有两个类 -
Parent
和Child
。 如果要使用@staticmethod
,print_name
方法应该写两次,因为类的名称应该写在打印行中。但是,对于
@classmethod
,不需要写两次print_name
方法。The difference occurs when there is inheritance.
Suppose that there are two classes --
Parent
andChild
. If one wants to use@staticmethod
,print_name
method should be written twice because the name of the class should be written in the print line.However, for
@classmethod
, it is not required to writeprint_name
method twice.实例方法:
+
可以修改对象实例状态+
可以< /em> 修改类状态类方法:
-
无法修改对象实例状态+< /code> 可以修改类状态
静态方法:
-
不能修改对象实例状态-
无法修改类状态输出:
我们实际上可以访问对象实例的实例方法,所以这是我的类对象的实例,而通过类方法,我们可以访问类本身。 但不适用于任何对象,因为类方法并不真正关心对象是否存在。 但是,您可以在对象实例上调用类方法和静态方法。 这会起作用,但实际上并没有什么区别,所以当你在这里调用静态方法时,它会起作用,并且它会知道你想调用哪个方法。
静态方法用于执行一些实用任务,类方法用于工厂方法。 工厂方法可以为不同的用例返回类对象。
最后,为了更好地理解一个简短的例子:
Instance Method:
+
Can modify object instance state+
Can modify class stateClass Method:
-
Can't modify object instance state+
Can modify class stateStatic Method:
-
Can't modify object instance state-
Can't modify class stateoutput:
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:
我将尝试用一个例子来解释基本的区别。
1 - 我们可以直接调用静态方法和类方法,而不需要初始化
2 - 静态方法不能调用 self 方法,但可以调用其他静态方法和类方法
3 - 静态方法属于类,根本不会使用对象。
4-类方法不绑定到对象,而是绑定到类。
I will try to explain the basic difference using an example.
1 - we can directly call static and classmethods without initializing
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.
Python 带有几个内置的装饰器。 其中最重要的三个是:
首先让我们注意,类的任何函数都可以通过此类的实例来调用(在我们初始化此类之后)。
@classmethod 是一种调用函数的方法,不仅作为类的实例,而且直接由类本身作为其第一个参数。
@staticmethod 是一种将函数放入类中的方法(因为它逻辑上属于该类),同时表明它不需要访问该类(因此我们不需要使用函数定义中的
self
)。让我们考虑以下类:
让我们看看它是如何工作的:
在这里您可以看到这些方法的一些用例。
额外奖励:您可以在此处阅读有关
@property
装饰器的信息Python comes with several built-in decorators. The big three are:
First let's note that any function of a class can be called with instance of this class (after we initialized this class).
@classmethod is the way to call function not only as an instance of a class but also directly by the class itself as its first argument.
@staticmethod is a way of putting a function into a class (because it logically belongs there), while indicating that it does not require access to the class (so we don't need to use
self
in function definition).Let's consider the following class:
Let's see how it works:
Here you can see some use cases for those methods.
Bonus: you can read about
@property
decorator here@classmethod:可用于创建对该类创建的所有实例的共享全局访问......就像多个用户更新记录......
我特别发现它在创建单例时也很有用......:)
@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
类方法接收类作为隐式第一个参数,就像实例方法接收实例一样。 它是绑定到类而不是类的对象的方法。它可以访问类的状态,因为它采用指向类而不是对象实例的类参数。 它可以修改适用于该类的所有实例的类状态。 例如,它可以修改适用于所有实例的类变量。
另一方面,与类方法或实例方法相比,静态方法不接收隐式第一个参数。 并且无法访问或修改类状态。 它只属于类,因为从设计的角度来看这是正确的方法。 但就功能而言,在运行时并不绑定到类。
作为指导,使用静态方法作为实用程序,使用类方法(例如工厂)。 或者也许定义一个单例。 并使用实例方法对实例的状态和行为进行建模。
希望我说清楚了!
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 !
我的贡献演示了
@classmethod
、@staticmethod
和实例方法之间的区别,包括实例如何间接调用@staticmethod
。 但是,与其从实例间接调用@staticmethod,不如将其设为私有可能更“Pythonic”。 这里没有演示从私有方法获取某些内容,但它基本上是相同的概念。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.您可能需要考虑以下之间的区别:
和
python2 和 python3 之间发生了变化:
python2:
python3:
因此,对仅直接从类调用的方法使用
@staticmethod
在 python3 中已成为可选。 如果您想从类和实例中调用它们,您仍然需要使用 @staticmethod 装饰器。unutbus 的回答已经很好地涵盖了其他情况。
You might want to consider the difference between:
and
This has changed between python2 and python3:
python2:
python3:
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.
顾名思义,类方法用于更改类而不是对象。 要对类进行更改,他们将修改类属性(而不是对象属性),因为这就是更新类的方式。
这就是类方法将类(通常用“cls”表示)作为第一个参数的原因。
另一方面,静态方法用于执行未绑定到类的功能,即它们不会读取或写入类变量。 因此,静态方法不将类作为参数。 使用它们是为了使类可以执行与类的用途不直接相关的功能。
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.
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.
我认为给出
staticmethod
和classmethod
的纯 Python 版本将有助于理解它们在语言级别上的差异(请参阅 描述符操作指南)。它们都是非数据描述符(如果您熟悉 描述符)。
I think giving a purely Python version of
staticmethod
andclassmethod
would help to understand the difference between them at language level (Refers to Descriptor Howto Guide).Both of them are non-data descriptors (It would be easier to understand them if you are familiar with descriptors first).
从字面上分析@staticmethod,提供不同的见解。
类的普通方法是隐式动态方法,它将实例作为第一个参数。
相反,静态方法不将实例作为第一个参数,因此称为'static'。
静态方法确实是一个普通的函数,与类定义之外的函数相同。
幸运的是,它被分组到类中,只是为了更接近它的应用位置,或者您可能会滚动鼠标来找到它。
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.
首先,让我们从一个示例代码开始,我们将使用它来理解这两个概念:
类方法
类方法接受类本身作为隐式参数,以及定义中指定的任何其他参数(可选)。 重要的是要理解类方法无法访问对象实例(就像实例方法一样)。 因此,类方法不能用于更改实例化对象的状态,但它们能够更改在该类的所有实例之间共享的类状态。
当我们需要访问类本身时,类方法通常很有用 - 例如,当我们想要创建工厂方法(即创建类实例的方法)时。 换句话说,类方法可以充当替代构造函数。
在我们的示例代码中,可以通过提供三个参数来构造
Employee
的实例;first_name
、last_name
和salary
。现在,我们假设可以在单个字段中提供员工姓名,其中名字和姓氏用空格分隔。 在这种情况下,我们可以使用名为
employee_from_full_name
的类方法,该方法总共接受三个参数。 第一个是类本身,它是一个隐式参数,这意味着在调用方法时不会提供它 - Python 会自动为我们执行此操作:请注意,也可以调用
employee_from_full_name 来自对象实例,尽管在这种情况下它没有多大意义:
我们可能想要创建类方法的另一个原因是当我们需要更改类的状态时。 在我们的示例中,类变量
NO_OF_EMPLOYEES
跟踪当前为公司工作的员工人数。 每次创建 Employee 的新实例时都会调用此方法,并相应地更新计数:静态方法
另一方面,在静态方法中,实例(即
self
)或者类本身(即cls
)都作为隐式参数传递。 这意味着此类方法无法访问类本身或其实例。现在有人可能会争辩说,静态方法在类的上下文中没有用,因为它们也可以放置在辅助模块中,而不是将它们添加为类的成员。 在面向对象编程中,将类构造为逻辑块非常重要,因此,当我们需要在类下添加方法时,静态方法非常有用,因为它在逻辑上属于该类。
在我们的示例中,名为
get_employee_legal_obligations_txt
的静态方法仅返回一个字符串,其中包含公司每个员工的法律义务。 此函数不与类本身或任何实例交互。 它可以被放置到不同的帮助器模块中,但是,它仅与此类相关,因此我们必须将其放置在 Employee 类下。静态方法可以直接从类本身
或类的实例访问:
引用
First let's start with an example code that we'll use to understand both concepts:
Class method
A class method accepts the class itself as an implicit argument and -optionally- any other arguments specified in the definition. It’s important to understand that a class method, does not have access to object instances (like instance methods do). Therefore, class methods cannot be used to alter the state of an instantiated object but instead, they are capable of changing the class state which is shared amongst all the instances of that class.
Class methods are typically useful when we need to access the class itself — for example, when we want to create a factory method, that is a method that creates instances of the class. In other words, class methods can serve as alternative constructors.
In our example code, an instance of
Employee
can be constructed by providing three arguments;first_name
,last_name
andsalary
.Now let’s assume that there’s a chance that the name of an Employee can be provided in a single field in which the first and last names are separated by a whitespace. In this case, we could possibly use our class method called
employee_from_full_name
that accepts three arguments in total. The first one, is the class itself, which is an implicit argument which means that it won’t be provided when calling the method — Python will automatically do this for us:Note that it is also possible to call
employee_from_full_name
from object instances although in this context it doesn’t make a lot of sense:Another reason why we might want to create a class method, is when we need to change the state of the class. In our example, the class variable
NO_OF_EMPLOYEES
keeps track of the number of employees currently working for the company. This method is called every time a new instance of Employee is created and it updates the count accordingly:Static methods
On the other hand, in static methods neither the instance (i.e.
self
) nor the class itself (i.e.cls
) is passed as an implicit argument. This means that such methods, are not capable of accessing the class itself or its instances.Now one could argue that static methods are not useful in the context of classes as they can also be placed in helper modules instead of adding them as members of the class. In object oriented programming, it is important to structure your classes into logical chunks and thus, static methods are quite useful when we need to add a method under a class simply because it logically belongs to the class.
In our example, the static method named
get_employee_legal_obligations_txt
simply returns a string that contains the legal obligations of every single employee of a company. This function, does not interact with the class itself nor with any instance. It could have been placed into a different helper module however, it is only relevant to this class and therefore we have to place it under the Employee class.A static method can be access directly from the class itself
or from an instance of the class:
References
子类化时会出现一个非常重要的实际差异。 如果你不介意的话,我会劫持@unutbu的例子:
在
class_foo
中,该方法知道它是在哪个类上调用的:在
static_foo
中,没有办法确定是在A
还是B
上调用:请注意,这并不意味着您不能在
staticmethod
中使用其他方法,您可以只需直接引用该类,这意味着子类的静态方法仍将引用父类:One pretty important practical difference occurs when subclassing. If you don't mind, I'll hijack @unutbu's example:
In
class_foo
, the method knows which class it is called on:In
static_foo
, there is no way to determine whether it is called onA
orB
:Note that this doesn't mean you can't use other methods in a
staticmethod
, you just have to reference the class directly, which means subclasses' staticmethods will still reference the parent class:太棒了;
staticmethod
本质上是绑定到类(及其实例)的函数。classmethod
本质上是可继承的staticmethod
。详情请参阅其他人的精彩回答。
tldr;
A
staticmethod
is essentially a function bound to a class (and consequently its instances)A
classmethod
is essentially an inheritablestaticmethod
.For details, see the excellent answers by others.