【问题标题】:What is "static method" in python什么是python中的“静态方法”
【发布时间】:2020-12-27 12:08:22
【问题描述】:

我对python很陌生,不明白python中的静态方法是什么(例如__new__())以及它的作用。谁能解释一下?谢谢一百万

【问题讨论】:

标签: python static-methods


【解决方案1】:

你已经读过这个了吗?

https://en.wikipedia.org/wiki/Method_(computer_programming)

特别是这个?

https://en.wikipedia.org/wiki/Method_(computer_programming)#Static_methods

说明

在 OOP 中,您可以定义 ,然后在 实例化。一个类只不过是一个蓝图:一旦你从一个类实例化对象,你的对象将完全遵循你的类的蓝图。这意味着:如果您在类中定义了一个名为“abc”的字段,您稍后将在您的对象中拥有一个字段“abc”。如果您在您的类中定义了一个方法“foo()”,那么稍后您将在对象上调用一个方法“foo()”。

请注意,这个“在您的对象上”是必不可少的:您总是实例化一个类,然后您可以调用该方法。这是“正常”的方式。

静态方法是不同的。虽然普通方法总是需要有一个实例(然后您可以在其中调用此方法),但静态方法却。静态方法独立于您的实例存在(这就是它被命名为“静态”的原因)。因此,静态方法与您的类定义本身相关联,因此始终存在,因此只能在您的类本身中调用。它完全独立于所有实例。

这是一个静态方法。

Python 的实现有点……嗯……简单。详细而言,与上述描述存在偏差。但这并没有什么区别:为了与 OOP 概念保持一致,您始终应该使用与上述完全相同的方法。

示例

举个例子:

class FooBar:

  def someMethod(self):
    print("abc")

这是一个常规(实例)方法。你可以这样使用它:

myObj = FooBar()
myObj.someMethod()

如果你有...

myObjB = FooBar()
myObjB.someMethod()

...您有一个额外的实例,因此在第二个实例上调用 someMethod() 将调用第二个 someMethod() 方法 - 在第二个对象中定义。这是因为您在使用之前实例化对象,因此所有实例都遵循定义的蓝图 FooBar。因此,所有实例都会收到某种someMethod() 的副本。

(实际上,Python 将在内部使用优化,因此实际上只有一段代码在内存中实现了您的someMethod(),但现在忘记这一点。对于程序员来说,它显示为一个类的每个实例都会有一个方法 someMethod() 的副本。这就是与我们相关的抽象级别,因为这是我们工作的“表面”。在实现的深处编程或脚本语言的事情可能有点不同,但这不是很相关。)

我们来看一个静态方法:

class FooBar:

  @staticmethod
  def someStaticMethod():
    print("abc")

这样的静态方法可以这样调用:

FooBar.someStaticMethod()

如您所见:没有实例。您直接在类本身的上下文中调用此方法。虽然常规方法适用于特定实例本身 - 它们通常修改此实例本身内的数据 - 类方法却没有。它可以修改静态 (!) 数据,但通常它不会。

将静态方法视为一种特殊情况。很少需要它。如果您编写代码,您通常想要的是 not 来实现静态方法。只有在非常特殊的情况下,实现静态方法才有意义。

self 参数

请注意,标准“实例”方法始终必须将self 作为第一个参数。这是特定于 python 的。在现实世界中,Python 将(当然!)只在内存中存储一​​次您的方法,即使您实例化了您的类的数千个对象。考虑这是一种优化。如果您随后在数千个实例中的一个上调用您的方法,则始终会调用同一段代码。但是为了区分方法的代码应该在您的实例上工作的特定对象,它会作为第一个参数传递给这段内部存储的代码。这是self 参数。它是某种隐式参数,并且对于常规(实例)方法总是需要的。 (不是:静态方法 - 你不需要需要一个实例来调用它们)。

由于这个参数是隐式的,并且大多数编程语言总是需要隐藏它给程序员(并在内部处理这个 - 在引擎盖下 - 以正确的方式)。无论如何,暴露这个特殊的论点并没有多大意义。

不幸的是,Python 没有遵循这个原则。 Python 不会隐藏这个隐式需要的参数。 (Python 对 OOP 概念的结合有点……简单。)因此,您几乎可以在方法中的任何地方看到 self。在您的脑海中您可以忽略它,但如果您定义自己的类,则需要明确编写它。 (为了以良好的方式构建程序,您应该这样做。)

静态方法__new__()

Python 非常特别。虽然常规编程语言遵循如何创建特定类的实例的严格且不可变的概念,但 Python 在这里有点不同。这种行为是可以改变的。此行为在__new__() 中实现。所以如果你这样做......

myObj = FooBar()

... Python 隐式调用FooBar.__new__(),后者又调用一个名为__init__() 的类构造函数(实例)方法,您可以(!)在类中定义(作为实例方法)和then 返回完全初始化的实例。在这个例子中,这个实例就是她存储在myObj 中的内容。

您可以根据需要修改此行为。但这需要一个非常非常非常特别不寻常的用例。在您使用 Python 的整个工作中,您可能永远不会与 __new__() 本身有任何关系。我的建议:如果您对 Python 不熟悉,请忽略它。

【讨论】:

  • 男人很好的答案!我非常喜欢你的澄清。
  • 请注意,staticmethod 可以在实例和类上以任何一种方式调用。它只是不接受任何作为第一个参数。事实上,任何一种方法都可以被调用,但是如果你以“不寻常”的方式使用它,你必须手动传递正确的第一个参数。
  • @deceze:是的。但我建议不要这样做,因为它违反了面向 OOP 概念的干净方法。仅仅因为 Python 允许你做特定的事情并不意味着你真的应该做这些事情。脚本/编程语言只不过是一个工具箱。由您决定哪些工具有意义,哪些没有意义。大多数时候,所有工具都经过精心定义,并且非常有意义。在 Python 中有点不同:有时有些工具没有多大意义,有些工具甚至完全丢失了......
  • @Mario:谢谢,感谢您的赞美。我可以告诉你:这些年来,我为这一切付出了很多。
  • 当然可以,但是这种“随心所欲地调用它”的一个例子是:lst.sort(key=str.upper)。您正在提供str 类的方法,该方法名义上是一个实例方法,但在这里没有实例使用,但由于sort 将如何调用它,它的行为就像在该实例上调用一样。因此,了解这些东西在 Python 中是如何实际工作而不是抽象地保持 OOP 是非常有用的。
猜你喜欢
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
  • 2012-06-10
  • 1970-01-01
相关资源
最近更新 更多