python闭包函数的必要条件_Python 函数 functions、闭包 closure

一般我们都知道,函数只有在调用的时候才会被执行

但是我们在用 def 定义一个函数时,编译器做了什么?或者什么都没做?

实际上,当用 def 定义一个函数时,就创建了一个函数对象,该对象封装了函数体,并将其赋值给函数名这个变量

可以看出,定义一个函数和定义一个其他对象,基本上相同的

需要注意的是,如果我们定义函数时,在函数内部使用了一些变量,我们通常称它为局部变量或本地变量(local),此时这些变量是否分配了内存?

实际上,函数对象封装了函数体,函数体在函数没有被调用之前,是一块处女地

这些局部变量只有在函数被调用时被召唤,在函数调用完时被释放

特别注意,函数的形参也是局部变量

我杜撰的三种函数形式

1. 裸调用 func()

2. 传入参数调用 func(arg1)

3. 传入参数调用,并有返回值 =func(arg1)

实际上,python中任何函数调用都有返回值,当没有return来指定返回值时,返回值为None

func(*args, **kw) #可变参数,可接收任意个参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

函数的参数

1. 位置参数

2. key参数

3. 默认值参数

4. 可变参数

5. 可变参数解包

函数调用时的参数传递

a = -2.3

def pa(a):

print(a,id(a))

pa(a)

print(a,id(a))

ab = [3,4]

def pab(ab):

print(ab, id(ab))

pab(ab)

print(ab, id(ab))

#运行反馈

-2.3 5742856

-2.3 5742856

[3, 4] 7162120

[3, 4] 7162120

可以观察到,参数传递都传递的是引用,而没有在函数内部创建新的对象

很多教程对此的描述有错误

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

高阶函数(Higher-order function)

现在要讨论的是 函数的高级用法;

Python中的高阶函数起源于 函数对象可以像其他对象一样被变量(标识符)引用,变量可以指向函数

或者我们可以说,函数名就是一个指向内存中函数体的变量(不知这样描叙是否准确?)

def func(arg2):

print(arg2*5)

fc = func #变量fc指向函数func,或者说函数func赋值给fc,此时fc和func指向了同一函数体

print(func)

print(fc)

fc('b') #与使用func('b')的完全一致

func=7 #将int赋值给函数名func

print(func.__class__)

print(fc)

#运行反馈

#内存中相同的函数体(貌似fc不是直接指向,而是通过func间接指向)

#内存中相同的函数体

bbbbb

#说明函数名其实也只是一个变量

#当func移情别恋;可以看出fc是直接指向,而不是通过func间接指向

既然函数名是变量,那就应该可以像其他变量一样,

可以作为参数 传入另外一个函数,或者作为另外一个函数的返回值 返回调用处

def add(x, y, f): #函数作为参数,传入另外一个函数的栗子

return print(f(x) + f(y))

add(-5,6,abs) #给add函数传入一个内置函数abs

一个函数作为另外一个函数的返回值,隐含了,在一个函数内部定义了另一个函数,即函数的嵌套

def log(func):

def wrapper():

print("

func()

print(">")

return wrapper

@log #装饰器

def now():

print("html",end="")

now()

---------------------------上下完全等同---------------------------

def log(func):

def wrapper():

print("

func()

print(">")

return wrapper

def now():

print("html",end="")

log(now)() #装饰器实际调用过程

装饰器: 是一个函数,一个用来包装函数的函数,一个返回函数的高阶函数;

装饰器接收一个可调用对象作为输入参数,并返回一个新的可调用对象

装饰器: 接收要被修饰的函数为参数,返回修饰处理闭包的嵌套函数

怎么写一个装饰器

1. 嵌套函数

2. 外层函数接收 被修饰的函数 作为参数,return内部函数

3. 内部函数中调用 作为参数被传递进来的 被装饰的函数,同时进行修饰处理

嵌套函数 外层参数接收被修饰的函数,内层参数接收被修饰函数的参数

如果修饰器本身也需要传递参数,该怎么办呢?

这就需要三层嵌套了

def countdown():

r='hello'

s=3

def next():

return r*s

return next

mx =countdown()

print(mx)

print(mx.__closure__)

print(mx.__closure__[0].cell_contents)

print(mx.__closure__[1].cell_contents)

#运行反馈

.next at 0x00000000007FE9D8>

(, )

hello

3

闭包

嵌套函数中作为外部函数返回值的内部函数,如果内部函数引用了外部函数的变量,这内部函数称为闭包

闭包的3个必要条件: 1. 有嵌套函数 2. 内部函数作为外部函数的返回值 3. 内部函数引用外部函数变量

闭包就是一个函数,只不过在函数内部带上了额外的变量环境

闭包关键特点就是它会记住自己被定义时的环境

仅仅引用了外部变量的函数,并不一定是闭包,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值