就像
str
,int
,和dict
一样,函数在Python中也是对象,掌握了这个特点可以写出更多灵活的代码
你大概已经听过,Python作为一种流行的面向对象语言,所有的都是对象。当我们谈到对象,经常是把对象指向一种数据集合,通常是作为属性,这个对象是某些预先定义好的函数,可以用于更新数据或者与其他对象交换数据。
数据类型
所有的数据类型例如数值,字符串,列表,字典在Python中都是对象。用一个实际的例子,你可以把他想象成实实在在的数据盒子。在大小方面,有些盒子较小比如int
,bool
和str
类型的数据,另外一些盒子比较大如list
和dict
,他们的大小差别表现在计算机需要多少内存存储这些数据。除此之外,这些盒子还有其他的特征,例如颜色和材质,你可以把这些联想成他们的数据类型不同。
作为对象他们都有以下通用的含义和功能:
- 可以赋值给变量
- 可以作为函数的参数
- 可以作为函数的返回值
- 与别的对象关联,并作为其中的一部分
# 赋值给变量
a = 5
# 作为函数的参数
def add_two(a):
return a + 2
add_two(6)
# 作为函数的返回值
def is_even(a):
return 'even' if a % 2 == 0 else 'odd'
is_even(745)
# 与别的对象关联,并作为其中的一部分
(True, 7, 8)
在上面的代码中,你看到了Python对象的这些含义,比如int
和string
。甚至你不太清楚Python代码或者其他编程语言,理解起来也不是很难对吧?
然而有人说函数也可以作为对象,这点可能会有些疑惑。接下来我们一起看看为什么这么说。
函数作为对象
在我们开始讨论函数作为对象之前,让我们回顾一下函数是什么?函数是一个命名的代码块,需要0个或多个输入参数,运行以后会返回输出值。
下面有一个简单的例子,组成函数的部分高亮出来了。
# 定义一个函数名为 add_two
# 函数需要一个整数作为参数
def add_two(a):
# 这个函数把2加到输入参数上
b = a + 2
# 函数返回求和作为输出
return b
在上面文中,我们提到的Python数据对象的四个通用的功能,我将用几个例子一一说明函数如何具备这些功能。
赋值给变量
在下面代码中,我创建了一个叫greeting()
的函数,赋值给变量say_hello
,调用say_hello
的输出与greeting
输出一样。
def greeting(name):
hello = 'Hello, ' + name + '!'
return hello
print(greeting('John'))
# Hello, John!
say_hello = greeting
say_hello('Mike')
# Hello, Mike!
greeting
和say_hello
在内存中指向相同的对象。例如,如果你检查他们的地址,他们会有相同的输出。如果我们删除函数greeting()
,这个greeting
指向的函数将变成未定义,而删除操作并不会影响say_hello
函数。因此,一个重要的概念是指向函数的变量和实际存储在内存中的对象是不同的。
print(id(greeting))
# 4606507480
print(id(say_hello))
# 4606507480
del greeting
say_hello('Jennifer')
# Hello, Jennifer
greeting('Rachel')
# NameError: name 'greeting' is not defined
把函数作为另外函数的参数
由于函数是一个对象,我们可以把函数作为另一个函数的参数。下面的例子,我创建了3个函数:combine_two_numbers()
, add_two_numbers()
, multiply_two_numbers()
,后面两个函数分别是求和和求积,第一个函数combine_two_numbers()
与你通常见到的函数不同,这个函数接受一个函数和一个元组作为参数。在下面的例子中你可以发现,我们将add_two_numbers
, multiply_two_numbers
作为参数,分别计算这个数组的和与乘积。
def combine_two_numbers(how_to, numbers):
return how_to(numbers)
def add_two_numbers(numbers):
a, b = numbers
return a + b
def multiply_two_numbers(numbers):
a, b = numbers
return a * b
combine_two_numbers(add_two_numbers, (3, 5))
# 8
combine_two_numbers(multiply_two_numbers, (4, 6))
# 24
函数作为返回值
另外一个有意思的特点就是,Python函数可以作为另外函数的返回值。让我们看下面的例子。我写了一个函数add_number_creator()
,他返回一个函数,这个函数是把一个数加到一个整型参数上。两个函数add_three()
和add_five()
被这个函数add_number_creator()
创建出来。这两个函数分别把3和5加到整型参数上。
def add_number_creator(number):
def add_number(a):
return a + number
return add_number
add_three = add_number_creator(3)
add_five = add_number_creator(5)
add_three(5)
# 8
add_five(100)
# 105
函数组成别的对象
由于函数是一个对象,我们可以创建一个函数列表,所有函数变成列表对象中的元素。接着上面的例子,我们用add_number_creator()
创建3个函数,把0,1,2加到整型变量上。你可以看到我们可以遍历列表中的函数,就像操作列表中整数或字符一样。
add_functions = [add_number_creator(0), add_number_creator(1), add_number_creator(2)]
for i, func in enumerate(add_functions):
a = 8
print('a is 8, adding '+ str(i) + ' is' + str(func(a)))
# a is 8, adding 0 is 8
# a is 8, adding 1 is 9
# a is 8, adding 2 is 10
总结
这篇文章告诉你,在Python中函数就像别的对象一样,既可以赋值给变量也可以用于函数中。上文中一些简单的例子说明了这个问题,如果你碰到更多复杂的情况,你可以应用相同的规则,把函数当成普通的对象在你的Python代码中使用。
大家可以关注我的微信公众号:数学编程
原文:Everything Is an Object in Python — Learn to Use Functions as Objects
注:本文是作者第一篇译文,鉴于作者英文水平欠缺,文中多处翻译不太流畅,请见谅