【问题标题】:Which is more fundamental: Python functions or Python object-methods?哪个更基础:Python 函数还是 Python 对象方法?
【发布时间】:2010-12-31 10:25:46
【问题描述】:

我试图从概念上理解 Python 函数和方法的性质。我知道函数实际上是对象,具有在执行函数时调用的方法。但是那个函数对象方法实际上是另一个函数吗?

例如:

def fred():
    pass

如果我查看dir(fred),我发现它有一个名为__call__ 的属性。但是dir(fred.__call__) 有一个名为__call__ 的属性。 fred.__call__.__call__ 等等也是如此。 __call__ 对象链的 id 表明它们都是不同的。他们真的反对还是解释器的一些低级技巧?

哪个更基本:函数还是对象方法?

【问题讨论】:

  • 调用对象的 id 表明它们是按要求生成的:有时我看到不同级别的重复项,有时我看到同一级别的不同 id。

标签: python function object


【解决方案1】:

不是专门的 Python 答案,但在最低级别,处理器只理解动作和变量。从中我们推断出函数,并从变量和函数中推断出对象。所以从底层编程的角度来看,我会说更基本的东西是函数。

Python 意义上的 Python 不一定如此,这可能是一个很好的例子,说明为什么作为用户深入研究该语言的实现并不总是有益的。 :) 将函数视为对象当然是 Python 本身更好的答案。

起初我以为您的调用是跟踪到 Python 库中的,但 .call 方法与任何其他方法具有相同的属性。因此,我认为,在使用 python CLI 玩了几分钟后,它正在递归地探索自己;我认为这是探索架构的一种痛苦方式,虽然不一定是一个错误,但它是 Python 如何处理幕后对象的属性。 :)

【讨论】:

    【解决方案2】:

    更基础的是:函数 还是对象方法?

    我认为最好的答案可能是“都不是”。请参阅 Python 参考的 Execution model 部分,其中它指的是“块”。这就是实际执行的内容。 __call__ 你在无限搜索结束时被挂断的东西只是一个知道如何执行代码块的包装器(请参阅函数的各种 func_xxx 属性,实际字节码存储为func_code)。

    同样相关的是 Function definitions 部分,它指的是“一个函数对象 [being](函数的可执行代码的包装器)”。最后,还有callable 一词,它也可能是对“哪个更基本?”的回答

    【讨论】:

      【解决方案3】:

      简短回答:两者都是基础,.__call__() 函数只是一个虚拟技巧。


      这个答案的其余部分有点复杂。你不必理解它,但我觉得这个主题很有趣。请注意,我将提出一系列谎言,并逐步修正它们。

      长答案

      在最基本的层面上,Python 可以说只有 2 个操作:

      • 属性访问:obj.attr
      • 函数调用:callable(args)

      方法调用 - obj.method(args) - 不是基本的。它们包括两个步骤:获取属性obj.method(它提供了一个可调用的“绑定方法”对象)并使用args 调用它。

      其他运算符是根据它们定义的。例如。 x + y 尝试 x.__add__(y),如果不起作用则回退到其他类似的组合。

      无限长的答案?

      到目前为止一切顺利。但是调用和属性访问本身也是根据obj.__call__(args)obj.__getattribute__(name)?!?
      是乌龟一路下来吗?!?

      诀窍在于对象上的操作是通过调用其类型的方法来定义的:type(obj).__call__(obj, args)type(obj).__getattribute__(obj, name)。顺便说一句,我骗了你,还有第三个基本操作:

      • 获取对象的类型:type(obj)

      好的,这仍然没有帮助。 type(obj).__call__(...) 仍然涉及属性访问和调用,所以这应该无限继续吗?问题是你最终会遇到 builtin 类型 - 通常是一个函数,objecttype - 对它们而言,属性访问和函数调用 是基础。 p>

      因此,当您调用自定义类的实例时,确实是通过其__call__ 方法实现的。但是它的__call__ 方法可能是一个普通的函数——可以直接调用。谜底结束。

      类似__getattribute__ - 你可以将它提供给你的类define 属性访问,但是类本身从根本上实现属性访问(除非它有一个自定义的元类 )。

      男人面前的帷幕

      那么为什么连一个函数都有fred.__call__ 方法呢?好吧,这只是 Python 用来模糊内置类型和自定义类之间差异的烟雾和镜子。此方法存在于所有可调用对象上,但调用普通函数不必经过它 - 函数基本上是可调用的。

      同样,所有对象都有obj.__getattribute__obj.__class__,但对于内置类型,它只是公开基本操作而不是定义它。

      小字

      第一次声称 Python 有 2 个基本操作实际上完全是谎言。从技术上讲,所有 Python 运算符都有 C 级别的“基本”操作,通过方法公开以保持一致性,自定义类可以通过类似的方法重新定义这些操作。

      但我告诉你的故事可能是真的,它减少了问题的中心:为什么.__call__().__getattribute__() 不是无限递归。

      【讨论】:

        猜你喜欢
        • 2018-07-16
        • 2012-03-24
        • 2020-03-30
        • 1970-01-01
        • 2016-05-17
        • 2022-09-23
        • 2010-12-21
        • 2016-07-16
        • 2015-11-20
        相关资源
        最近更新 更多