• Python学习笔记四


    一.装饰器

        1.知识储备

           函数对象

        函数可以被引用

                  函数可以当参数传递

                  返回值可以是函数

                  可以当作容器的元素

    def func1():
        print (666)
    def func2():
        print (666)
    def func3():
        print (666)
    list1=[func1,func2,func3]
    for i in list1:
        i()

           *args:接收溢出的位置参数

      **kwargs:接收溢出的关键字参数

           名称空间与作用域

         2.闭包函数

            闭包函数的定义:定义在函数内部的函数,特点是:包含对外部作用域而不是全局作用域名字的引用。这个函数就称为闭包函数。

      闭包函数的两个特征:内部函数要引用外部函数的变量,外部函数的返回值是内部函数。

      例子:

      

      当函数内部需要一个变量的时候,有两种方式给函数传入变量,

      第一种:为函数添加一个参数。

      第二种:把这个函数变成闭包函数,也就是在函数外部添加一个函数。把变量写在外部函数内,或者当作参数传给外部函数。将内部函数的函数名return一下,这样内部函数就被外部函数包起来了。

       闭包特性:python遇到闭包,不会释放名称空间。

         3.装饰器

             为什么要用装饰器?

             开放封闭原则:对扩展是开放的,对修改是关闭的

                       1. 不修改被装饰对象的源代码           2. 不修改被装饰对象的调用方式。

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

             什么是装饰器?

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

             

       带参数的装饰器,怎么写?

           4.练习题:

              一,编写函数,(函数的执行时间是随机的)

    import time
    def a():
        x = time.strftime('%Y-%m-%d %X')
        print(x)
    a()

    结果:

    D:\Python36\python.exe F:/python/第一课/while-lianxi.py
    2017-10-14 08:40:11

              二,编写装饰器,为函数加上统计时间的功能。

    
    
    #这种是采用传参的方式,虽然没有修改index和home函数的源代码,但是修改了它们的调用方式。所以需要采用装饰器。
    import time
    def timmer(tongji_hanshu):
    # tongji_hanshu=home
    def inner():
    start_time=time.time()
    tongji_hanshu()
    stop_time=time.time()
    print("函数执行时间: %s" %(stop_time-start_time))
    return inner
    @timmer #语法糖
    def index():
    time.sleep(3)
    print("welcome to index page!")
    index()
    @timmer
    def home():
    time.sleep(5)
    print("welcome to home page!")
    home()

    结果:

    D:\Python36\python.exe F:/python/第一课/while-lianxi.py
    welcome to index page!
    函数执行时间: 3.0001718997955322
    welcome to home page!
    函数执行时间: 5.000285863876343

           三. 编写装饰器,为函数加上认证的功能。

    import time
    def outter(func):
        def auth():
            username=input("输入用户名: ").strip()
            password=input("输入密码: ").strip()
            if username=='yangjianbo' and password=='123':
                print ("登录成功!")
                func()  #这么写死了
            else:
                print("登录失败!")
        return auth
    @outter
    def index():
        time.sleep(3)
        print("welcome to index page!")
    index()

    结果:

    D:\Python36\python.exe F:/python/第一课/while-lianxi.py
    输入用户名: yangjianbo
    输入密码: 123
    登录成功!
    welcome to index page!

    四:编写装饰器,为多个函数加上认证功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码。

    #这种情况是针对index,没有参数的函数,如果被装饰的函数有参数,如何修订装饰器。
    import time
    def outter(func):
        def auth(*args,**kwargs):
            username=input("输入用户名: ").strip()
            password=input("输入密码: ").strip()
            if username=='yangjianbo' and password=='123':
                print ("登录成功!")
                func(*args,**kwargs)  #这么写死了
            else:
                print("登录失败!")
        return auth
    @outter
    def index():
        time.sleep(3)
        print("welcome to index page!")
    index()
    @outter  #home=outter(home)
    def home(username):
        time.sleep(2)
        print("welcome %s to home page!" %username)
    home('yangjianbo')

    结果:

    D:\Python36\python.exe F:/python/第一课/while-lianxi.py
    输入用户名: yangjianbo
    输入密码: 123
    登录成功!
    welcome to index page!
    输入用户名: yangjianbo
    输入密码: 123
    登录成功!
    welcome yangjianbo to home page!

     根据题目要求:只要登录成功,以后就不需要再登录。所以上面的代码还需要修改。

    import os
    import time
    login_status=False
    def outter(func):
        def auth(*args,**kwargs):
            if  login_status is True:
                return func(*args,**kwargs)
            else:
                username=input("输入用户名: ").strip()
                password=input("输入密码: ").strip()
                with open('account.txt','r',encoding='utf-8') as accout:
                        accout=accout.read().strip('\r\n').split('|')
                        if username==accout[0] and password==accout[1]:
                            print ("登录成功!")
                            login_status=True
                            func(*args,**kwargs)
                        else:
                            print("登录失败!")
        return auth
    @outter  #index=outter(index)
    def index():
        time.sleep(3)
        print("welcome to index page!")
    index()
    
    @outter
    def home(username):
        time.sleep(2)
        print("welcome %s to home page!" %username)
    home('yangjianbo')

    结果:

    D:\Python36\python.exe F:/python/第一课/while-lianxi.py
    Traceback (most recent call last):
    File "F:/python/第一课/while-lianxi.py", line 158, in <module>
    index()
    File "F:/python/第一课/while-lianxi.py", line 140, in auth
    if login_status is True:
    UnboundLocalError: local variable 'login_status' referenced before assignment

    上面报错的分析:说局部变量login_status在引用之前没有指定.

    我明明定义在全局作用域了,为什么报错?

    解决方法:在函数内,添加一个关键字global,表示引用全局变量。

    修改后的代码:

    import os
    import time
    login_status=False
    def outter(func):
        def auth(*args,**kwargs):
            global login_status
            if  login_status is True:
                return func(*args,**kwargs)
            else:
                username=input("输入用户名: ").strip()
                password=input("输入密码: ").strip()
                with open('account.txt','r',encoding='utf-8') as accout:
                        accout=accout.read().strip('\r\n').split('|')
                        if username==accout[0] and password==accout[1]:
                            print ("登录成功!")
                            login_status=True
                            func(*args,**kwargs)
                        else:
                            print("登录失败!")
        return auth
    @outter  #index=outter(index)
    def index():
        time.sleep(3)
        print("welcome to index page!")
    index()
    
    @outter
    def home(username):
        time.sleep(2)
        print("welcome %s to home page!" %username)
    home('yangjianbo')

    结果:没有报错了。

     第四个装饰器最后版本:

    import time
    user_status={"user":None,"login_status":False}
    def outter(func):
        def auth(*args,**kwargs):
            if user_status['user'] and user_status['login_status']:
                res=func(*args, **kwargs)
                return res
            username=input("输入用户名: ").strip()
            password=input("输入密码: ").strip()
            if username=='yangjianbo' and password=='123':
                print ("登录成功!")
                user_status['user']=username
                user_status['login_status']=True
                res=func(*args, **kwargs)
                return res
            else:
                print("登录失败!")
        return auth
    @outter
    def index():
        time.sleep(3)
        print("welcome to index page!")
        # return 123
    index()
    @outter
    def home(username):
        time.sleep(2)
        print("welcome to %s home page" % username)
        # return 456
    
    home('yangjianbo')
    

     练习五  编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录

    import time
    import random
    user={"user":None,"login_time":None,'timeout':0.03}
    
    def timmer(func):
        def inner(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('%s' %(stop_time-start_time))
            return res
        return inner
    def outter(func):
        def auth(*args,**kwargs):
            if user['user']:
                timeout=time.time()-user['login_time']
                if timeout<user['timeout']:
                    res=func(*args, **kwargs)
                    return res
            username=input("输入用户名: ").strip()
            password=input("输入密码: ").strip()
            if username=='yangjianbo' and password=='123':
                user['user']=username
                user['login_time']=time.time()
                res=func(*args, **kwargs)
                return res
            else:
                print("登录失败!")
        return auth
    @outter
    def index():
        time.sleep(random.randrange(3))
        print("welcome to index page!")
    
    index()
    
    
    @outter
    def home(username):
        time.sleep(random.randrange(3))
        print("welcome to %s home page" % username)
    
    
    home('yangjianbo')
    

      练习六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果

    from urllib.request import urlopen
    
    def outer(url):
        def get():
            f=urlopen(url).read()
            return f
        return get
    baidu=outer('http://www.baidu.com')
    sohu=outer('http://www.sohu.com')
    baidu=baidu()
    sohu=sohu()
    
    

      练习七:拿到下载的页面,保存到一个文件中。

    from urllib.request import urlopen
    
    def outer(url):
        def get():
            f=urlopen(url).read()
            return f
        return get
    baidu=outer('http://www.baidu.com')
    sohu=outer('http://www.sohu.com')
    baidu=baidu()
    sohu=sohu()
    with open('baidu.html','w',encoding='utf-8') as f:
        f.write(baidu.decode('utf-8'))
    

      

    六. 迭代器

          可迭代对象

        内部含有'__iter__'方法的数据就是可迭代对象

        s1='abcdef'

        print (dir(s1))

        print('__iter__' in dir(s1))

          迭代器对象

        内部含有'__iter__'方法并且含有'__next__'方法就是迭代器

      如何将可迭代对象转换为迭代器对象

        list1=[1,2,3,4]

        iter1=iter(list1)  #可迭代对象转换为迭代器

        print(iter1)

        print(iter1.__next__())

      迭代器的特点

        1.  非常节省内存

        2.  他满足惰性机制

        3.  一条走到黑

      利用while循环模拟for循环

        list1=[1,2,3,4]

        iter1=iter(list1)

        while 1:

          try:

            print(iter1.__next__())

          except StopIteration:

            break

    七. 生成器

      自己用python代码写的迭代器

      生成器的定义:

        1.  函数式写法,构建生成器

        2.  只要函数中出现yield,那么他就不是函数了,它是生成数函数。

    八.列表推导式

      凡是用列表推导式构建的数据,python代码都可以构建,列表推导式都可以构建。

      循环模式

      list1=[i for i in range(1,200)]

           print (list1)

      筛选模式

    九.生成器表达式

    十.列表推导式与生成器表达式

      优点:构造简单,一行完成。

      缺点:不能排错

         不能构建复杂的数据结构

      

      

        

           

    一往无前虎山行,拨开云雾见光明
  • 相关阅读:
    20165105 学习基础和C语言基础调查
    2017-2018网络攻防第四周作业
    2017-2018-2 20165233 实验三 敏捷开发与XP实践
    20165233 2017-2018-2 《Java程序设计》第九周学习总结
    Linux学习笔记(一)
    第三周学习总结
    数据结构C++,线性表学习
    uname()系统调用学习
    cd
    go连接数据库并执行文件中的sql语句
  • 原文地址:https://www.cnblogs.com/yangjianbo/p/7643124.html
Copyright © 2020-2023  润新知