关于Python的函数的几点特别说明
Python 函数还支持赋值、作为其他函数的参数以及作为其他函数的返回值。
一、Python 允许直接将函数赋值给其它变量
变量可以指向函数,以Python内置的求绝对值的函数abs()为例,调用该函数用以下代码:
>>> abs(-10)
10
但是,如果只写abs呢?
>>> abs
<built-in function abs>
可见,abs(-10)是函数调用,而abs是函数本身。
要获得函数调用结果,我们可以把结果赋值给变量:
>>> x = abs(-10)
>>> x
10
但是,如果把函数本身赋值给变量呢?
>>> f = abs
>>> f
<built-in function abs>
结论:函数本身也可以赋值给变量,即:变量可以指向函数。
如果一个变量指向了一个函数,那么,可否通过该变量来调用这个函数?用代码验证一下:
>>> f = abs
>>> f(-10)
10
成功!说明变量f现在已经指向了abs函数本身。直接调用abs()函数和调用变量f()完全相同。
那么函数名是什么呢?函数名其实就是指向函数的变量!对于abs()这个函数,完全可以把函数名abs看成变量,它指向一个可以计算绝对值的函数!
如果把abs指向其他对象,会有什么情况发生?
>>> abs = 10
>>> abs(-10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
把abs指向10后,就无法通过abs(-10)调用该函数了!因为abs这个变量已经不指向求绝对值函数而是指向一个整数10!
当然实际代码绝对不能这么写,这里是为了说明函数名也是变量。要恢复abs函数,请重启Python交互环境。
注:由于abs函数实际上是定义在__builtin__模块中的,所以要让修改abs变量的指向在其它模块也生效,要用__builtin__.abs = 10。
这样做的效果是,程序中也可以用其他变量来调用该函数,更加灵活。
例1、
def my_def ():
print("正在执行 my_def 函数")
#直接调用 my_def() 函数
my_def()
#先将函数赋值给其他变量
other = my_def
#再如下间接调用 my_def() 函数
other()
这段代码运行结果是:
正在执行 my_def 函数
正在执行 my_def 函数
特别提示:函数名(例如my_def)为该函数的内存地址;函数名 括号(例如my_def ()为调用该函数。
【python中的的fun和fun()的区别:
def fun(x,y):
return x+y
a = fun #【注1】 a等效fun函数的名
print(a(10,20)) # 输出30
b = fun(10,20) #【注2】 b等效fun函数返回的值
print(b) # 输出30
请留意【注1】【注2】处的注释】
例2、
def func (a,b):
return a+b
#直接调用带参函数
print(func(10,20))
print("------------")
#间接调用带参函数的两种用法:
ref1 = func #函数名后不带括号
print(ref1(10,20)) #
ref2 = func(10,20) #函数名后带括号
print(ref2) #
这段代码运行结果是:
30
------------
30
30
二、在Python中可以将函数当做实参传递给函数。
既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数——函数名也可以作为另一个函数的参数。
一个最简单的高阶函数:
def add(x, y, f):
return f(x) + f(y)
当我们调用add(-5, 6, abs)时,参数x,y和f分别接收-5,6和abs,根据函数定义,我们可以推导计算过程为:
x = -5
y = 6
f = abs
f(x) + f(y) ==> abs(-5) + abs(6) ==> 11
return 11
用代码验证一下:
>>> add(-5, 6, abs)
11
再举几个函数名作为另一个函数的参数的例子
例1:
import time
def test():
time.sleep(1.5)
print("test is running!")
def deco(func):
start = time.time()
func() #【注2】
stop = time.time()
print(stop-start)
deco(test) #【注1】,将test函数作为另一个函数deco的形参
说明:
在【注1】处,我们把test函数当作实参传递给deco函数的形参func,即func=test。注意,这里传递的是地址,也就是此时func也指向了之前test所定义的那个函数体,可以说在deco()内部,func就是test。在【注2】处,把函数名后面加上括号,就是对函数的调用(执行它)。因此,这段代码运行结果是:
test is running!
1.5655810832977295
例2:
def add(x, y):
return x + y
def sub(x, y):
return x - y
def apply(func, x, y): #【注1】
return func(x, y) #【注2】
print(apply(add, 2, 1)) #【注3】
print(apply(sub, 2, 1))
说明:
add 和 sub 是自定义的 Python 函数,都是接受两个值并返回一个计算的值。在【注1】 处可以看到变量接收一个就像其他普通变量一样的函数。在 【注2】 处调用了传递给 apply 的函数 func——在 Python 中双括号是调用操作符,调用变量名包含的值。在 【注3】 处展示了在 Python 中把函数作为值传参并没有特别的语法——和其他变量一样。这段代码运行结果是:
30
10
三、在Python中,可以在函数中将函数作为返回值返回
将函数作为值返回的例子
例1、
def bar():
print("in the bar.")
def foo(func):
print("in the foo.")
return bar
res=foo(bar)
res()
这段代码运行结果是:
in the foo.
in the bar.
例2、
def func(x):
def func1(y):
return x + y
return func1
test = func(4)
tes1 = test(5)
print(tes1)
这段代码运行结果是:
9
高阶函数(higher-order function):接受函数为参数,或者把函数作为结果返回的函数是高阶函数。换句话说,一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。
四、、python中函数必须先定义、后调用,函数调用函数例外。
详见 https://blog.csdn.net/couragehope/article/details/83031932