python基础梳理(十四)闭包、装饰器和函数的文档字符串

多数语言没有的,python特有的内容

一、闭包 closure
什么是闭包:
内嵌函数的语句和这些语句的执行环境打包在一起后 得到的函数对象称为闭包

闭包必须满足以下三个条件:
1.必须有一个嵌套函数
2.内嵌函数必须引用外部函数中的变量
3.外部函数返回值必须是内嵌函数

示例:

#此程序示意闭包的用法
#1.fn为内嵌函数
#2.fn用到了fn外部的变量y
#3.make_power将fn绑定的函数对象返回给调用者
def make_power(y):
    def fn(x):
        return x ** y
    return fn

pow2 = make_power(2)
print("5的平方是:",pow2 (5))

执行结果:
25

分析上面程序我们不难发现:
make_power函数返回了fn函数的变量,最终pow2绑定的是fn;
y是函数make_power的局部变量,所以make_power(2)函数调用完以后,按理来说局部变量y = 2应该被回收掉了,但是我们发现pow2(5)执行后,结果为25,看起来y= 2并没有被销毁。

这是为什么?
其实这就是闭包。
实际上,make_power函数不仅仅返回了fn的函数对象,而是将局部变量y和函数对象fn一起打包起来返回给了pow2,这个包我们就叫闭包
可以这样理解,我内嵌函数用到了外层函数的变量,这样就将变量的和函数对象捆绑在了一起,整个大的运行环境的引用计数+1,函数对象到哪里,那自然变量也得跟着去哪儿,自然就不会被销毁了

闭包的好处:就像是个函数工厂
相当于是绑定函数的一个参数,另外一个参数由用户传入

#求一些数的平方
pow2 = make_power(2)       #pow2函数专门用来求某个数的平方
print("5的平方是:",pow2 (5))
print("10的平方是:",pow2(10))
print("12的平方是:",pow2(12))
#求一些数的立方
pow3 = make_power(3)         #pow3函数专门用来求某个数的立方
print("5的立方是:",pow3 (5))
print("10的立方是:",pow3(10))
print("12的立方是:",pow3(12))
#同理,求一些数的5次方
pow4 = make_power(5)
print("5的5方是:",pow4 (5))
print("10的5方是:",pow4(10))
print("12的5方是:",pow4(12))
执行结果:
5的平方是: 25
10的平方是: 100
12的平方是: 144
5的立方是: 125
10的立方是: 1000
12的立方是: 1728
5的5方是: 3125
10的5方是: 100000
12的5方是: 248832
#pow2等同于
def pow2(x):
    return x ** 2
    #pow3等同于
def pow3(x):
    return x ** 3
#有了闭包就可以很快的创建类似功能的函数

接下来我们通过图来理解整个过程:
在这里插入图片描述
所以,内部函数可以放心的使用外部的函数的变量,不用担心被释放。
(如果一个内嵌函数访问了外部嵌套函数的作用域内的变量,则这个内嵌函数就是闭包)

二、装饰器 decorators(专业提高篇)
什么是装饰器:
装饰器是一个函数 , 这个函数的主要作用是包装另一个函数或者类
包装的目的:
不改变原函数名的情况下改变被包装对象的行为(是在原理函数的基础上装饰)

函数装饰器 function decorators
函数装饰器是指装饰一个函数,传入的是一个函数,返回的也是一个函数

示例1:用新的函数装饰(替换掉)原来的函数

#fn绑定旧的函数(被修饰的函数),返回新的函数
def mydeco(fn):#装饰器函数
    def fx ():
        print("hello world")
    return fx

def hello():  #被装饰函数
    print("hello python")

hello()   #装饰前
hello = mydeco(hello)   #将hello绑定在了mydeco函数返回的函数上
                                     #此种做法可以用装饰器@语法解决
hello()   #装饰后
执行结果:
hello python
hello world

示例 1 ** 还有另外一个写法,使用 @ 来代替,与上面的等价 **:即就是@用法的原理

def mydeco(fn):#装饰器函数
    def fx ():
        print("hello world")
    return fx
@mydeco
def hello():  #被装饰函数
    print("hello python")

hello()   #装饰后
执行结果:
hello world

示例2:装饰器可以在不改变原来函数的调用的情况下,在调用原来函数的前后进行一些操作

def mydeco(fn):#装饰器函数   绑定的是原来被装饰前原来的函数
    def fx ():
        print("******************")
        fn()
        print("##################")
    return fx
@ mydeco
def hello():  #被装饰函数  原函数
    print("hello python")

hello()   #装饰后    被装饰的函数

执行结果:
******************
hello python
##################

#此例用意说明:
#我们这里并没有改变原来函数的执行,但是我们可以在原函数调用的基础上做一些装饰,或者其他操作

三、函数的文档字符串:其实就是给开发人员看的函数说明书
语法:
def 函数名(参数列表):
“”“函数的文档字符串”""
函数语句块
说明:
文档字符串通常用来说明本函数的功能和使用方法
在交换模式下,输入help(函数名)
可以查看函数,“文档字符串”

示例1:查看一个内建函数的文档字符串

help(max)
执行结果:
Help on built-in function max in module builtins:

max(...)
    max(iterable, *[, default=obj, key=func]) -> value
    max(arg1, arg2, *args, *[, key=func]) -> value
    
    With a single iterable argument, return its biggest item. The
    default keyword-only argument specifies an object to return if
    the provided iterable is empty.
    With two or more arguments, return the largest argument.
 
 #max(...)以下的字符,用来描述函数的作用,参数列表,返回值等

实例2:自己写一个函数的文档字符串

def function(a,b):
    """"这是一段对function函数的解释,
    主要内容包括我的函数名称、参数列表
    以及返回值等,我就说这么多,这是我
    全部关于该函数的文档字符的"""
    print("hello world")
    
function(1,2)
执行结果:
hello world
#我们甚至可以查看我们自己给自己的function函数的文档字符串
help(function)

执行结果:
Help on function function in module __main__:

function(a, b)
    "这是一段对function函数的解释,
    主要内容包括我的函数名称、参数列表
    以及返回值等,我就说这么多,这是我
    全部关于该函数的文档字符的


Process finished with exit code 0

四、函数的_doc_属性:

函数内第一次未赋值给任何变量的字符串是此函数的文档字符串
此字符串会自动赋值给函数的_doc_属性

示例:

def cba():
    "这是一个文档字符串"      #这是一个表明没有赋值给任何变量的字符串
    pass                   #我们知道函数就是一个对象,对应着函数对象有一个叫_doc_的属性
                           #会将这个字符串赋值给对象的_doc_属性
print(cba.__doc__) #这是一个文档字符串

执行结果:
这是一个文档字符串

五、函数定义的完整语法:
[@装饰器1]
[@装饰器2]
[…]
def 函数名([位置形参],[*元组形参],[命名关键字形参],[**字典形参]):
“文档字符串”
语句块

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值