在最近的Python学习 课程中,了解到Python的一些很奇妙的特性,分享 一个印象深刻的例子:
先看一段代码:
def add(a,b):
return a + b
x = add
print(x(1,2))
输出的结果为:3
新手看到这里或许会感到疑问,add 是个自定义的函数名, x 按理来说是个变量名,但在
x = add
print(x(1,2))
中,为什么 x 似乎已经取代了 add,变为了函数名呢?而且还吸收了它的本领(难道是传说中的吸星大法?)难道函数名也可以赋值,江山就这样易主了?
哈哈,没错,在python中,函数是可以赋值给变量的,而且变量也会喧宾夺主,继承函数的功能.
那么问题又来了,这样做又有什么意义呢?好玩?(虽然很炫酷,但真的很酷炫)
下面我们来看个应用:
#冒泡排序
ls = [5,3,11,1,7,9]
print(ls)
def sort(ls:list):
for i in range(len(ls)-1):
for j in range(len(ls)-i-1):
if ls[j] > ls[j+1]: #此处当ls[j] > ls[j+1]时,会交换位置,从而实现从小到大排列
temp = ls[j]
ls[j] = ls[j+1]
ls[j+1] = temp
sort(ls)
print(ls)
先写了个冒泡排序,实现列表中数据从小到大排列,我们知道,是:
if ls[j] > ls[j+1]:
条件控制着排列顺序,若’>‘变为’<'号,ls中的数据会变为从大到小排列,如果后续我们想要实现既能从大到小又能从小到大排列,那就必须把这段代码写两遍,是不是太麻烦了。
这里,我们做出一些改变:
#冒泡排序
ls = [5,3,11,1,7,9]
print(ls)
def sort(ls:list,cmp):
for i in range(len(ls)-1):
for j in range(len(ls)-i-1):
if cmp(ls[j], ls[j+1]): #此处当ls[j] > ls[j+1]时,会交换位置,从而实现从小到大排列
temp = ls[j]
ls[j] = ls[j+1]
ls[j+1] = temp
#添加一个比较函数
def bigger(s1,s2):
return s1 > s2
sort(ls,bigger)
print(ls)
我们发现,与上一段代码相比,我增加了一个简短的bigger函数,并改变了一下sort函数的参数个数,然后将之前的比较条件以调用函数的方式进行替换,同样也实现了从小到大的排列,有没有很神奇。
我们来捋一捋到底发生了什么,我们先将改变了sort函数的参数个数,增加了一个cmp参数(这里取compair)的含义,然后将控制排列顺序的部分替换为了函数调用的形式,cmp(arg1,arg2),那么cmp是函数吗?
我们再看看sort被调用时的情况
def bigger(s1,s2):
return s1 > s2
sort(ls,bigger)
嗯,传入sort的一个实参的确是一个函数名bigger,那么,调用时就是这个意思:
cmp = biiger
唉,有没有想起啥?没错,开篇里 x = add,不也是这样吗,同样的,cmp 也继承了bigger的函数功能,从而比较出了 ls[j] 和 ls[j+1]的大小,并以bool类型的值回传到被调用处,从而实现了控制列表从小到大排列的功能。
同理,如果我们想要实现列表从大到小排列,那么我们只需再写一个smaller函数,然后在调用sort时传入smaller函数名即可实现,代码我想留给大家试一下,就不写了。(\调皮)