00:00
好,接下来我们来进入到我们下一个知识点啊,还是说我们这个函数啊,那在这里我们先说一句话啊,在我们的Python中,函数是一等对象啊,一等对象,那什么叫一等对象?那我们说了一等对象会有这么一些特点啊,第一个对象是在运行时创建的啊,那这不用废话了,拍子里面所有对象都是这样的,对吧?程序在运行的时候这个对象才创建,那除了运行式创建对比的,还有一个叫什么呀?叫编译式创建,有一种语言,它那些呃,可能函数啊,那些类,那些对象是在编译的时候就已经创建好了,而在我们Python里边它是什么呀?它是在运行时创建的啊,代码在执行的时候才会创建对象啊,然后第二,一个能赋值给变量或作为数据结构中的元素,比如说我的这个函数,我这个对象能赋值给一个变量,或者我能把它存到一个列表,或者存到一个字典当中,这个我们函数是不是都可以啊?哎,第三一个能作为参数传递啊,能把这个函数作为参数传递,之前也说过。
01:00
啊,任何对象是不是都可以作为参数,哎,作为参数,然后最后一个能作为返回值返回,这个之前演示过了,我们返回值也可以是一个函数,那凡是具有如下这四个特点的,它都是什么呀?一等对象啊,都是一等对象,那所以其实你看到这儿你也就会发现了,其实在我们Python当中,所有的对象是不是都具有这些特点,哎,所以实际上Python当中所有对象都是一等对象,但是所有对象都是一等对象,也并没有什么特殊的,那特殊的是什么呢?函数也是一等对象,那注意了,并不是所有的语言当中函数都是一等对象啊,而是什么呀?在patternython中它是啊,在pattern它是,那它是一种对象有什么用?那在函数,在我们的patternython中,函数是一种对象,那也就是意味着在我们的Python中,我们可以通过什么呀?我们可以使用函数式编程,函数式编程就是一种以函数为主的编程方式。说白了就。
02:00
就是把我们的一个一个功能程序当中的一个一个功能分解成一个一个函数,通过函数来执行这个功能,函数式编程我们需要用到什么呀,大量的函数啊,大量的函数,但是pyon它是它支持函数式编程,但是它并不是一个函数式编程语言,哎,就像什么呀,我们说了这个火箭可以飞,但是火箭并不是一个飞机,对吧,它是火箭,虽然它可以飞,但是它也不是飞机,所以Python也是它支持函数式编程,但是它并不是一个函数式编程语言,并且我们这种函数式编程其实也用的不多啊,用的不多,只会很少的情况下会用到,所以这个呢,也主要是了解一下,那函数编程里边最大的一个特点就是什么呢?叫做一个高阶函数,那支持函数式编程的语言都会支持这么一个叫做高阶函数,那什么叫高阶函数,高阶函数至少要符合两两个诶以下两个特点中的一个啊,什么呢?第一个它会接收一个或多个函数作为参数,也为它需要一。
03:00
函数作为参数,第二个它可以干嘛呢?把函数作为返回值返回啊,把函数作为返回值返回,那同学看到这就会懵了,那这高阶函数有什么用呢?我为什么要接收一个函数作为参数呢?而我又为什么要将函数作为返回值返回呢?那这个我们要了解一下了啊来我们在这里新建一个文件保存一下,我们这来零八啊到这个code里,零八我们叫一个高阶函数,点一个PY,这是我们这个零八,好,我们这来说一下高阶函数,再请问一下什么叫高阶函数,哎,接收什么呢?哎,接收函数作为参数或者。哎,将我们这个函数作为返回值的这个函数,哎,是什么呢?是我们这个高级函数啊,两个点满足一个就OK了啊,两个点满足一个就OK了,那我们来说说为什么需要高阶函数,那这里边我们先举个例子啊,在这儿呢,我来创建一个列表啊,创建一个列表,我直接来一个L等于一个中号来什么呢?诶来一个诶来一个123456789,哎,我现在有这么一个列表,再来一个十蜡,诶有这么一个列表。
04:19
那现在我需要什么呢?哎,我这样啊,我需要来定义一个函数啊,相当于一个练习了啊,定义一个函数啊,定义函数这个函数它可以干嘛呢?哎,可以。哎,将我们这个指定,哎列表中的什么呢?哎,列表中的这个所有的偶数啊,所有的偶数保存到一个什么呢?哎,新的列表中返回,新的列表中返回啊,把一个列表当中所有的偶数保存到一个新的表中返回,也就是说现在我这一个L,我希望这个方法干嘛呢?接收这个L作为参数,那我么这L里边是不是有奇数134579,因为偶数二四八十啊,我要干嘛呢?把这里边的偶数全都取出来,取出来以后干嘛呢?放到一个新列表里,然后给我返回,说白了就相当于是不是对我这个列表做一个筛选呀?哎,做个筛选,那这函数我们怎么定义,我们来尝试去定义一下,还是先把函数的结构定义出来,哎,定DeFine,我们来一个FN,那这个FN首先我们来需要一个参数,什么参数呢?我们说啊,是不是要将指定列表中的所有数啊,哎,指定列表那哪个列表啊,那我们这个列表是不是需要作为参数传进来啊,哎,我们这。
05:31
叫一个随便写一个,叫做一个LST啊,一个这个列表,那这个函数我们先写一个什么呀?哎文档字符串先来描述一下这个函数可以什么呢?FN这个函数,哎,它可以将我们什么呢?哎,指定列表中的这个元素啊叫什么呢?哎,偶数元素,哎,嗯,指定列表中的所有偶数,哎,所有数哎获取出来。哎。
06:00
获取出来,哎并什么呢?哎,并保存到一个新列表中返回就这么一个函数功能非常简单,那这里边我们有一个参数,参数我们叫做一个LSTLST是什么呀?诶是要进行我们这个筛选的一个什么呀?哎,筛选的一个列表啊,这是要进行筛选列表,就说你要对这进行筛选,那现在我们这个一步一步来做一下,好,那他说了我们要保存到一个新的列表中返回吧,所以我们第一件事儿,我需要先创建一个什么呢?诶创建一个新列表啊,直接来一个,我们来一个new,诶啊list等于一个中号对吧?那最后是不是肯定也要返回新列表啊,哎,返回我们这个新列表,直接来个return,一个new,一个list,把这列表给你返回,然后在中间我们是不是要对我们这个列表进行筛选啊,哎,对我们这个列表进行筛选,进行筛选,那还是既然要筛选了,毫无疑问我需要便历便利,我直接来一个n in这个LS。
07:01
替我们这个老的列表对吧,对它进行便利,那现在我们在这儿的时候要判断什么呀,我要判断我们这个N的一个什么呀,诶奇偶,我要判断N是奇数还是偶数啊奇偶数。奇数啊,偶数啊,我要判断这个N是奇数还是偶数,那怎么判断呀?哎,非常简单,来一个if n摩以二等等于零,也就是说N能被二整除,那是不是证明N是偶数啊,那既然N是偶数,我们是不是应该把这数放到一个新列表里啊,新列表里,所以在这我们直接来一个new list,点一个a pen aend,谁啊,Aend一个en,这是不是就放进去了?哎,那好,我这还用不用写else了?哎,不用写了,如果它是奇数,我们是不是就不管它了?哎,那这样经过这个循环以后,我们这个新列表里放的全都是什么?哎,全都是偶数,奇数是不是都没放进来?哎,没放进来啊,那我们这个函数就定义完了,那注意了,我们这个函数它会不会影响到原来的变量?哎,很明显这时候是不会的,因为我们这个原来那个对象我们没有改,我们是便利它,然后把取出的元素值放在一个新列表里啊,哎,所以这个时候它是不会影响原列表了,那它影响的是谁?哎,它是不是影响到它是返回值啊,哎,反。
08:15
N值,所以要看它的话,我们只需要看什么,只需要看它的什么呀,返回值,所以在这儿直接调FN传谁呀?哎,是不是把我们L作为参数传进去,哎,直接传一个L这里保存,那这时候我们来看它的结果,走一个二四六八十,是不是取出来所有偶数,这个时候注意我在这儿再单独打印一下L,你会发现L是没有任何影响的,看到了吧,L是没有影响的,它是返回了一个新的列表啊新的列表好,那这个就是我们一个普通的函数,哎,那说了这叫高阶函数吗?很明显不叫,因为我们说了它也没有接收函数作为参数,也没有将函数作为返回值返回,但是这就是这样一个函数,那好了,现在我们来说问题了啊,来说问题了,那现在我是想取所有的。
09:01
偶数,哎,假如我这题变了,我想干嘛呢?我想要所有的奇数。奇数那我就改呗,不等于零不就完了吗?一直行是不是13579啊,哎,13579这确实行了,那我可能想干嘛呢,我这也不想要奇数,也不想要偶数了,我想要它所有的大于五的数,我想要所有大于五的数啊,列表里所有大于五的数怎么办呀,那你就不能写它了,你得写什么呀,你得写一个N大于。五这样一直行,是不是它取出的六七八九十啊,大于五是不是取出来了,对吧,这是可以的,但是这这这我希望什么呢?我最终希望这个东西它既能取出偶数。也能取出奇数,还能取出大于五的数,我希望是这样的。就这一个函数。它具有多个功能。可以取出所有的奇数,可以取出所有的偶数,可以取出所有大于五的数,或者说你还有一些其他的乱七八糟的功能,我希望它都是可以满足的,对吧?我希望它都是可以满足的,那行不行,行不行,诶,那我就想了,这样啊,这样,那现在我们会发现,在这儿我要想往新列表里添加元素,我们要做第一件事,是不是都先判断呀?哎,我先判断它是不是偶数,是偶数就添加对吧?我这先判断它是不是大于五,是大于五就添加对吧,是大于我就添加,那我想想我在这里我能不能专门创建一个函数来检查它是不是偶数,或者来检查它是不是大于五呢?行不行?哎,很明显是可以的,对吧?那所以在这啊,我们在函数内部啊,我们先在函数内部。
10:50
来在这我来干嘛呢?哎,我来定义一个函数啊,当然这个函数我们得往上定义啊,往上定义,因为我们得先定义是不是再使用啊,哎,好,定义一个函数用来干嘛呢?哎,我们来用来检查一个这个诶任意的数字是否偶是偶数,是否是偶数,那这个函数定义起来非常简单啊,我们这是一个内部函数,直接在函数内部来定义,直接de,哎,一个这个F2,我们简单一点了,里边我们传一个参数叫做一个I,也就是说我们去检查这个I是否是偶数,直接if I摩以二等等于零,如果等等于零,我们证明它是偶数吧,我就直接return一个true啊,返回true,然后如果没有等于零,是不是就不会返回数,不会返回数在这我们返回一个false啊,返回false,那这个函数的作用非常简单,如果I是偶数,就返回一个什么呀处,否则是不是就返回一个false呀?哎,返回false,那它有啥用啊,大家注意了。现在来看这。
11:50
之前我们是不是还是这么判断的呢?那这个时候我就不用了啊,我把这先给它注掉,我之前还这么判断的,哎,它是不是偶数,那现在有了这个函数我可以干嘛了,我是不是可以直接FN2,然后我这传一个N,是不是直接通过这个函数去解啊,如果它返回处就证明N是偶数,返回falses是不是证明N不是偶数,哎,N不是偶数,我这一保存这一执行是不是跟刚才效果是一样的呀?哎,效果是一样的,但是同学看到这就会说了,老师你这么写不更麻烦了吗?你之前就直接写个它就完事了,而这你现在还要定义一个函数,这是不是太麻烦了?哎,的确,如果你单纯的来看这个代码量来说,这的确麻烦了,但是它有一个什么好处,看着了啊,那现在这是它,那如果我现在想检查它是不是奇数呢?诶那你直接干嘛呀,其实奇数的话,你可以直接上面取一个反来一个nott,这时候取的是不是就奇数了,哎,这样可以,或者比如说现在你想检查你想获取什么呢?所有大于。
12:50
五的数,那怎么办?你可以再定义一个函数,来一个DEF,来一个FN3,我们这来一个哎还是来一个,哎,那这个时候呢,我们来一个EI大于5IF y大于五,我们就干嘛呀,Return一个处,然后呢,哎,我们特一个什么呀?哎,For你没五大我就返回一个,那这个函数干嘛?哎,这个函数用来定用来干嘛呀?哎,检查我们这个指定的数字是否大于五啊,是不是大于五,那我们直接来看效果,这个时候我这换了,我直接来一个FN3,我们这一执行是不是就获取到大于五的了,哎,你会发现我在这换了不同的函数,这规则是不是就变了呀?哎,这规则就变了,但是这个时候有同学就就看迷糊了是吧,老师你这么写好像还是没用啊。
13:42
你这么一写完了以后,这是还写死了,你掉SN3就检查是否大于五,你掉SN2是不是检查是否是偶数啊,的确如此,现在来看我们这么写是没有意义的,因为我这块还是写死了,我们在这里是不是希望我可以处理任何值啊,哎,你是偶数也好,是奇数也好,还是大于五也好,还是小于七也好,我在这里边我是不是都可以去比较动态的决定,而不是像现在这样写死了呀?哎,那我们来想想我们怎么能动态来决定,那现在我们会发现我这块到底是偶数,是奇数,还是大于三,还是大于七,是不是都由我调哪个函数决定的?哎,我现在调它就是偶数调3MN3就是大于五,对吧?那既然现在我们等于说这个规则是由函数来决定的,那我们想想,如果这个函数不是我们指定的,而是由什么呢?由调用者给我们传进来的,那这样。
14:43
啊,我们是不是能做到他给我们传什么,我们是不是就可以以什么规则来使用了,哎,比如说啊,看着我改一下了,我改一下啊,我把这两个函数啊,我给它挪到外边来。我给你挪到外边,现在这有两个函数啊,我们调整一下,缩进两个函数,一个是FN2,它是检查偶数的,还有一个是FN3,它是检查什么呀?是检查我们这个大于五的R大于五的,那这个时候注意了,这我就不写它了,因为这里边现在是不是没有FN3了,诶FN3了,那在这里我直接定义一个参数啊,定一个参数,这个参数呢,我们叫做一个FUC吧。
15:23
随便写一个啊,这个参数叫FUC,那现在注意了,它既然是个参数了,我在这是可以调它了,那注意了,现在我执行肯定不行,为什么?因为我这是没有传参呀,哎,没有传参,所以这时候会告诉你少了一个参数,对吧,少了一个这个参数那怎么办?那现在假如说我想按照偶数排序,我这直接传什么呢?我传一个FN2,那注意了,此时此刻我的第一个参数是不是就是一个函数,就是一个函数,我传进去以后,F fun nc是不是就是FN2,那现在它在排序,是不是根据这个函数来排序,这时候我们一保存一执行是不是偶数了,哎,偶数,那假如说我这传了一个FN3 FN3我传完了,这个时候我传的是什么?是不是大于五的那个函数啊,那这个时候我们再排序,是不是排到所有大于五的了,哎,排到所有大于五的了,那再来看啊,我再来写一个,我这来一个定义,一个FN4 FN4呢,我说什么里边还是需要一个艾。
16:23
作为参数,然后这里边我做一个简单判断,If一个I干嘛呢?哎,I摩以三等等于零,I摩以三等等于零,在这里我直接return一个什么呀?诶return一个处,然后呢,这直接return一个负,也就是说我看这个数能不能被三整除吧,那你猜猜我这如果传了个FN4是什么效果,那这个时候取得的是不是都是三的倍数,哎,我这一执行走一个是不是取得都是三的倍数,哎,你会发现我们在这我通过传递不同的函数作为参数,我们这个排序规则是不是就改了呀?哎,改了,所以这个就是一个高阶函数啊,这个就是一个高阶函数,所以注意高阶函数可以接收函数作为参数,那接收函数作为参数什么意思,什么作用,什么作用,那我们想想,如果我们的参数是个字符串也好,是个数字也好,是个布尔值也好,我们传递进去的是不是都是一个简单的数据啊?
17:23
哎,但是当我们使用一个函数作为参数时啊,当我们使用一个函数作为参数时,那我们什么呀?哎,我们实际上是将我们这个指定的代码传递进了什么呢?传递进了目标函数,所以注意现在来看,当我们将FN2作为参数传去的时候,我实际上是不是传的FN2的代码啊,当我做把FN3作为参数的时候,我传进去的是不是就是FN3的代码,当我传的是FN4的时候,我传的我是不是就传的是FN4代码啊?哎,所以注意把函数作为参数的好处就是我们可以直接向函数里去传什么传代码,那这样是不是就给你提供了一个高度的可定制性了,那这样就是你传什么代码,它是不是就等于传什么规则?哎,你可以根据不同的规则做一个什么呀。
18:23
排序,那这个就是我们说的一个什么呀,高阶函数啊,高阶函数,但是这里注意了,很明显,其实我这么写有点有点麻烦,哪麻烦呢,你看啊,我这要排个序是吧,我要调这个函数,我得定义了仨函数,FN2 FN3 FN4仨函数,这是不是很麻烦呀?哎,注意这里写的目前确实有点麻烦,那待会儿我们来说如何去解决这个问题,那现在先体会一下啊,先体会一下这个高阶函数,体会一下我为什么要将一个函数左右参数就是什么,就是把函数中保存的代码给传到那个目标函数里,把这个代码好好的去体会一下啊好,我们来停一。
我来说两句