深入理解Python函数是第一类对象

Python有一个很重要的特点:万物皆对象。Python函数也是对象,并且称之为第一类对象(first class object)

什么是第一类对象(first class object)

第一类对象的称谓(first class object)并没有严格的术语定义。第一类对象并不一定是面向对象中class的实例,可以理解为实体。一般第一类对象所具有的特性有:

  • 是某类型的实例
  • 可以赋值给变量
  • 可以保存于结构或者容器中
  • 可以作为函数参数
  • 可以作为函数的返回值
  • 可以在运行时创建

例如在C语言中,函数就不能在运行时创建,所以在C语言中函数不是第一类对象。大多数编程语言中整型,字符类型都是第一类对象 第一类对象可以简单理解为:在某编程语言中,如果某一类实体可以像普通实体(如简单类型整型等)被毫无限制的使用,那么该内实体就是第一类对象。

Python函数是对象

下面看一个简单的例子:

>>> def sum(a,b):
...     return a + b
...
>>> sum(1,2)
3

这是一个简单的求和函数,在Python中,函数也是对象,拥有对象模型的三个通用属性:id,type和值,同时像普通对象一样,可以添加属性。

>>> id(sum)
140599725427024
>>> type(sum)
<class 'function'>
>>> sum
<function sum at 0x7fdfecb08950>
>>> sum.version=1
>>> sum.version
1
>>> sum(2,3)
5

可以看到,函数sum是类function的一个实例。

Python函数赋值及放入容器

Python函数作为元素存入容器中也可以赋值给普通变量。

>>> f = sum
>>> f(2,4)
6
>>> l = [f]
>>> l[0](5,5)
10

Python函数作为参数

Python函数可以方便的作为另一个函数的参数。

>>> l = [1, -1, -2]
>>> list(map(abs,l))
[1, 1, 2]

上面的例子中,函数abs就是作为map函数的参数,对列表中每个元素取绝对值。

Python函数作为函数返回值

Python函数可以作为另一个函数的返回值。

>>> def make_add_func(add_num):
...     def func(x):
...             return x + add_num
...     return func
...
>>> add10 = make_add_func(10)
>>> add10(2)
12
>>> add5 = make_add_func(5)
>>> add5(2)
7
>>> add10(2)
12
>>>

上面这个例子也可看到Python函数支持嵌套。

运行时创建Python函数

在上面的例子中,函数add5与函数add10可以认为是在运行时创建的,因为相对简单而且函数功能已经预先规划,严格来说不算是运行时创建函数。

实际上Python可以使用types.FunctionType完全运行时创建函数,有兴趣的读者可以查阅Python文档。

对象作为函数

Python中对象也可以制作成函数,像函数一样使用,即用()调用。这需要再对象中定义一个特别的方法call

>>> class Echo:
...     def __init__(self, s):
...             self.str = s
...     def __call__(self):
...             print(self.str)
...
>>>
>>> h = Echo("Hello, world")
>>> h()
Hello, world
>>>

小结

Python中函数是第一类对象,函数可以赋值给变量、存储在容器中、作为函数参数、作为函数返回值、可以添加属性等。