为什么在没有 "self" 且没有装饰器的情况下声明 Python class 的方法不会引发异常?
Why is a method of a Python class declared without "self" and without decorators not raising an exception?
我认为以下代码会导致错误,因为据我所知,Python class 中的方法必须具有 "self"(或任何其他标签,但按照惯例 "self")作为它的第一个参数,或者如果使用 @classmethod
装饰器则为 "cls" 或类似的,或者如果使用 @staticmethod
装饰器则为 none用过。
为什么我在终端中使用 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
:"How come I'm getting a seemingly working static method without the @staticmethod decorator?"
self
不一定是必需的。但是,如果您想引用与对象关联的任何变量或值(class 的实例化)(例如,对于关于汽车的 class,它是速度,self.speed)您您需要将 self
作为函数中的参数。出于这个原因,通常的做法是始终将 self 作为参数,否则您并没有真正出于正确的原因使用 class。
编辑:
如果您执行以下操作,这实际上会引发错误:
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)
这没什么特别的。在 python 3 中,在 class 内部定义的函数与在 class 外部定义的函数没有区别。两者都是正常的功能。
您在这里谈论的 self
或 cls
只有在您通过 实例 访问函数时才会出现。因此在这里你没有得到任何错误。
但是,如果您将代码稍微修改为如下所示,则会收到预期的错误。
def main(args):
MyClass().test_method(args)
# Should throw an error
编辑:
@staticmethod
将适用于 class 实例,如 MyClass().test_method(args)
和常规直接调用,如 MyClass.test_method(args)
- 但是,无法在 class 实例上调用常规方法(其中没有
self
)。所以你总是必须将它称为 MyClass.test_method(args)
在Python2中,定义在class体中的函数会自动转换为"unbound methods",没有staticmethod装饰器不能直接调用。在Python3中,这个概念被去掉了; MyClass.text_method
是一个位于 MyClass 命名空间内的简单函数,可以直接调用。
在 Python 3 中仍然使用 staticmethod
的主要原因是如果您还想在 实例 上调用该方法。如果不使用装饰器,该方法将始终将实例作为第一个参数传递,从而导致 TypeError。
添加到此处的现有答案并提供代码示例:
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
和字符串输入中都被传递。通过添加装饰器,我们可以引导解释器执行我们想要的操作)
我认为以下代码会导致错误,因为据我所知,Python class 中的方法必须具有 "self"(或任何其他标签,但按照惯例 "self")作为它的第一个参数,或者如果使用 @classmethod
装饰器则为 "cls" 或类似的,或者如果使用 @staticmethod
装饰器则为 none用过。
为什么我在终端中使用 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
:"How come I'm getting a seemingly working static method without the @staticmethod decorator?"
self
不一定是必需的。但是,如果您想引用与对象关联的任何变量或值(class 的实例化)(例如,对于关于汽车的 class,它是速度,self.speed)您您需要将 self
作为函数中的参数。出于这个原因,通常的做法是始终将 self 作为参数,否则您并没有真正出于正确的原因使用 class。
编辑: 如果您执行以下操作,这实际上会引发错误:
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)
这没什么特别的。在 python 3 中,在 class 内部定义的函数与在 class 外部定义的函数没有区别。两者都是正常的功能。
您在这里谈论的 self
或 cls
只有在您通过 实例 访问函数时才会出现。因此在这里你没有得到任何错误。
但是,如果您将代码稍微修改为如下所示,则会收到预期的错误。
def main(args):
MyClass().test_method(args)
# Should throw an error
编辑:
@staticmethod
将适用于 class 实例,如MyClass().test_method(args)
和常规直接调用,如MyClass.test_method(args)
- 但是,无法在 class 实例上调用常规方法(其中没有
self
)。所以你总是必须将它称为MyClass.test_method(args)
在Python2中,定义在class体中的函数会自动转换为"unbound methods",没有staticmethod装饰器不能直接调用。在Python3中,这个概念被去掉了; MyClass.text_method
是一个位于 MyClass 命名空间内的简单函数,可以直接调用。
在 Python 3 中仍然使用 staticmethod
的主要原因是如果您还想在 实例 上调用该方法。如果不使用装饰器,该方法将始终将实例作为第一个参数传递,从而导致 TypeError。
添加到此处的现有答案并提供代码示例:
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
和字符串输入中都被传递。通过添加装饰器,我们可以引导解释器执行我们想要的操作)