从零开始的Linux运维屌丝之路,资源免费分享平台   运维人员首选:简单、易用、高效、安全、稳定、社区活跃的开源软件
  • 首页
  • Python
  • 28、python函数进阶、闭包、装饰器

28、python函数进阶、闭包、装饰器

发布:蔺要红05-11分类: Python



1、闭包

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

可以将闭包理解为一种特殊的函数,这种函数由两个函数的嵌套组成,且称之为外函数和内函数,外函数返回值是内函数的引用,此时就构成了闭包


当闭包执行完后,仍然能够保持住当前的运行环境
 
# -*- coding:utf-8 -*-
def func():
    n = 10
    def func2():
        print(n)
    return func2
f = func()
print(f)
f()

#D:\python\python.exe F:/运维笔记/python/函数/函数进阶-闭包.py
<function func.<locals>.func2 at 0x000002830D440840>
10

关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局 部变置、参数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变置、參数以及其他内部函数。这些局部变置、参数和函数声明(最初时)的 值是外部函数返回时的值,但也会受到内部函数的影响

闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裏了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层 包裹的作用域

 

2、python装饰器

 

python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象(函数的指针)。装饰器函数的外部函数传入我要装饰的函数名字,返回经过修饰后函数的名字;内层函数(闭包)负责修饰被修饰函数


实质: 是一个函数
参数:是你要装饰的函数名(并非函数调用)
返回:是装饰完的函数名(也非函数调用)
作用:为已经存在的对象添加额外的功能
特点:不需要对对象做任何的代码上的变动


python装饰器有很多经典的应用场景

如:插入日志、性能测试、事务处理、权限校验等。装饰器是解决这类问题的绝佳设计。
从引入中的列子中我们也可以归纳出:装饰器最大的作用就是对于我们已经写好的程序,我们可以抽离出一些雷同的代码组建多个特定功能的装饰器,
这样我们就可以针对不同的需求去使用特定的装饰器,这时因为源码去除了大量泛化的内容而使得源码具有更加清晰的逻辑

 

01、对如下现有代码进行修改,要求加入登陆验证
# -*- coding:utf-8 -*-
def home():
    print("-------首页-------")
def america():
    print("-------美国新闻-------")
def japan():
    print("-------日本新闻-------")
def shandong():
    print("-------山东新闻联播-------")
home()
america()
japan()
shandong()
#D:\python\python.exe F:/运维笔记/python/函数/装饰器0.py
-------首页-------
-------美国新闻-------
-------日本新闻-------
-------山东新闻联播-------

第一次修改
 
违背 开放-封闭 原则。规定已经实现的功能模块不能被修改,但是可以被扩展
封闭:已实现的功能代码模块不应该被修改
开放:对现有功能的扩展开放
 
# -*- coding:utf-8 -*-
user_status = False
def login():
    _username = "lin"
    _password = "123"
    global user_status
    if user_status == False:
        username = input("user:")
        password = input("password:")
        if username == _username and password == _password:
            print("welcome login....")
            user_status = True
        else:
            print("username or password error")
    else:
        print("用户已登录,通过验证....")
def home():
    print("-------首页-------")
def america():
    login()
    print("-------美国新闻-------")
def japan():
    print("-------日本新闻-------")
def shandong():
    login()
    print("-------山东新闻联播-------")

shandong()
america()
japan()
home()
#D:\python\python.exe F:/运维笔记/python/函数/函数-装饰器.py
user:lin
password:123
welcome login....
-------山东新闻联播-------
用户已登录,通过验证....
-------美国新闻-------
-------日本新闻-------
-------首页-------

第二次修改:利用高阶函数

   虽然没有修改源代码、但是改变了调用方式(会被同事打死吧)

 
# -*- coding:utf-8 -*-
user_status = False
def login(func):
    _username = "lin"
    _password = "123"
    global user_status
    if user_status == False:
        username = input("user:")
        password = input("password:")
        if username == _username and password == _password:
            print("welcome login....")
            user_status = True
        else:
            print("username or password error")
    else:
        print("用户已通过验证............")
    if user_status == True:
        func()
def home():
    print("-------首页-------")
def america():
    print("-------欧美专区-------")
def japan():
    print("-------日韩专区-------")
def shandong():
    print("-------山东专区-------")
