函数可以是 instance 方法, class 方法或 static 方法。
前者的特征是self
作为其第一个(隐式)参数,直接作用于类的实例,并且不需要任何修饰符。
但是,其他两个方法在方法名称之前需要装饰器@classmethod
和@staticmethod
-这就是为什么我将实例方法称为“默认”方法,即为之不需要包装器。
我的问题是:
假设我正在上课,并且将我的计算分为几个函数以提高可读性。这些方法中只有一种需要访问我逐个实例共享的self.something
变量,但是大多数其他方法不需要了解它们所属的类-它们仅用于“内部整理”。 / p>
是否应该使这些功能(不需要任何self.something
知识的功能)全部@staticmethod
?
这样做需要装饰器,因此需要一个 extra 步骤。
对于每个方法来说,将其作为实例方法将很容易,而不需要使用decotator的额外步骤,因此继承了很多潜力,但由于它不是所需的功能范围。
为什么实例方法是“默认”的?
为什么不将每个方法默认设置为静态方法,并赋予它与带有包装的实例方法相关的额外功能?
答案 0 :(得分:2)
默认使用实例方法的原因是,这通常是您在进行面向对象编程时想要的。我想不出一种声称支持OOP且方法默认为实例方法的语言。类是“带有行为的数据”的模板,因此默认设置是使方法为类的每个实例提供行为。如果只需要功能集合,则可以在模块的顶层定义它们,然后保存不必要的类。
通常,@staticmethod
的意思是“我知道这不是类或其实例的行为,但是它有助于实现真实的行为,并且在类外不是很有用,所以我会在其中命名空间。”如果这些功能在类之外有用,则只需将其设为普通的顶级函数,而不是将其放在类中即可。在适当的地方使用@staticmethod
是有利的;它的调用比实例方法要快一点,因此,如果不需要实例,@staticmethod
会加快代码的速度(注意:在3.7+版本中,{{3} },可以加快实例/类方法的速度。
@classmethod
基本上有两个用例:
cls
是实际的子类(如果适用),而不仅仅是它在其中定义的类)@staticmethod
的替代方法,当该方法需要调用其他静态方法并且您不必一遍又一遍地通过名称引用该类时。重点是,@staticmethod
主要用于您退出OOP时的情况,而@classmethod
是针对利基用例的;实例方法更有用,因此是默认方法。除此之外,作为历史记录,静态和类方法稍后会介绍,因此将它们设置为默认方法会破坏 all 现有的Python代码,而没有真正的好处。
在@staticmethod
被忽略的实例方法上使用self
的主要原因(当不需要self
时)是,当在类本身上被调用时,它将继续工作,不只是在课程实例上如果您尝试呼叫MyClass.notreallystatic()
,它将因缺少self
而死,而MyClass.actuallystatic()
会起作用。