【问题标题】:Do "static method object" and "class method object" not have "callable types"?“静态方法对象”和“类方法对象”没有“可调用类型”吗?
【发布时间】:2017-09-15 15:45:57
【问题描述】:

Python Language Reference, Chapter 3 Datamodel, 为什么“可调用类型”下列出了“实例方法”,而“内部类型”下列出了“静态方法对象”和“类方法对象”?

可调用类型 这些是可以应用函数调用操作(参见调用部分)的类型 ...

实例方法 ...

内部类型 解释器内部使用的一些类型会暴露给用户。他们的定义可能会改变 解释器的未来版本,但为了完整起见,这里提到它们。 ...

静态方法对象 ...

类方法对象 ...

静态和类方法对象不应该也是可调用类型吗?

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    不,staticmethod's 和 classmethods 不可调用,no rationale to do so was found

    >>> def foo():
    ...     print("hello") 
    >>> s = staticmethod(foo)
    >>> s()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'staticmethod' object is not callable
    

    它们旨在通过描述符协议调用,并且(通常)返回一个可调用对象:

    >>> s.__get__(foo)()
    hello
    

    不过,这不是最常见的形式。通常在属性访问时会自动调用描述符,as the descriptor how-to states:

    描述符可以通过其方法名直接调用。例如,d.__get__(obj)

    另外,更常见的是在属性访问时自动调用描述符。例如,obj.dobj 的字典中查找d。如果d 定义了__get__() 方法,那么d.__get__(obj) 将根据下面列出的优先规则被调用。

    【讨论】:

    • 谢谢。类的普通方法(即既不是静态方法也不是类方法的类的方法)是否可以调用?
    • 在什么情况下静态和类方法不用作类的属性?
    • 是的@Tim,他们是。函数是__get__ 方法返回方法的描述符,当在类中使用并执行属性查找时,调用function.__get__ 并返回方法。因此,函数和方法都是可调用的。我还没有看到任何在类外使用static/class 方法的情况,我只是使用了那个例子,因为它更短:-)
    • “函数是描述符”是指在任何类之外用def 定义的函数是描述符吗?例如foo 在您的示例中。
    • @Tim 描述符是定义__get__(也可能是__set__)的任何对象。唯一一次自动调用 __get__ 是描述符是属性查找的结果(MyClass.fooMyClass().foo)。
    【解决方案2】:

    staticmethod 对象不可调用:

    Python 3.5.3 (default, Jan 19 2017, 14:11:04) 
    [GCC 6.3.0 20170118] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> staticmethod(lambda x: print(x))
    <staticmethod object at 0x7f8499f1ebe0>
    >>> meth = staticmethod(lambda: print('static method called'))
    >>> meth()
    Traceback (most recent call last):
    

    但是他们实现了 descriptor 协议方法__get__。然后__get__ 方法返回一个实际的可调用对象。

    File "<stdin>", line 1, in <module>
    TypeError: 'staticmethod' object is not callable
    >>> meth.__get__(object, object())()
    static method called
    

    当您将staticmethod 对象存储到一个class 属性中,然后查找它时,会隐式调用__get__ 方法。

    【讨论】:

    • 文档中的相关引用:“静态方法对象本身不可调用,尽管它们通常包装的对象是。”
    猜你喜欢
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    相关资源
    最近更新 更多