python cs架构 运维_运维架构师-Python 自动化运维开发-025

*运维架构师-Python 自动化运维开发-025

十四、高阶函数介绍

1、特点把一个函数的函数名当做实参传给另一个函数

函数本身可以作为另外一个函数的返回值

def foo():

return 10

def func(bar):

print(id(bar), bar)

func(foo())

#def func(foo):

# print(id(foo),foo)

# 直接打印原函数的 id

print(id(foo))

# 调用函数 并把 foo 作为实参传递进去,查看传输的函数的 id

func(foo())

在调用函数 func(foo) 时,如下图:可以看出被传入的函数和原函数是一个对象

2、内部函数

在一个函数内部定义的函数

def outer():

def inner():

x = 10函数 inner 就是一个内部函数

3、 闭包

是一个函数动态生成的另一个函数,并且返回一个 包含了外部作用域而非全局作用域变量名称的函数。这个函数可以使用外部作用域的变量。

闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)

python语言中形成闭包的三个条件,缺一不可:1)必须有一个内嵌函数(函数里定义的函数)——这对应函数之间的嵌套2)内嵌函数必须引用一个定义在闭合范围内(外部函数里)的变量——内部函数引用外部变量3)外部函数必须返回内嵌函数——必须返回那个内部函数

# 什么是闭包

# 定义一个函数

def test(number):

# 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包

def test_in(number_in):

print("in test_in 函数, number_in is%d" % number_in)

return number+number_in

# 其实这里返回的就是闭包的结果

return test_in

# 给test函数赋值,这个20就是给参数number

ret = test(20)

# 注意这里的100其实给参数number_in

print(ret(100))

# 注意这里的200其实给参数number_in

print(ret(200))

# 运行结果:

in test_in 函数, number_in is 100

120

in test_in 函数, number_in is 200

220

#_*_ coding:utf-8 _*_

# def test():

# x = 10

# def test_in(num_in):

# print("在test_in函数, num_in is %d" % num_in)

# return x + num_in

# print(x)

# return test_in

#test()

# 1. 调用test函数,开始执行函数

# 2,产生局部变量 x = 10

# 3,定义一个函数(没有调用,不执行),只有test_in函数方法

# 4, 打印输出变量x

# 5,把定义的test_in 这个函数返回给调用者(test函数调用的)

# 6,最后获取的的值 test_in 函数

# ret = test()

# 把返回的test_in函数重命名为ret(类似于变量赋值)

# print(ret)

# 打印输出一下test_in函数方法,返回test_in 函数方法

# print(ret(1000))

# 相当于调用了 test_in函数,返回 test_in 返回值(相加的结果)

def test(arg):

def test_in(num_in):

print("在test_in函数, num_in is%d" % num_in)

return arg + num_in

print(arg)

return test_in

test(10) # 打印了一下arg ===》10

print(test(10)) # 打印10 并放回test_in 函数

ret1 = test(10) # 把test函数的返回值赋值给ret1

print(id(ret1)) # 打印ret1的函数内存位置(也就是test_in这个函数的内存位置)

print(ret1(100)) # 调用了test_in函数,返回了结果 arg ===>10 + num_in ===》100 ===》110

#函数可以作为另一个函数的参数或返回值,可以赋给一个变量。函数可以嵌套定义,即在一个函数内部可以定义另一个函数,有了嵌套函数这种结构,便会产生闭包问题。如:

def outer(f):

def inner():

print(f)

return inner

really_inner = outer(10)

really_inner()

上面的 f 可以是任何的 python 对象,当然也可以是给函数。

def foo():

pass

def outer(f)

def inner():

print(f)

return inner

really_inner = outer(foo)

此时, really_inner 就是闭包, 其本质就是 inner 函数对象, 并且包含了 foo 这个函数对象。

创造一个闭包:

def line_conf():

def line(x):

return 2*x+1

return line # 返回line 函数对象

my_line = line_conf()

print(my_line(5))

def line_conf():

b = 15

def line(x):

return 2*x+b

return line # 返回line 函数对象

b = 5

