黑马程序员学Python——装饰器基础

本文主讲:闭包的概念,装饰器入门、类装饰器、多重装饰器等等….

闭包基础【重点】

将函数名赋值给变量并且打印,会打印出什么

答:函数变量名保存的是这个函数在内存中存储的十六进制的地址

注意事项:函数名只是函数地址的一个引用,也就是一个变量 它可以赋值给其他变量,也可以被其他值赋值

图示:

image-20211012154150057

代码:

image-20211012154157111

了解函数的闭包

闭包概念:在一个外函数中定义一个内函数,内函数里运用了外函数的临时变量,并且外函数返回值是内函数的函数名(引用)

函数形成闭包的条件:

1:在外函数内部又定义了一个内函数

2:内函数可以引用(使用)外部函数的临时变量(内部函数引用外部变量)

3:外部函数返回值是内部函数的引用(函数名)

图示:

注意:下面代码的result(10,20) 不指定参数10,也是可以打印10 的,因为这个参数定义的形参就是和外部函数一致的

image-20211012154211238

闭包中的变量问题【重点】

闭包中变量使用的一些问题

问题图示:

image-20211012154222272

解决办法:

在内部函数打印前提前声明 num 变量不使用内部函数的nun即可!

关键字:nonlocal

图示

image-20211012154232949

装饰器入门【面试点】

python内装饰器的使用场景

答:装饰器可以在不改变函数源代码的前提下为函数增加新的功能

装饰器的使用前提:

1:有一个待扩展功能的普通函数(不改变这个函数的源代码增加新功能)

2:装饰器要依赖于闭包才能实现扩展新功能(用于扩展函数新的功能)

工作写代码的准则

答:掌握开放封闭原则,即以前写好的功能尽量不要修改其源代码(封闭),但是可以对以前写的功能进行扩展也就是开放(装饰器)

装饰器的语法及使用依赖和使用方法

语法:@闭包内的外层函数名

示例:

1
2
3
4
@function_out
def test( ):
xxxx
Xxxx

其中function_out是闭包中的外层函数名,test()是待扩展功能的普通函数

使用依赖:

1:必须要有一个待扩展功能的函数

2:必须要有一个闭包,为待扩展函数在不修改源代码的前提下增加功能

3:在装饰器模式下,原来的闭包就被称为装饰器了

注意事项:

1:闭包的外层函数必须要有参数,用于待扩展函数的函数名传递

2:上方的 @function_out 等价于 test = function_out(test)

使用方法图示:

image-20211012154304559

注意事项:

1:test = function_out(test) 前后两个test代表的函数地址是不一样的 前面test代表的是闭包内层函数的地址,后面test代表的是test函数的内存地址!

2:闭包内的 func()函数执行的就是待扩展的函数 test()

装饰器装饰有参数的函数【应用】

装饰器如何装饰有不可变参数的函数

image-20211012154317998

装饰器如何装饰有可变参数的函数

答:function_in(闭包的内层函数参数)函数与 func 函数的参数设置同名!

图示分析

image-20211012154328310

装饰有返回值的函数【应用】

如何装饰有返回值的函数

目标需求:

image-20211012154344345

实现代码:

image-20211012154351297

实现通用版装饰器【重点】

装饰器通用版的模板是什么样的!(既能传递参数也能有返回值)

代码:

image-20211012154408237

在装饰器外部设置变量(定义函数)【理解】

如何在装饰器外部设置变量(定义函数)

答:即在装饰器(原始闭包)的外部再次定义一个函数并且返回原装饰器外层函数的函数名

注意事项:设置装饰器外部变量看着像是创造了装饰器,因此这种语法模式也被称为装饰器工厂模式

图示:

image-20211012154420691

怎么使用设置外部变量后的装饰器!

关键字:@设置的外部变量函数名(参数) 例如 @variable(“haha”)

注意:@variable(“haha”) 分为三步从而达到调用装饰器的目的

第一步:先执行 variable(“haha”)函数

第二步:执行 @第一步函数的返回值 例如 @function_out

第三步:正常执行装饰器的步骤

图示:

image-20211012154442599

不设置外部变量的装饰器与设置外部变量装饰器的区别

答:装饰器的调用一定要注意区别

例如 @ viriable(“lala”) 与 @viriable 有参数和没参数就天差地别

注意:装饰器的调用有参数就说明这个装饰器设置了外部变量,没有参数就没有设置外部变量!

多重装饰器【面试点】

什么是多重装饰器?

答:多重装饰器就是多个装饰器(闭包)装饰一个待扩展的函数

多重装饰器的工作流程

实例:

@ 第一个闭包外层函数名 → 这是第一个装饰器

@ 第二个闭包外层函数名 → 这是第二个装饰器

待扩展函数 → 这是待装饰的函数

工作流程:函数从上向下开始执行 执行到第一个装饰器之后因为装饰器下面没有函数因此先停止装饰,第二个装饰器开始装饰下面的待扩展函数装饰完毕后第一个装饰器再装饰已经被第二个装饰器扩展完毕的函数!

也就是第二个装饰器装饰函数 → 第一个装饰器装饰被第二个装饰器扩展的函数!

image-20211012154520715

多重装饰器的工作步骤(具体观看视频 p204)

image-20211012154528084

类装饰器【重点】

为一个类创建的对象加上括号会发生什么?

答:为一个类创建的对象加上括号会调用这个类中的 call 方法

图示:

image-20211012154539853

什么是类装饰器

答:正常装饰器的扩展体是一个闭包,而类装饰器的扩展体是一个类!

怎么使用类装饰器

关键字:@类名 例如 @Test

使用方法:在待扩展函数前面加上@类名 即可实现利用类装饰器装饰函数的功能

实例:

1
2
3
4
5
@Tset
def ceshi( ):
Xxx
Xxx
Xxx

注意事项:

1:上面示例的 @Test 等价于 ceshi = Test(ceshi)

2:实例化的对象加上括号就会调用类里面的 call( )方法

3:类装饰器中的类必须包含两种方法,init( ) 与 call( ) 方法,而且 init( ) 方法必须接收 待扩展的函数名!并且初始化 例如 self.func = func call( )方法内必须要执行 self.func()才能达到装饰函数的目的

代码演示:

image-20211012154600352

数据库的主从配置【了解】

数据库的主从配置使用场景

答:当我们做一个项目时,一台服务器上的数据库保存着大量重要的数据,这时为了避免这个地区断电或者其他原因造成这个数据库(主服务器)不能正常访问,我们就可以访问从服务器,避免事故

注意事项:

1:主服务器与从服务器是即时通信的,主服务器上数据发生变化,会通过二进制报文与从服务器进行通信,从服务器可以实时更新数据

2:主服务器与从服务器的数据库版本以及环境要一模一样,否则不能建立通信

3:主服务器与从服务器不要放在同一地区

数据库主从配置的配置步骤

请去浏览器搜索查看步骤!

未完待续……