为什么在没有”self”和没有decorator的情况下声明python类的方法不会引发异常?

Why is a method of a Python class declared without “self” and without decorators not raising an exception?

我认为下面的代码会导致一个错误,因为据我所读,python类中的一个方法的第一个参数必须是"self"(或任何其他标签,但按照惯例是"self"),或者如果使用@classmethod修饰器,则必须是"cls"或类似的,或者如果使用@staticmethod修饰器,则必须是"none"。

为什么在终端中用python 3.5运行这个命令不会出错,即使test_method不满足这些要求?它作为一个静态方法似乎工作得很好,但是没有修饰器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/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))

输出:

1
2
$ python3 testscript.py"testing"
$ testing

编辑:

我的问题也可以用不同的措词,把注意力从self@staticmethod上移开:"没有@static method修饰器,我怎么会得到一个看似有效的静态方法?"


这没什么特别的。在Python3中,在类内定义的函数和在类外定义的函数之间没有区别。它们都是正常功能。

您在这里谈论的self,或者可能只有通过实例访问函数时,cls才会出现。所以在这里你没有得到任何错误。

但是,如果您将代码稍微修改一下,使其看起来像下面这样,那么您将得到一个您所期望的错误。

1
2
3
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)


在python2中,类体中定义的函数会自动转换为"未绑定方法",没有staticmethod修饰符就不能直接调用。在python3中,这个概念被删除了;MyClass.text_method是一个简单的函数,它位于myclass名称空间内,可以直接调用。

在python3中仍然使用staticmethod的主要原因是如果您还想在实例上调用该方法。如果不使用decorator,该方法将始终作为第一个参数传递给实例,从而导致类型错误。


不需要self。但是,如果要引用与对象相关的任何变量或值(类的实例化)(例如,对于关于汽车的类,它是速度,self.speed),则需要在函数中使用self作为参数。出于这个原因,通常的做法是将self作为一个参数,否则您实际上并没有出于正确的原因使用类。

编辑:如果您执行以下操作,这实际上会引发一个错误:

1
2
3
4
5
6
7
8
class a():
    def __init__(self, x):
        self.asd = x
    def hello(x):
        print(x)

>>> g = a(4)
>>> g.hello(5)

当调用"hello"时,"self"和"4"都将作为参数传递。它可以在以下情况下工作,这就是我上面所说的:

1
2
>>> g = a
>>> g.hello(4)

1
>>> a.hello(4)