我认为下面的代码会导致错误,因为据我所知,Python 类中的方法必须将"self"(或任何其他标签,但按照惯例为"self"(作为其第一个参数,或者"cls"或类似的参数(如果使用@classmethod
装饰器(,或者如果使用@staticmethod
装饰器则没有。
为什么我在终端中使用 Python 3.5 运行它时没有错误,即使test_method
不符合这些要求?它似乎可以作为静态方法正常工作,但没有装饰器。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
class MyClass:
def test_method(args):
print(args[1])
@staticmethod
def static_method():
print("static_method")
@classmethod
def class_method(cls):
print("class_method")
def main(args):
MyClass.test_method(args)
if __name__ == '__main__':
sys.exit(main(sys.argv))
输出:
$ python3 testscript.py "testing"
$ testing
编辑:
我的问题也可以用不同的措辞,将注意力从self
转移到@staticmethod
:"为什么在没有@staticmethod装饰器的情况下,我得到了一个看似有效的静态方法?
在 Python 2 中,类体中定义的函数会自动转换为"未绑定方法",如果没有 staticmethod 装饰器,则无法直接调用。在 Python 3 中,这个概念被删除了;MyClass.text_method
是位于 MyClass 命名空间内的简单函数,可以直接调用。
在 Python 3 中仍然使用staticmethod
的主要原因是您是否还想在实例上调用该方法。如果不使用修饰器,该方法将始终作为第一个参数传递实例,从而导致 TypeError。
这没有什么特别的。在 python 3 中,类内定义的函数和类外定义的函数之间没有区别。两者都是正常功能。
您在这里谈论的self
或可能cls
仅在通过实例访问函数时才会出现。因此,在这里您没有收到任何错误。
但是,如果您稍微修改代码以如下所示,则会收到预期的错误。
def main(args):
MyClass().test_method(args)
# Should throw an error
编辑:
@staticmethod
将适用于两个类实例(如MyClass().test_method(args)
(和常规直接调用(如MyClass.test_method(args)
- 但是,常规方法(不含
self
(不能在类实例上调用。所以你总是必须称它为MyClass.test_method(args)
不一定需要self
。但是,如果你想引用与对象(类的实例化(关联的任何变量或值(例如,对于一个关于汽车的类,它是speed,self.speed(,你需要self
作为函数中的参数。出于这个原因,通常的做法是始终将 self 作为参数,否则您并没有真正出于正确的原因使用类。
编辑: 如果您执行以下操作,这实际上会引发错误:
class a():
def __init__(self, x):
self.asd = x
def hello(x):
print(x)
>>> g = a(4)
>>> g.hello(5)
与调用"hello"时一样,"self"和"4"都将作为参数传递。它将在以下情况下工作,这就是我上面所说的:
>>> g = a
>>> g.hello(4)
或
>>> a.hello(4)
要在此处添加现有答案并提供代码示例,请执行以下操作:
class MyClass:
def __init__(self):
pass
def myStaticMethod():
print("a static method")
@staticmethod
def myStaticMethodWithArg(my_arg):
print(my_arg)
print("a static method")
MyClass.myStaticMethod()
MyClass.myStaticMethodWithArg("skhsdkj")
abc = MyClass()
abc.myStaticMethodWithArg("avc")
尝试删除@staticmethod
装饰器并重新运行代码,看看会发生什么!(最后一次调用将失败,因为该方法在self
和字符串输入中传递。通过添加装饰器,我们可以指导解释器执行我们想要的动作(