代码之家  ›  专栏  ›  技术社区  ›  Lone Learner

staticmethod()有什么魔力,使得静态方法总是在没有实例参数的情况下被调用?

  •  6
  • Lone Learner  · 技术社区  · 11 年前

    我试图了解静态方法是如何在内部工作的。我知道如何使用 @staticmethod decorator,但我将避免在本文中使用它,以便深入了解静态方法的工作原理并提出问题。

    根据我对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代码中,我该如何做?甚至可以从我们自己的Python代码中定义这样的方法吗,或者这样的函数只能定义为内置函数?

    2 回复  |  直到 9 年前
        1
  •  9
  •   Bakuriu    11 年前

    它作为 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'>
    
        2
  •  5
  •   user2357112    11 年前

    方法(包括实例、静态和类方法)通过 descriptor protocol 。如果类dict中的对象实现 __get__ 特殊方法:

    class Descriptor(object):
        def __get__(self, instance, klass):
            return instance, klass
    
    class HasDescriptor(object):
        descriptor = Descriptor()
    
    x = HasDescriptor()
    

    则访问以下属性:

    x.descriptor
    HasDescriptor.descriptor
    

    将调用描述符的 __获取__ 计算其值的方法,如下所示:

    descriptor.__get__(x, HasDescriptor)
    descriptor.__get__(None, HasDescriptor)
    

    功能, staticmethod classmethod 所有机具 __获取__ 以使方法访问工作。你也可以这样做:

    class MyStaticMethod(object):
        def __init__(self, f):
            self.f = f
        def __get__(self, instance, klass):
            return self.f
    

    还有 __set__ __delete__ 方法,分别允许您控制设置和删除属性。方法不使用这些,但是 property