my_line = line_conf()

print(my_line(5)) # 返回25

# 在内部函数中只能对外部函数的局部变量进行访问,但是不能修改,如果需要修改则需要用到nonlocal关键字,委屈求全可以使用“容器类型”代替

def line_conf():

b = 15

def line(x):

nonlocal b

b=20

return 2*x+b

return line # return a function object

b = 5

my_line = line_conf()

print(my_line(5)) #返回30

def line_conf():

b = [15]

def line(x):

b[0]=20

return 2*x+b[0]

return line # return a function object

my_line = line_conf()

print(my_line(5)) #返回30

我们根据上面的三准则创造了一个函数,其中的funy就是所谓的闭包,而funy内部所引用过的x就是所谓的闭包变量。

闭包有什么用

在交互式模式下,对函数进行简单的测试:

def funx():

x=5

def funy(): # 内部函数中只能对外部函数的局部变量进行访问,不能修改

nonlocal x # 如果需要修改则需要用到 nonlocal关键字

x+=1

return x

return funy

>>> a=funx()

>>> a()

6

>>> a()

7

>>> a()

8

>>> a()

9

>>> x

Traceback (most recent call last):

File "", line 1, in

x

NameError: name 'x' is not defined

>>>

funx中的x变量原本仅仅是funx的一个局部变量。但是形成了闭包之后,它的行为就好像是一个全局变量一样。但是最后的错误说明x并不是一个全局变量。其实这就是闭包的一个十分浅显的作用,形成闭包之后,闭包变量能够随着闭包函数的调用而实时更新,就好像是一个全局变量那样。(注意我们上面的a=funx(),a实际上应该是funy,所以a称为闭包)

4、 装饰器

1、原始方式实现(老的方式)

def echo():

print('欢迎来到千锋云计算')

def outer(arg): # arg = echo ---> arg()===echo()

def inner():

print("*" * 20)

arg() # echo() 原函数

print("*" * 20)

return inner

echo = outer(echo) # 最终的结果是inner()函数

# def outer(echo):

# def inner():

# print("*" * 20)

# echo()

# print("*" * 20)

# return inner

echo()

# 执行流程

# 1,运行echo()函数 (放进内存)

# 2,运行outer(arg)函数 (放进内存)

# 3,重新赋值后调用 outer(arg)函数,

# 4,运行inner()函数 (放进内存)

# 5,调用inner()函数并返回结果

# 6,echo()得到新结果

# 7,业务线的调用echo()函数的方式没有变,但功能添加了

# 8,业务线调用新的echo()函数,就开始执行inner函数

# 9,根据函数执行顺序,包含了原来的echo()函数和添加的功能

2、语法糖实现(目前使用此种方式)

def outer(arg): # arg = echo()

def inner():

print("*" * 20)

arg() # echo 原函数

print("*" * 20)

return inner

@outer

# 1, 执行outer函数 outer(echo),

# 2,获取outer的返回值,并把返回值赋值给被装饰的函数的函数名,echo = outer(echo) 最终 echo=inner()

def echo():

print('欢迎来到千锋云计算')

echo()

# 执行装饰器,对被装饰的的函数进行重新赋值

使用装饰器的理由

在软件开发领域有个规则:

在开发时,需要遵循 开放封闭原则,就是对扩展开放,对修改封闭。

扩展开放,就是可以对原来的函数功能进行扩展。

修改封闭,就是给原来的函数添加功能的时候,不可以直接修改原来的函数。

装饰器的作用是什么

装饰器时装饰其他对象的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。

强调装饰器的原则:不修改被装饰对象的源代码

不修改被装饰对象的调用方式

装饰器的目标:

在遵循1和2的前提下,为被装饰对象添加上新功能

3、补充内置函数 枚举 enumerate

li = ["hello","world", 'len', 'network']

#

# for idx, item in enumerate(li):

# print(idx, item)

# for idx, item in enumerate(li, 1):

# print(idx, item)

欢迎访问磊哥B站主页:千锋云计算磊哥

喜欢文章的话,欢迎点赞收藏评论互动哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值