在Python中,函数是第一类对象吗?
我正在学习一个关于Python的教程。这个教程在解释Python中的函数是“第一类对象”。
def foo():
pass
print(foo.__class__)
print(issubclass(foo.__class__,object))
我运行上面的代码得到的输出是
<type 'function'>
True
这个程序是用来展示Python中的函数是第一类对象吗?我有以下几个问题。
- 上面的代码是怎么证明函数是第一类对象的?
- 第一类对象有什么特点?
function.__class__
是什么意思?它返回一个元组<type,function>
,这有什么用呢?
5 个回答
关于你对 @I.K. 的回答的评论,下面的 f_at_2()
就是一个 方法。
def f_at_2(f):
return f(2)
def foo(n):
return n ** n
def bar(n):
return n * n
def baz(n):
return n / 2
funcs = [foo, bar, baz]
for f in funcs:
print f.func_name, f_at_2(f)
...
>>>
foo 4
bar 4
baz 1
>>>
方法其实就是一个类里面的函数,但这个概念也可以用在类外的函数上。函数(作为对象)被放在一个数据结构里,然后传递给另一个对象。
关于你的第三个问题,<type 'function'>
其实不是一个元组。Python 中元组的写法是 (a,b)
,而不是用尖括号。
foo.__class__
返回的是一个类对象,也就是说,它表示的是 foo
所属于的类。类对象在解释器中会显示一些描述性的信息,这里告诉你 foo
的类是叫 'function'
的 type
。在现代 Python 中,类和类型基本上是一样的。
除此之外,这并没有太多其他的意思,就像其他对象一样,函数也有一个类型:
>>> x = 1
>>> x.__class__
<type 'int'>
>>> y = "bar"
>>> y.__class__
<type 'str'>
>>> def foo(): pass
...
>>> foo.__class__
<type 'function'>
你证明了函数是第一类对象,因为你可以把foo
当作参数传给一个方法。
第一类对象的特点在这篇文章中总结得很好:https://stackoverflow.com/a/245208/3248346
根据不同的编程语言,这可能意味着:
- 可以用一个匿名的字面值表示
- 可以存储在变量中
- 可以存储在数据结构中
- 有一个内在的身份(不依赖于任何给定的名称)
- 可以和其他对象进行相等比较
- 可以作为参数传递给过程或函数
- 可以作为过程或函数的返回结果
- 可以在运行时构造
- 可以被打印出来
- 可以被读取
- 可以在分布式进程之间传输
- 可以存储在运行进程之外
一等公民这个词简单来说就是函数可以像普通的值一样被使用——也就是说,你可以把它们赋值给变量,可以从其他函数中返回它们,还可以把它们当作参数传递。这意味着你可以写出这样的代码:
>>> def say_hi():
print "hi"
>>> def say_bye():
print "bye"
>>> f = say_hi
>>> f()
hi
>>> f = say_bye
>>> f()
bye
这很有用,因为你现在可以像使用普通变量一样,把函数赋值给变量:
>>> for f in (say_hi, say_bye):
f()
hi
bye
或者写一些高阶函数(也就是那些可以接收函数作为参数的函数):
>>> def call_func_n_times(f, n):
for i in range(n):
f()
>>> call_func_n_times(say_hi, 3)
hi
hi
hi
>>> call_func_n_times(say_bye, 2)
bye
bye
在Python中,__class__
可以告诉你你所拥有的对象是什么类型。例如,如果你在Python中定义了一个列表对象:a = [1,2,3]
,那么a.__class__
的结果将是<type 'list'>
。如果你有一个日期时间对象(通过from datetime import datetime
导入,然后d = datetime.now()
),那么d
这个实例的类型将是<type 'datetime.datetime'>
。他们只是想说明在Python中,函数并不是一个全新的概念。它只是一个普通的对象,类型是<type 'function'>
。
这是Guido在他的博客中关于“第一类对象”的说法:
我设计Python的一个目标就是让所有对象都成为“第一类”。我的意思是,我希望在这个语言中所有可以被命名的对象(比如整数、字符串、函数、类、模块、方法等等)都享有同等的地位。也就是说,它们可以被赋值给变量,可以放在列表中,可以存储在字典里,可以作为参数传递,等等。
这篇博客文章值得一读。
在你发布的例子中,教程可能想表达的是,第一类对象通常是“对象”类的子类。