1、闭包
- 什么是闭包:内部函数对外部函数作用域里的非全局变量的引用,称【内部函数】为闭包。
- 闭包三要素:1、嵌套函数;2、变量引用;3、返回内部函数
def fun(n):
def fun_in(m):
print("sum = ",n+m)#内部函数对外部函数的变量的引用(n)
return n,m
return fun_in
f = fun(10) # 这里f 为函数fun()的返回值,及fun_in的地址
f
<function __main__.fun.<locals>.fun_in(m)>
# 要想调用函数,只需要加上括号并传入相关的参数即可
f(100)
sum = 110
(10, 100)
使用
- 下面的代码定义了一个一次函数y = ax+b,其中a,b为参数,我们可以i对其进行指定:
def fun(a,b):
def fun_in(x):
return a*x + b
return fun_in
f = fun(2,3)
f
<function __main__.fun.<locals>.fun_in(x)>
f(10)#2*10+3
23
#也可以直接调用
fun(4,10)(10)
50
2、装饰器
- 首先,放出来那两篇博客的链接,大家可以去看看,保证有所收获!python装饰器详解和Python 装饰器的通俗理解
- 功能:简单来说,装饰器的作用就是在已经定义了某个函数之后,后期我们希望为该函数增加新的功能,但是碍于代码已经上线运行等原因,我们不能直接在源代码上直接修改。从中可以看出有以下几点:
- 1、不修改原来的核心代码
- 2、不能改变核心代码的调用方式
- 3、给核心代码增加新的功能
高级函数
- 首先需要知道函数名和变量名在实际上就是一个地址。高级函数可以分为:
- 1、函数的参数是一个函数
- 2、函数的返回值是一个函数
- 还有就是区分函数定义和函数调用,下面举个例子:
def func1():
def func2():
print('call func2')
print('call func1')
func1()
call func1
- 注意上述代码并没有打印出call func2,这里可以这样理解,func1()的功能就是定义func2,并打印call func1
def func1():
def func2():
print('call func2')
func2()
print('call func1')
func1()
call func2
call func1
- 上述代码可以理解为有两个功能:一个是定义func2,一个是调用func2.
# 该函数在两秒之后打印内容
import time
def test():
time.sleep(2)
print("test is running")
test()
test is running
- 现在需要增加该函数的功能,计算该函数的运行时间,但是不可以改变test()函数
import time
def test():
time.sleep(2)
print("test is running")
def deco(func):
start = time.time()
func()
stop = time.time()
print(stop - start)
deco(test)
test is running
2.000415325164795
- 上述代码中deco()函数其实就是一个高级函数,它的参数为一个函数。
* 但是上面的函数虽然实现了增加功能的要求,但是它改变了函数的调用方式,原来我们是调用test()函数,我们像不改变调用方式,怎么办呢?
import time
def test():
time.sleep(2)
print("test is running")
def dec(func):
print(func)
return func
dec(test)()
<function test at 0x06383150>
test is running
- 上面的dec()函数也是一个高级函数,它的返回值是一个函数。但是它并没有增加我们需要的功能。
嵌套函数
- 嵌套函数是指在函数内部定义函数,注意不是调用函数
# 定义函数
def func1():
def func2():
pass
pass
# 调用函数
def func1():
func2()
pass
import time
def test():
time.sleep(2)
print("test is running")
def timer(func):
def deco():
start = time.time()
func()
stop = time.time()
print(stop-start)
return deco
test = timer(test) #1
test() #2
test is running
2.000458002090454
-
#1处调用timer()函数,并返回了deco,赋值给test,此时test实际上就是函数deco()的入口地址
-
#2处在test后面加上(),实际上完成了对test()函数的调用,也即deco()函数的调用。
-
实际上上面的函数也是一个闭包,它满足了闭包的三个条件
-
装饰器可分为对【有无参数】函数进行装饰的装饰器和对有【无返回值函数】进行装饰的装饰器,组合起来一共有4种。即:装饰器对无参数无返回值的函数进行装饰,装饰器对无参数有返回值的函数进行装饰,装饰器对有参数无返回值的函数进行装饰,装饰器对有参数有返回值的函数进行装饰。
对无参数的函数进行装饰
import time
def timer(func):
def deco():
start = time.time()
func()
stop = time.time()
print(stop-start)
return deco
@timer
def test():
time.sleep(2)
print("test is running")
test()
test is running
2.000509738922119
- 使用装饰器既增加了函数的功能,又没有改变调用方式(还是调用的test())
对有参数的函数进行装饰
def timer(func):
def deco(args):
start = time.time()
func(args)
stop = time.time()
print(stop-start)
return deco
@timer
def test(args):
time.sleep(args)
print("test is running")
test(3)
test is running
3.0000321865081787
1、装饰器对无参数函数进行装饰
#对字体加粗
def makeBold(fn):
def wrapped():
return "<b>"+fn()+"</b>"
return wrapped
#斜体字处理
def makeItalic(fn):
def wrapped():
return "<i>"+fn()+"</i>"
return wrapped
@makeBold
def test1():
return "hello"
@makeItalic
def test2():
return "world"
@makeBold
@makeItalic
def test3():
return "hello world"
test1()
'<b>hello</b>'
test2()
'<i>world</i>'
test3()
'<b><i>hello world</i></b>'
- 上面的代码是做网页时对字体进行处理。注意:可以对一个函数同时使用多个装饰器,装饰的顺序由内而外
2、装饰器对有参数的函数进行装饰
def deco(func):
def wrapped(a,b):
print('在此处增加功能')
func(a,b)
return wrapped
@deco
def sum(a,b):
print(a+b)
sum(10,20)
在此处增加功能
30
- 当装饰器装饰有参数的函数时,装饰器内部的函数也必须带有和其相同的参数,因为被装饰的参数会被当成参数传进装饰器的内部函数中,如果两者的参数不一致,会报错。
3、装饰器对不定长的参数函数进行装饰
from time import ctime,sleep
def deco(func):
def wrapped(*args, **kwargs):
print("{} is called at the time: {} ".format(func.__name__,ctime()))
func(*args,**kwargs)
return wrapped
@deco
def test1(a,b,c):
print(a+b+c)
@deco
def test2(a,b):
print(a*b)
test1(1,2,3)
test1 is called at the time: Thu Nov 29 19:25:07 2018
6
test2(2,4)
test2 is called at the time: Thu Nov 29 19:25:15 2018
8
4、装饰器对有返回值的函数进行装饰
from time import ctime,sleep
def deco(func):
def wrapped(*args, **kwargs):
print("{} is called at the time: {} ".format(func.__name__,ctime()))
return func(*args,**kwargs)
return wrapped
@deco
def test():
return "hello"
test
<function __main__.deco.<locals>.wrapped(*args, **kwargs)>
test()
test is called at the time: Thu Nov 29 19:30:34 2018
'hello'