- 函数名是一个特殊的变量,保存了函教的地址和
- 自定义一个变量可以获取函数地址
- 自定义变量调用函数 “函数名()”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| def work():
print("我是一个测试函数")
ret = work
print(ret)
print("地址:%X" % id(ret))
print("地址:%X" % id(work))
ret()
work()
out:
<function work at 0x00000161E3091E18>
地址:161E3091E18
地址:161E3091E18
我是一个测试函数
我是一个测试函数
|
- 当我们定义函数
test1
后,函数名test1
保存的是函数在内存的首地址函数名就是一个特殊的变量,函数名()
调用函数,执行函数体test1()
和ret()
都会调用函数,并执行函数体 - 和变量名一样的,函数名数名只是函数代码空间的引用,当函数名赋值给一个对象的时候就是引用传递。
闭包概念#
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包
维基百科中关于闭包的概念:在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。
闭包构成条件#
- 必须有一个内嵌函数(函数里定义的函数)–这对应函数之间的嵌套
- 内嵌函数必须引用一个定义在闭合范围内(外部函数里)的变量–内部函数引用外部变量
- 外部函数必须返回内嵌函数–必须返回那个内部函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| def function_out(num):
print("1.function_out num = ", num)
def function_in(num_in):
print("2.---------- function_in -----------------num", num)
print("3.---------- function_in -----------------num_in", num_in)
return function_in
# function_out(10)
# 调用function_out获取内层函数的地址,保存到ret
ret = function_out(100)
# 调用内层函数
ret(88)
out:
1.function_out num = 100
2.---------- function_in -----------------num 100
3.---------- function_in -----------------num_in 88
|
通俗理解:
- 存在函数的嵌套关系
- 内层函数引用了外层函数的临时变量
- 外层函数返回内层函数的引用
闭包中的变量#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| def function_out(num):
def function_in():
# 如果在内层定义了和外层变量同名的变量,但是要使用外层变量
# nonlocal 不使用内层函数的,而是使用外层的变量
nonlocal num
print("function_in num", num)
# 内部自定义的变量
num = 88
return function_in
# 调用外部函数
ret = function_out(99)
ret()
out:
function_in num 99
|
装饰器入门#
- 装饰器作用:在不改变函数的代码前提下,给函数添加新的功能
- 装饰器的使用:
写代码要道循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| def function_out(func):
def function_in():
print("开始验证")
func()
return function_in
@function_out
# @function_out装饰了 login() 函数
# 底层实现
# login = function_out(login)
def login():
print("开始登陆!")
# 通过闭包调用外层函数
# login = function_out(login)
login()
out:
开始验证
开始登陆!
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| def function_out(func):
def function_in(*args, **kwargs):
print("开始验证")
print("function_in user=", args)
print("function_in password=", kwargs)
return func(*args, **kwargs)
return function_in
@function_out
def login(*args, **kwargs):
print("开始登陆 user=", args)
print("开始登陆 password=", kwargs)
return 10
# 装饰完 login == function_in
result = login(20, a=18)
print(result)
out:
开始验证
function_in user= (20,)
function_in password= {'a': 18}
开始登陆 user= (20,)
开始登陆 password= {'a': 18}
10
|
在原装饰器增加外部变量#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
def test(path):
print(path)
def function_out(func):
def function_in():
print("开始验证")
func()
return function_in
# 返回装饰器的引用(装饰器工厂)
return function_out
@test("login.py")
# @test("login.py")分解为2步
# 1)test("login.py")-->function out 引用(地址)
# 2)@ 第一步的结果-->@function out
def login():
print("开始登陆")
@test("register.py")
def register():
print("开始注册")
login()
register()
out:
login.py
register.py
开始验证
开始登陆
开始验证
开始注册
|
多重装饰器#
- 给一个函数进行多次装饰
- 装饰原则:就近原则(靠近待装饰函数的先装饰,随后一层一层装饰)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| # <b>helloWord</b>
# 定义一个让文字加粗的装饰器
def makeBlod(func):
def function_in():
return '<b>' + func() + '</b>'
return function_in
# 定义一个让文字倾斜的装饰器
def makeItalic(func):
def function_in():
return '<i>' + func() + '</i>'
return function_in
@makeBlod
def demo():
return "helloWord"
@makeItalic
def demo2():
return "Luenci"
@makeBlod
@makeItalic
def demo3():
return "LYnn"
print(demo())
print(demo2())
print(demo3())
out:
<b>helloWord</b>
<i>Luenci</i>
<b><i>LYnn</i></b>
|
类装饰器#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| # 装饰器类
class Demo(object):
def __init__(self, func):
print("__init__方法")
print("-- func --", func)
self.func = func
def run(self):
print("正在奔跑")
def __call__(self, *args, **kwargs):
print("-- 开始验证 --")
# 调用原来login内容
self.func()
@Demo
# login = demo(login)
def login():
print("正在登陆")
login()
out:
__init__方法
-- func -- <function login at 0x0000024E64D857B8>
-- 开始验证 --
正在登陆
|