是Python吗;“功能对象”;功能?

是Python吗;“功能对象”;功能?,python,python-2.7,function,callable,descriptor,Python,Python 2.7,Function,Callable,Descriptor,我们都知道函数也是对象。但是函数对象与函数相比如何呢?函数对象和函数之间有什么区别 所谓函数对象,我指的是这样定义的g: class G(object): def __call__(self, a): pass g = G() 我所说的功能是指: def f(a): pass 使用def语句或lambda表达式时,Python会为您创建函数对象: >>> def foo(): pass ... >>> foo <fu

我们都知道函数也是对象。但是函数对象与函数相比如何呢?函数对象和函数之间有什么区别

所谓函数对象,我指的是这样定义的g:

class G(object):
    def __call__(self, a):
        pass
g = G()
我所说的功能是指:

def f(a):
    pass

使用def语句或lambda表达式时,Python会为您创建函数对象:

>>> def foo(): pass
... 
>>> foo
<function foo at 0x106aafd70>
>>> lambda: None
<function <lambda> at 0x106d90668>
>>def foo():通过
... 
>>>福
>>>兰姆达:没有

因此,无论何时在python中定义函数,都会创建这样的对象。没有简单的函数定义方式。

TL;DR任何实现
的对象都可以调用,例如:函数、自定义类等

稍长的版本:(walloftext)

关于差异的完整答案在python虚拟机的实现中,因此我们必须了解一下python。首先是代码对象的概念。Python将您抛出的任何东西解析为它自己的内部语言,这种语言在所有平台上都是相同的,称为字节码。这方面的一个非常直观的表示是,在导入您编写的自定义库之后,您将获得一个.pyc文件。这些是python虚拟机的原始指令。忽略这些指令是如何从源代码中创建的,然后由Python/ceval.c中的
PyEval\u EvalFrameEx
执行。源代码有点像野兽,但最终工作起来就像一个简单的处理器,其中一些复杂的部分被抽象掉了。字节码是该处理器的汇编语言。特别地,这个“处理器”的一个“操作码”是(恰当地命名)
CALL\u函数
。回调经过多次调用,最终到达
PyObject\u Call()
。此函数获取指向
PyObject
的指针,并从其类型中提取属性并直接调用它(从技术上讲,它会检查它是否首先存在):

。。。
call=func->ob\u type->tp\u call//func是PyObject\u call()的参数,是指向PyObject的指针
...
结果=(*调用)(func,arg,kw);
任何实现
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
的对象都会被赋予一个
tp\u call
属性,该属性带有一个指向实际函数的指针。我相信这是由Objects/typeobject.c的
slotdefs[]
定义处理的:

cpython实现中定义了函数的
\uuuu调用
方法本身,它定义了python VM应该如何开始执行该函数的字节码,以及应该如何返回数据(如果有)。当你给一个任意类一个
\uuuuu调用
方法时,该属性是一个函数对象,它再次引用
\uuu调用的cpython实现。因此,当您调用“正常”函数
foo时,会引用\uu call\uu
。当您调用一个可调用的类时,
self.\uu调用
相当于
foo
,而实际调用的cpython引用是
self.\uu调用.\uu调用.\im\u函数。\uu调用

免责声明


对我来说,这是一段进入未知领域的旅程,我完全有可能曲解了实现的一些细节。我主要是从关于python可调用函数如何在引擎盖下工作的博客文章中,以及我自己在python中的一些挖掘

你说的“普通函数”是什么意思?请举例说明您认为函数对象和函数是什么。这就像询问Python中普通的
int
对象和
int
对象之间的区别一样。。。没有简单的
int
s.@MikeMüller我编辑了这个问题,解释了我对函数对象和函数的理解。谢谢你提出了一个更清楚的问题。在OP澄清了他的问题后,这似乎无关紧要。“函数”对象是否具有属性“set”?属性“get”呢?你没有回答我的问题。谢谢你有趣的回答。实际上,我想知道高级语言的更多特性,比如为什么“function”对象没有属性“set”和“get”。但是我发现你在回答中提供的信息也很有趣。函数确实实现了
\uuuuu get\uuuuu
,它返回文本“”,使用getter和setter应用于类的单个属性而不是类本身更为常见。此外,函数也不会从基本对象类继承,其目的是如果您想要自定义行为,可以使用类来实现它。从技术上讲,您可以创建自己的函数类,但这将非常缓慢且相当复杂。通过不从基本对象类继承,python可以运行它的c代码来管理代码对象的调用
FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call,
       "__call__($self, /, *args, **kwargs)\n--\n\nCall self as a function.",
       PyWrapperFlag_KEYWORDS)