login(shandong)
login(japan)
login(home)
login(america)
#D:\python\python.exe F:/运维笔记/python/函数/函数-装饰器2.py
user:lin
password:123
welcome login....
-------山东专区-------
用户已通过验证............
-------日韩专区-------
用户已通过验证............
-------首页-------
用户已通过验证............
-------欧美专区-------

第三次修改:利用函数装饰器
 
# -*- coding:utf-8 -*-
user_status = False
def login(func):#shandong
    def inner(*style,**kwargs):   #AAA #非固定参数
        _username = "lin"
        _password = "123"
        global user_status
        if user_status == False:
            username = input("user:")
            password = input("password:")
            if username == _username and password == _password:
                print("welcome login....")
                user_status = True
            else:
                print("username or password error")
        else:
            print("用户已登录...........")
        if user_status:
            func(*style,**kwargs)        #shandong(AAA)
    return inner
@login
def home():
    print("-------首页-------")
@login
def america():
    print("-------欧美专区-------")
@login
def japan():
    print("-------日韩专区-------")
@login  #login(shandong)        #装饰器
def shandong(style):   #加了一个参数
    print("-------山东专区-------",style)

shandong("AAA")  #inner(AAA)
japan()
america()
home()

#D:\python\python.exe F:/运维笔记/python/函数/函数-装饰器3.py
user:lin
password:123
welcome login....
-------山东专区------- AAA
用户已登录...........
-------日韩专区-------
用户已登录...........
-------欧美专区-------
用户已登录...........
-------首页-------

#或者---------------------------------------------------------------------------------------------------

# -*- coding:utf-8 -*-
user_status = False
def login(func):#shandong
    def inner(*style,**kwargs):#AAA
        _username = "lin"
        _password = "123"
        global user_status
        if user_status == False:
            username = input("user:")
            password = input("password:")
            if username == _username and password == _password:
                print("welcome login....")
                user_status = True
            else:
                print("username or password error")
        else:
            print("用户已登录...........")
        if user_status:
            func(*style,**kwargs)#shandong(AAA)
    return inner
def home():
    print("-------首页-------")
def america():
    print("-------欧美专区-------")
def japan():
    print("-------日韩专区-------")
def shandong(style):
    print("-------山东专区-------",style)

shandong = login(shandong)   #inner
japan = login(japan)
america = login(america)
home = login(home)
shandong("AAA")  #inner(AAA)
japan()
america()
home()
#D:\python\python.exe F:/运维笔记/python/函数/函数-装饰器3.py
user:lin
password:123
welcome login....
-------山东专区------- AAA
用户已登录...........
-------日韩专区-------
用户已登录...........
-------欧美专区-------
用户已登录...........
-------首页-------

扩展-函数装饰器带参数

比如用QQ登陆或者微信登陆


 
# -*- coding:utf-8 -*-
user_status = False
def login(auth_type):#qq
    def outer(func):#AAA
        def inner(*style,**kwargs):#AAA
            _username = "lin"
            _password = "123"
            global user_status
            if user_status == False:
                username = input("user:")
                password = input("password:")
                if username == _username and password == _password:
                    print("welcome login....")
                    user_status = True
                else:
                    print("username or password error")
            else:
                 print("用户已登录...........")
            if user_status:
                func(*style,**kwargs)#AAA
        return inner
    return outer
@login('WX')
def home():
    print("-------首页-------")
@login('WB')
def america():
    print("-------欧美专区-------")
@login('QQ')
def japan():
    print("-------日韩专区-------")
@login('QQ') #shandong = login('qq')(shandong) = inner
def shandong(style):
    print("-------山东专区-------",style)
# xx = login('qq')#outer
# print(xx)
# shandong = xx(shandong)
# print(shandong)
shandong('AA')
japan()
america()
home()

#D:\python\python.exe F:/运维笔记/python/函数/函数-装饰器带参数.py
user:lin
password:123
welcome login....
-------山东专区------- AA
用户已登录...........
-------日韩专区-------
用户已登录...........
-------欧美专区-------
用户已登录...........
-------首页-------
温馨提示如有转载或引用以上内容之必要,敬请将本文链接作为出处标注,如有侵权我会在24小时之内删除!

欢迎使用手机扫描访问本站