我试图了解静态方法在内部如何工作。我知道如何使用@staticmethod装饰器,但在本文中我将避免使用它,以便更深入地研究静态方法的工作方式并提出我的问题。

据我对Python的了解,如果存在一类A,那么调用A.foo()会调用无参数的foo(),而调用A().foo()会调用一个参数的foo(),其中一个参数是实例A()本身。

但是,对于静态方法,无论我们将其称为foo()还是A.foo(),似乎总是在不带参数的情况下调用A().foo()

下面的证明:

>>> class A:
...     x = 'hi'
...     def foo():
...         print('hello, world')
...     bar = staticmethod(foo)
...
>>> A.bar()
hello, world
>>> A().bar()
hello, world
>>> A.bar
<function A.foo at 0x00000000005927B8>
>>> A().bar
<function A.foo at 0x00000000005927B8>
>>> A.bar(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes 0 positional arguments but 1 was given
>>> A().bar(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes 0 positional arguments but 1 was given

因此,我是否可以得出结论,staticmethod()函数确实具有一定的魔力,使得foo()始终使用0个参数来调用?

如果要在自己的Python代码中定义自己的staticmethod(),该怎么办?甚至有可能通过我们自己的Python代码来定义这种方法,还是只能将这种函数定义为内置函数?

最佳答案

它实现为descriptor。例如:

In [1]: class MyStaticMethod(object):
   ...:     def __init__(self, func):
   ...:         self._func = func
   ...:     def __get__(self, inst, cls):
   ...:         return self._func
   ...:

In [2]: class A(object):
   ...:     @MyStaticMethod
   ...:     def foo():
   ...:         print('Hello, World!')
   ...:

In [3]: A.foo()
Hello, World!

In [4]: A().foo()
Hello, World!

以相同的方式,您可以定义classmethod,只需将cls传递给原始函数即可:
In [5]: from functools import partial
   ...:
   ...: class MyClassMethod(object):
   ...:     def __init__(self, func):
   ...:         self._func = func
   ...:     def __get__(self, inst, cls):
   ...:         return partial(self._func, cls)

In [6]: class A(object):
   ...:     @MyClassMethod
   ...:     def foo(cls):
   ...:         print('In class: {}'.format(cls))
   ...:

In [7]: A.foo()
In class: <class '__main__.A'>

In [8]: A().foo()
In class: <class '__main__.A'>

关于python - staticmethod()的作用是什么,所以总是在没有实例参数的情况下调用static方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22294450/

10-14 09:10