00:00
好,刚刚呢,我们已经初步完成了需求,但是后边我们也抛出了一个,哎问题,什么问题呢?呃,就是你这虽然已经可以对那个I的呀,或者说对我们FN这个函数进行扩展了,但是其实它还是很麻烦,他没有修改源代码,但是它很麻烦,因为我们每要包装,每要去修改,去扩展一个函数,我是不是就要定一个新的函数,对吧,新的函数,那我就希望我这个步骤我能不能简单一点,也就是说我不要每一次都手动去创建新函数,诶那同学说不要手动去创建新函数,那怎么办呢?不手动串新函数那怎么办?那在这里我们说了,哎咱们先写一下问题啊上边的方式,哎,我们应该嘛了,哎,我们已经。可以。哎,在不修改我们这个源代码的情况下。
01:05
哎,源代码的情况下对什么呢?哎,对我们这个函数进行扩展了,哎,已经可以在不修改源代码的情况下对函数进行扩展了。但是这种方式要求我们每。扩展一个函数就要干嘛呀,哎,手动创建一个新的函数啊,新的函数那实在是干嘛呀,哎,太麻烦了啊,实在是太麻烦了,那我们有没有什么简单的方式,那其实。非常简单,怎么简单呢,你既然觉得手动创建麻烦,那我们就干嘛,哎,我们就让它自动去创建,所以哎为了哎解决这个问题。哎,解决这个问题,我们可以干嘛呀?哎,我们可以创建一个函数,哎让这个什么呢?哎,让这个函数可以干嘛呀?哎,自动的哎帮助哎我们生成函数,也就说我们要创建一干嘛,创建一个创建函数函数啊,创建一个创建函数函数啊那现在我们来写一个,那这个函数,我们先定义一个这个函数我们叫什么呢?呃,这个函数我们的系功能是在我们这函数执行之前打印一个直行开始对吧,执行之后呢,打印一个执行结束,所以我们简单一点,我就叫一个be gn叫做一个begin,诶begin什么呢?诶begin end啊,我们就教这么一个函数,在执行前打印一个开始,在直行后打印一个这个end参数呢,诶这也不需要什么参数,因为它是因它这不需要传参对吧,不需要传参,那这函数它要干嘛的,哎,我们来说一下啊,那这个函数我们来说一下它的作用。
02:53
它是什么作用?它的作用是用来对我们的其他函数进行扩展啊,用来对其他函数进行扩展,使什么呢?哎,使我们这个其他函数可以在执行前诶打印,哎,执行哎,就是开始执行啊,开始执行,执行后打印干嘛呢?哎,执行结束就这么一个功能,对吧?那现在我们要怎么做?我们说了这个函数是用来帮我们创建函数的函数,对吧?所以在这里边我们先都不用想别的,我们先来干嘛,我们先来创建一个什么呀?哎,创建一个新函数啊,创建一个新函数直接DeFine,我们来一个叫做一个new,一个什么呀?哎,Function啊new一个function,这个就是我们的什么呀,新函数这我先写一个pass来占位啊,Pass来占位好,那现在我们来看,我在begin and这个函数里边创建了一个new function这个函数,那现在每卧调一次。
03:56
一定按的是不是就会生成一个新函数,每调一次就会生成一个新函数,每调一次就会生成一个新函数,但是现在产生一个问题,这个新函数我外边能看见吗?外边能看见吗?哎,外边是看不到的,对吧,后边是看不到的,所以在这儿我们还要做一件事,我要干嘛呢?哎,我要返回这个新函数啊,返回这个新函数,直接来一个return,来一个这个new function,是不是把它作为一个返回值返回啊,那现在的效果就是我这去调begin and的时候,我们来看一下啊,我直接来一个F等于一个begin and,调一下我再来一个F2,等于一个begin and,那现在我调了两次,我要问你F是什么,F2是什么?哎,F和F2是不是两个函数啊,它都是这个new function,但是它们两个是不是同一个,哎,不是,因为这个是我调两次所产生的函数啊,所以它们是两个函数,我这一保存一执行来看是不是函数啊,地址一样吗?哎,不一样。
04:56
就是两个函数,那现在我完成了第一个任务,也就是说我们现在的begin and是不是已经可以给我们返回一个新函数了,哎,返回一个新函数了,但是现在问题又来了,你的确是返回了一个新函数,是返回个新函数,但是这个函数它没用啊,我们希望这函数是干嘛的,这函数是不是应该是对我们这个旧函数进行扩展的呀?哎,对旧函数进行扩展的,所以这里边我是不是应该写点东西呀?哎,我写点东西我应该写什么呀?你说了执行前打印开始执行,执行后打印执行结束,对吧?所以在这我可以干嘛呀?哎,我直接打印一个叫做一个开始执行,开始执行啊,然后呢,我这再打印一个,打印什么呢?打印一个执行结束啊,执行结束,但是问题来了,我光这么写没用,我在开始执行和执行结束中间,我是不是应该再调一下我们这个旧函数啊,我调谁?
05:56
啊,如果你想对FN进行扩展,你这是不是应该调一下FN啊?如果你想对FN2进行扩展,你这是不是应该调一下FN2啊?如果你想对仨这个爱的进行扩展,你这是不是应该调一下爱的呀?说白了,你这要对谁扩展,你是不是就调谁呀?哎,就调谁,但是问题来了,我这写I的行吗?
06:16
哎,我这写FN行吗?哎,很明显这是不行的,因为我这写谁是不是就写死了,你写爱的就永远对爱的进行扩展,你写FN是不是永远对FN进行扩展呀,如果你这么做还不够麻烦的,对吧?但是咱们先这么做吧,我就先这么做,我现在就先对FN进行扩展,在这儿我们是不是来干嘛呀?诶调用我们这什么呀?哎,被扩展的函数。哎,被扩展的函数对吧,调用它,然后注意了,现在我们再调B呢,它返回的这个新的函数是不是就是对FN进行扩展了,哎,那现在这个函数啊,我来调一下这个F,调一下这F,我们来一执行走一个开始执行,我是FN函数执行结束,那等于我是不是就对FN进行扩展了,哎,就是这样一个效果,它的好处就是我不用每一次都手动定义新函数,因为定义新函数我是把它分装到另一个函数的内部了,你直接调这个函数,它就会自动去创建一个新函数,啊,自动会创建一个新函数,好,那这创建完了,接下来我们来看个问题了,还是刚才说这个问题了,你这写SN。
07:24
是不是只对FN进行扩展呀?你这写hello是不是只对hello进行扩展,你写什么就扩展什么,你这东西是不是就写死了,写死了好像就没有什么意义了。对吧,那这应该写谁?哎,这应该是写的是被扩展的函数,你想对FN进行扩展,你就应该写FN,你想对我们的这个。爱的进行扩展,这应该写爱的,你想对谁扩展,你是不是应该写谁呀?那我到底想对谁进行扩展,这确定,哎,不确定,因为我有可能想对艾进行扩展,有可能想对这个这个这个Mar进行扩展,也有可能想对FN进行扩展,对吧?那这个东西是不确定的,不确定怎么办?
08:09
哎,不确定,我们就需要把它做为一个什么呀参数传进来,比如说我们又传一个参数,叫做一个old,那这里边我们来说一下这个参数,参数什么呢?是我们这个要扩展的函数对象,也就是说你这要对谁进行扩展,你就干嘛,你就传谁,你要对艾特性扩展,你就传艾,你要对function对这个FN传扩展,就传什么呀FN,但是我这都是以I的形式进行old的形式进行接收,所以这个时候我就来什么呀,Old的我就调的,我不管你是谁,你传谁,我是不是对谁进行扩展呀,那注意了,Old这个时候需要的是一个函数对象,那注意这个时候你再去调begin的,你能不能不传参了,哎,很明显这时候必须要干嘛,必须要去传递参数,那怎么传呀?哎,怎么传?在这里我们直接传一个。比如说你要对FN进行扩展,你就传什么呀,FN,咱们来看一下效果,这一执行是不是效果是一样的,哎,效果是一样的,只不过这时候我们传那个FN作为参数,如果你不传这就干嘛了。
09:11
就报错了啊,就报错了,一定要注意传一个函数作为参数,那你要对爱进行扩展呢,你就传一个什么呀,I的这一保存行不行啊,哎,注意这么写肯定不行,肯定要报错,为什么?因为I里边是不是需要两个参数,而你这在调这个old的时候有没有传参,没有传参那怎么办?哎,那还是按照我们刚才那思路呗,A逗号B,你这传一个A逗号B,这一保存一执行。嗯,当然我这没传对吧,这传一个123逗号一个456,因为这个函数实际上是不是就是它呀,这需要两个参数,你就得传两个参数啊,这一保存一直行。呃,没保存啊,保存一下我们来关闭再执行走一个是不是就OK了,诶并且在这儿实际上也会有什么呀,也会有结果,但是现在还没有,因为它的结果我们是没有返回啊,所以在这我需要接收结果reut result等于它,然后最后我们要干嘛,我们要返回函数的一个执行结果啊,执行结果直接我们来一个return一个这个result啊return一个result直接返回,那现在我们这接收一下R等于它,然后我们这来打印一下这个啊,这一保存一执行是不是就是579啊,哎,就是579,那现在我们就获取到了这个结果,但是现在又有问题了,你现在是对A进行扩展对吧?那假如说我现在想对这个这个这个叫什么呀?FN进行扩展,FN有没有参数啊,FN是没有参数的,你这时候一调,我们来看这一保存。
10:38
一执行是不是报错了,哎,你看你有function丢了两个参数,你是不是还必须得传参数啊,我传一个吧,123来一个456这一保存一执行你看。FN需要零个参数,但是你给了它什么呀,两个,那这个时候你这再传AB是不是又报错了,哎,又报错了,所以现在我们已经可以对函数进行扩展了,但是问题是有的,这种需要我们扩展的函数,有的是需要参数的,有的是不需要参数的,有需要一个参数的,有需要两个参数,有需要100个参数的,有需要位置参数的,有需要关键字参数的,它是不是会有各种各样不同的情况呀,那你现在就带来一个问题,你这写参数也不是,你不写参数干嘛呀,也不是,写多了也不是,写少了也不是,哎呀,那要怎么办?那我们就想,我们这块肯定这个new function,它是要能适用于所有参数的,你有参数也好,没有参数也好,你是不是都可以用它呀?哎,都可以用它,那这时要怎么着。
11:39
哎,那我们有没有一种方式,我可以接收所有参数,哎,所有参数,那在这我们可以来什么呀?哎,来一个星号,来一个X啊星号我们说了它是不是接收所有的位置参数,哎在这我再来一个逗号,来一个星星,来一个keywords,一个什么呀,X啊,Keyword X,那这keywords X干嘛?它是不是接收所有的关键字参数啊,诶有有有就接收,没有就不接收,那我只需要把这两个东西写下来,我是不是应付到你所有的参数情况,你没有也行,有干嘛呀也行,是不是都能对付了,哎都能对付了,然后你再把这两个东西干嘛呀,你要在这是不是传进去,哎,把它做为参数再去传进去,但是注意这个虽然写法一样,但是意义不一样,这是在干嘛?这是把你的参数是不是装包成一个元组,或者装包成一个字典啊,哎,装包一个字典,而这是干嘛,这是把你这个元组拆包成位置参数传进去,这是把你个字典拆包成这个关键字参数数传进去。哎注意这两。
12:40
可个意义是不一样的,但你要知道这写是为什么啊,这写是为什么好写完了看效果啊,那现在我们这来看,现在我先包装FN这一保存一执行走一个,诶FN函数是执行了,哎,返回值式,那然后我再来一个啊F2等于一个这个begin and我来谁呢?我包装一个N呢,那注意了,这时候还用不用考虑参数了,哎,不用了,为什么不用了,因为我们这是不是都已经设置好了,直接来一个F2等于什么呀?哎,等于诶比如F2了R等于一个F2 f2这一保存我这一执行。
13:12
好,没传参啊,这应该123逗号一个456这一保存一直行是579也行了,诶也行了,你说我想再包装一个,再再再再扩展一个mart对吧,我直接来个FN3等于begin,那我们来一个这个mart mart我这再来一个啊来一个这助掉一个R等于一个F3FN31234562F3这一执行是不是也就OK了,哎,OK了,那也就是说如果你以后再有谁啊,再有哪个函数你需要进行扩展,你还用不用手动去写这代码了,哎,不用了,你想扩展SN,你就用比跟and去包装,去把这个SN作为参数传进来,哎,你要想扩展I的,就对I的调比begin,哎,如果你要想扩展mart,就对比begin and去调这个什么呀,Mart它都会返回一个新函数,你只要去调这个新函数,这个新函数是不是就是对我们这个函数扩展以后产生的新函数,你调用它就是一个功能增强版的一个函数啊。
14:13
啊,功能中间两个函数,那这个就是我们说的一个什么呀?哎,这个就是我们说的一个装饰器。哎,装饰器我在这直接来写了,像什么呢?哎,像我们这个,哎,Begin and这种函数。哎,我们就称它为什么呢,称为装饰器,什么叫装饰器,什么叫装饰器,哎,就像什么呀。诶,你有个玩具是吧,你家买个房子,你有个这个这个这个工作室对吧?诶你想对它进行装饰装饰,那是不是就对这东西进行打扮,要增强它呀,诶你给这娃娃,你给给这娃娃穿衣服,你给娃娃梳头发是吧?你给这娃娃戴帽子,穿各种各样好看的这个哎鞋对吧?裤子裙子你都可以,你是不是可以去装饰这个娃娃,装饰你的房间,装饰你的屋子呀,哎装饰你的屋子,那我们这种函数,我们它为装饰器,为什么称它为装饰器呢?哎,那我们说了,通过我们装饰器可以什么呢?哎,可以在不修改我们这个原来。
15:25
函数的这个情况下来干嘛呢?哎,来对我们这个函数进行扩展啊,你可以在不修改原来函数情况下对函数进行扩展,我们一般干嘛呢?哎在开发中,哎我们都是什么呀?哎通过哎装饰器哎来干嘛呢?哎来扩展我们这个函数的一个功能的啊功能的其实装饰器非常简单,就是你传一个旧函数作为参数传进去,然后它给你返回什么呀,新函数,这个新函数已经对我们这函数进行什么呀,进行升级改造了,你以后再调就可以去调这个什么呀,新函数它的功能哎和这个老函数是一样的,但是它更加的什么呀,强大多了一些,这种扩展啊,这就叫做一个装饰器啊装饰器,但是这里边我们一般情况下不会去手动定义,很少情况像这种去动定义,在这里你主要要理解一下什么呀的一个原理,关键点,这个参数是怎么回事,待会儿自己去体会。
16:26
会一下啊,体会一下,但是一般情况下,这东西我们还不是这么用,诶一般情况下我们像我这种用法呢,也会用到,但是呢,典型的用法不是这么用的,那怎么用看着了,那比如说现在我这有一个函数,我这个函数叫什么呢?哎,我们直接定义一个这个函数,我叫做一个say hello。非常那像这种它是我们那个自定义的函数,它的功能非常简单,就是打印什么呀,大家好,就是打印大家好。那这个时候呢,我就希望这个函数干嘛呀,也可以在函数执行前呀,打印一个开始执行,执行后打印一个执行结束了,我也希望直前实现这么一个功能,那根据我们之前的思路,我是不是调一个begin and,然后把c hello是不是传进作为参数,哎,这是可以的,但是呢,我们更直接的方法是什么呢?我可以在这直接写一个at at的后边跟着一个begin and啊,At的后边跟着一个begin and,那现在这个加上and以后,这就表示的是一个什么呀?装饰器,这就表示什么意思呢?我再用begin and这个装饰器去装饰say hello这个函数,那现在注意你再调用这个say hello,这个say hello,现在注意就不是你认识那个say hello,这个say hello就已经是被我们这个begin and它装饰过的say hello,它就已经是装饰过的函数,来我们来看效果,这一保存一执行,来看开始执行,大家好,是不是执行结束啊,诶执行结束,那这个就是我们一个装饰纪的典型用法,你定义完函数可以在这加一个什么呀,装。
17:56
示器,这样它可以干嘛,诶是不是少写代码了,如果你没有写这代码,你得把这对代码在你的c hello里边干嘛呀,再写一遍,但是当你写过以后,你是不是就省事了,哎,省事了可以用这个艾方式来对这个函数进行装饰,当然这种装饰完了以后,你再想找c hello你就找不着了,因为c hello这是不是已经被赋值了,I被赋值了,你要想再找就找不着了,那这种方式就是你就呃他就直接去改了,当然你说了,老师我不想用它了,怎么办啊,不想用把这装饰器一去走,你是不是就光你给大加好哎,你加上这个装饰器走,你是不是就。
18:31
装饰后的一个函数了,哎,装饰后函数啊,这是我们常用的一个用法,总之装饰器的作用就是来对我们函数进行装饰啊,进行这个更新,进行这个升级的啊,升级的诶,当然这时候就会有一个疑问了,有一些情况是这样的,在这啊,我们来定义一个第三一个啊,我直接是复制一个。这是一个装饰器对吧,装饰器,那我能不能再定一个新的呀?哎,当然可以了,我定义什么呀,我定一个这个D外,我们这来一个FN3吧,没有三对吧,FN3那现在呢,也是反应新函数,跟刚那是一样的对吧,跟刚才是一样的,那这个我改一个FN3。
19:13
装饰下面也写一个FN3装饰,那其实整个流程都是一样的,只不过这个加了一个FN3装饰,那个没有对吧?那个没有,那我要说什么问题,现在看着我这写一个at begin,这再写一个at fn3,也就是说我在这是不是给这个函数加了两个装饰器啊,那这是什么效果?哎,这是什么效果?哎,那我们来先写一下啊,先写一下。哎,我们在定义函数时啊,定义函数时可以通过我们这个艾特叉叉叉,哎叫做一个装饰器,哎来干嘛呢?哎来指定,哎来使用我们这个指定的这个什么呀?哎装饰器哎来干嘛呢?哎来装饰我们这个当前的一个函数,那注意了,我们可以同时哎为一个函数指定什么呀?哎多个装饰器啊指定多个装饰器,那指定多个呢?它这到底是怎么装饰的呀,看效果一直行啊当然这我没有调c hello啊调一下c hello这一保存一总开始执行,然后FN3装饰,然后大家好,FN3装饰,然后执行结束,发现什么了,发现什么了,它是不是诶咱们来看谁先起作用的。
20:34
谁先起作用的,咱们说了是不是我这个比begin先打印的呀,但是是谁先起作用的呀,很明显是FN3先起作用的,为什么?因为FN3是不是在里边啊,诶FN3在里边,也就是说它实际上是先用FN3进行包装,进行装饰,然后是不是再用进行装饰,诶那看着我把FN3跟begin换一个位置。这时候再看已保存。是不是比begin在里边,FN3在外边了,哎,就是说它是有这样一个顺序的啊,所以注意我们可以同时为一个函数指定多个装置器,这叫什么呢?
21:09
哎,这样函数将会什么呀,先被我们这个,哎内层的。哎,先将会什么呢,将会按照我们这个油内。从内向外的一个顺序被装饰什么意思呀?你这写了一个在里边是不是内部啊,F03是不是在外边啊,那就先用begin去装饰,Begin装饰完了以后再用FN3去装饰,你写100个也是先第一个,第二个,第三个,第四个,第五个,第一个越靠外是不是越靠外呀?哎,就是说它实际上等于我FN3是在装饰什么呀?是在装饰这个东西啊,是在装饰这个东西,那这个就是我们说的一个什么呀?哎,装饰器啊,装饰器这里还是主要理解一下它的概念,像这种情况下,我们真正去手动定义装饰器的情况呢,不是那么多,但是你也要自己去会定义,知道它是怎么回事,它是干嘛的,就是用来对我们的函数进行扩展的啊,进行功能增强的,那那好处就是解决了我们这些问题,什么问题啊,我们说了,如果我想去扩展一个函数,如果是什么呀,修改过多很麻烦,有了装饰器直接写一个装饰器是不是全都搞定了,哎第二一个不方便后期维护,有了装饰器你说我想改了,我用不用一个一。
22:29
给改啊,哎,不用,你只需要把装饰器里边那个代码改了是不是就OK了,诶然后第三一个,哎,违反开辟原则,那就装饰器以后还违不违反开辟原则不违反,因为我们压根儿就没有去修改原来的那个函数啊,没有修改原来的函数好装置器我们就说完了,我们来评一下。
我来说两句