zoukankan      html  css  js  c++  java
  • day 13 闭包函数,装饰器,迭代器

    闭包函数

    函数传参的方式一
    def inner(x):
      print(x)

    inner(1) # 1

    函数的传参方式二 (闭包函数,把变量和函数一起包起来,下次要用直接调用)
    def outter(x):
      def inner():
        print(x)
      return inner

    inner = outter(2) 
    inner() # 2 

    def get_res(url):
      res = requests.get(url)
      print(res.text)
    get_res('https://www.taobao.com')

    def func(url):
      def get_res():
        res = requests.get(url)
        print(res.text)
      return get_res

    baidu_spider = func('https://www.baidu.com') 
    baidu_spider()


    装饰器

    装饰的工具(函数),这个函数有装饰的作用装饰器本质就是一个函数A,装饰的对象也是一个函数B,用一个函数A去装饰一个函数B,

    装饰器要满足两个条件:

    1. 不改变函数B的调用方式

    2. 不改变函数B的源码

    def A():
      """装饰器"""
      pass

    def B():
      """被装饰的对象"""
      pass
    B()

    def index():
      """被装饰的函数"""
      print('hello, index')

    index()

    1. 打印函数运行的时间

    1.1 改变了函数体代码,没改变调用方式

    import time

    def index():
      start = time.time()
      print('hello, index')
      time.sleep(1)
      end = time.time()
    print(end - start)

    index()


    1.1 # 没改变调用方式,也没改变源码,但是不通用
    import time
    def index():
      """被装饰的函数"""
      print('hello, index')

    start = time.time()
    index()
    time.sleep(1)
    end = time.time()
    print(end-start)

    1.2没改变源码,也没改变调用方式
    import time
    def deco(func):    # func = index
      """装饰器函数"""
      def inner():
        start = time.time()
        func()    # index
        time.sleep(1)
        end = time.time()
        print(end - start)
      return inner

    def index():
      """被装饰的函数"""
      print('hello, index')

    index = deco(index) # index = inner
    index()

    2.检测index的运行的时间,但是不能改变index的调用方式,以及index的源码
    # 写一个装饰器
    def deco(func):    # func = 真正的index
      """装饰器"""
      def f1():     # 重新创建的index
        start = time.time()
        func() # 真正的index()
        end = time.time()
        print(end-start)
     return f1

    index(重新创建的index) = deco(index(真正的index))   # index = f1

    index() 


    import time
    def deco(func):
      def f1(*args, **kwargs):
        print('args:',args)    # (10,) 元组只有一个元素时,必须要加逗号
        print('kwargs:',kwargs)
        start = time.time()
        res = func(*args, **kwargs) # 真正的index()
        end = time.time()
        print(end - start)
        return res
      return f1

    @deco # 语法糖(更精简的代码) index = deco(index)
    def index(x, a=1):
      print('x', x)
      print('a', a)
      print('hello index')
      time.sleep(1)
     return 123

    index = deco(index) # index = f1
    index(10) # f1(1)


    装饰器模板
    def login(func):
      def inner(*args, **kwargs):
      # 登录功能
        username = input('usrename:')
        pwd = input('pwd:')
        if username == 'nick' and pwd == '123':
          print('登录成功')
          res = func(*args, **kwargs) # shopping()
          return res
        else:
          print('登录失败')
      return inner

    def time_count(func):
      def inner(*args,**kwargs):
        start = time.time()
        res = func(*args,**kwargs)
        end = time.time()
        print(end-start)
        return res
      return inner


    def outter(func):
      def inner(*args,**kwargs):
      # 加功能
        func(*args,**kwargs)
      return inner

    先执行离得近的语法糖,在执行远的语法糖
    @time_count
    @login
    @outter
    def shopping():
      print('shopping')
    shopping()


    三层装饰器: 给双层装饰器加参数
    判断账号密码来自于哪个地方
    def auth(engine):
      def login(func):
        def inner(*args, **kwargs):
        # 登录功能
        if engine == 'file':
          username = input('usrename:')
          pwd = input('pwd:')
          if username == 'nick' and pwd == '123':
            print('登录成功')
            func(*args, **kwargs) # shopping()
          else:
            print('登录失败')
        elif engine == 'db':
          print('账号密码来自于数据库,非法请求')
        return inner
      return login

    @auth('db')
    def shopping():
      print('shopping')


    login = auth('db')      # login = login
    shopping = login(shopping)    # shopping = inner
    shopping() # inner()

    装饰器模版
    # 双层装饰器

    def outter(func):
      def wrapper(*args, **kwargs): # wrapper是未来要运行的函数
      # 加功能
        func(*args, **kwargs) # func是被装饰的函数
      return wrapper


    @outter
    def shopping():
      print('shopping')


    # 三层装饰器:给双层装饰器加参数的

    def sanceng(engine):
      def outter(func):
        def wrapper(*args, **kwargs): # wrapper是未来要运行的函数
        # 加功能
          print(engine)
          func(*args, **kwargs) # func是被装饰的函数
        return wrapper
      return outter


    迭代器对象

    更新换代, 重复, 基于上一次的结果推出下一次的结果

    1)可迭代(具有__iter__方法) 对象

    x = 1 # 不可迭代对象
    s = 'nick' # 可迭代对象
    s.__iter__()
    lt = [1, 2, 3] # 可迭代对象
    dic = {'a': 1, 'b': 2} # 可迭代对象
    tup = (1,) # 元组只有一个元素必须得加逗号# 可迭代对象
    se = {1, 2, 3} # 可迭代对象
    f = open('time.py') # 可迭代对象

    def func(): # 不可迭代对象
      pass


    有__iter__()方法的对象就是可迭代对象,然后出了数字类型和函数之外都是可迭代对象
    s = 'nick'
    s_iter = s.__iter__()
    print(s_iter.__next__()) # 基于索引(基于上一次结果)通过__next__进行迭代


    s = 'nick'
    s[0]

    dic = {'a':1,'b':2} # 可迭代对象
    dic['a']
    dic_iter = dic.__iter__() # 不依赖索引取值 # 迭代器对象
    print(dic_iter.__next__())



    2)迭代器对象: 具有__iter__以及__next__方法的叫做迭代器对象
    s = 'nick' # 可迭代对象,不属于迭代器对象
    s.__iter__()
    lt = [1, 2, 3] # 可迭代对象,不属于迭代器对象
    dic = {'a': 1, 'b': 2} # 可迭代对象,不属于迭代器对象
    tup = (1,) # 元组只有一个元素必须得加逗号# 可迭代对象,不属于迭代器对象
    se = {1, 2, 3} # 可迭代对象,不属于迭代器对象
    f = open('time.py') # 可迭代对象,迭代器对象

    #只有文件是迭代器对象

    3)for循环原理 # 迭代循环

    lt = [1,2,3]
    lt_iter = lt.__iter__()
    while 1:
      try:
        print(lt_iter.__next__())
      except StopIteration:
        break


    for i in lt: # 可迭代对象;迭代器对象 # 不依赖索引取值,而是迭代取值
    print(i)
    1. 首先使用iter把lt变成迭代器对象;对于文件也要使用iter方法吧文件再一次iter下
    2. 然后使用next方法进行迭代取值
    3. 判断StopIteration异常,遇到异常终止

    f = open('time.py') # 可迭代对象,迭代器对象
    f_iter = f.__iter__()
    print(id(f_iter))
    f_iter_iter = f_iter.__iter__()
    print(id(f_iter_iter))

    可迭代对象: 具有__iter__方法的对象就是可迭代对象,除了数字类型和函数都是可迭代对象
    迭代器对象: 具有__iter__和__next__方法的都是迭代器对象,只有文件
    迭代器对象一定是可迭代对象; 可迭代对象不一定是迭代器对象


    for循环 == 迭代循环

    dic ={'a':1,'b':2}
    for i in dic:
      print(i)

    1. 把lt(可迭代对象/迭代器对象)用__iter__方法转换成迭代器对象
    2. 使用__next__取出迭代器里的所有值
    3. 使用__next__方法取尽迭代器中的所有值,一定会报错,通过异常捕捉退出while循环
    # 解决了不依赖索引取值

    也可以使用iter(),next()
    dic ={'a':1,'b':2}
    dic_iter = iter(dic)
    print(next(dic_iter))
    print(next(dic_iter))










  • 相关阅读:
    MySQL三种备份
    四层和七层负载均衡的区别
    触发器及触发器的作用
    sql 存储过程
    自动ftp 上传
    #题目:有10 台被监控主机、一台监控机,在监控机上编写脚本,一旦某台被监控机器/ 分区适用率大于80%, 就发邮件报警放到crontab 里面, 每10 分钟检查一次
    /proc/sys 子目录的作用
    Linking code for an enhanced application binary interface (ABI) with decode time instruction optimization
    facebook webdriver 学习
    WebDriverException: Message: A session is either terminated or not started
  • 原文地址:https://www.cnblogs.com/wwei4332/p/11341922.html
Copyright © 2011-2022 走看看