我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python3 基础(4)-装饰器、生成

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python3 基础(4)-装饰器、生成

装饰器(本质:函数)

  1. 定义:为其他函数添加附加功能(装饰器对于被装饰函数是“透明的”、“不存在的”);执行过程:调用被装饰函数实际上是调用修饰函数

  2. 原则:

    1. 不能修改被装饰函数的源代码;

    2. 不能修改被装饰函数的调用方式。

  3. 实现装饰器的知识补充:

    1. 函数即“变量”:

      1. 调用前先定义(即要先有内存地址空间、函数的执行顺序)

      2. 可赋值给其他函数名

        clipboard.png

        def bar():

           print("in the bar")

        #函数bar()在以下三处位置,只有1、2处时,调用foo()才正确执行

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

        #1#

        def foo():

           print("in teh foo")

           bar()

        #2#

        foo()

        #3#

    2. 高阶函数

      1. 条件一:一个函数名(被装饰的函数)当作实参传给另一个函数(装饰函数);(满足原则一不修改被装饰函数的源代码)

      2. 条件二:返回值中包含函数名(装饰函数)。(满足原则二不修改被装饰函数的调用方式)

    3. 函数嵌套

  4. 举例:

    1. 统计运行时间的装饰器

      带无参数、固定参数、无固定参数的函数

      print("分割线".center(50,"="))

      import time

      def timmer(func):

         def wrapper(*args,**kwargs):

             start_time=time.time()

             res = func(*args,**kwargs)   #这里的参数由wrapper函数的参数传递

             stop_time=time.time()

             print("func run time is %s"%(stop_time-start_time))

             return res            #返回被装饰函数的返回值

         return wrapper   #返回装饰函数wrapper的内存地址

      @timmer  #同test1=timmer(test1);

                 # 理解:执行timmer(test1),得到返回值wrapper内存地址,再把wrapper内存地址赋值给test1

      def test1():

         time.sleep(1)

         print("my name is test1")

         return "test1"

      @timmer   #同test2=timmer(test2);

                 # 理解:执行timmer(test2),得到返回值wrapper内存地址,再把wrapper内存地址赋值给test2

      def test2(name,age):

         time.sleep(1)

         print("my name is %s,I'm %s" %(name,age))

      test1()   #要配合上面@timmer使用,同timmer(test1)()

      print(test1())

      test2("chen",40)   #要配合上面@timmer使用,同timmer(test2)("chen",40)

      print(test2("chen",40))

      #结果

      my name is test1

      func run time is 1.000598430633545

      my name is test1

      func run time is 1.0012288093566895

      test1

      my name is chen,I'm 40

      func run time is 1.0007030963897705

      my name is chen,I'm 40

      func run time is 1.0007030963897705

      None

    2. 页面登录认证

      无参装饰器:

      有参装饰器:

      user,passwd = "chen","123456"

      def auth(func):

         def wrapper(*args,**kwargs):

             username = input("Username: ").strip()

             password = input("Password: ").strip()

             if user == username and passwd == password:

                 print("\033[32;1m通过本地认证!\033[0m")

                 return func(*args,**kwargs)

             else:

                 exit("\033[31;1m错误的用户名或密码\033[0m")

         return wrapper

      def index():

         print("welcome to index page")

      @auth

      def home():

         print("welcome to home page")

         return "from home"

      @auth

      def bbs():

         print("welcome to bbs page")

         return "from bbs"

      index()

      home()

      bbs()

      #结果

      welcome to index page

      Username: chen

      Password: 123456

      通过本地认证!

      welcome to home page

      Username: chen

      Password: 123456

      通过本地认证!

      welcome to bbs page

      user,passwd = "chen","123456"

      def auth(auth_type):

         def outer_wrapper(func):

             def wrapper(*args,**kwargs):

                 if auth_type == "local":

                     username = input("Username: ").strip()

                     password = input("Password: ").strip()

                     if user == username and passwd == password:

                         print("\033[32;1m通过本地认证!\033[0m")

                         return func(*args,**kwargs)

                     else:

                         exit("\033[31;1m错误的用户名或密码\033[0m")

                 elif auth_type == "ldap":

                     print("\033[32;1m远程认证!\033[0m")

             return wrapper

         return outer_wrapper

      def index():

         print("welcome to index page")

      @auth(auth_type="local")   #同home=auth(auth_type="local")(home)

      def home():

         print("welcome to home page")

         return "from home"

      @auth(auth_type="ldap")   #同bbs=auth(auth_type="ldap")(bbs)

      def bbs():

         print("welcome to bbs page")

         return "from bbs"

      index()

      home()

      bbs()

      #结果

      welcome to index page

      Username: chen

      Password: 123456

      通过本地认证!

      welcome to home page

      远程认证!

生成器 

    创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

    而生成器节省大量的空间,因为生成器只有在调用时才会生成相应的数据。

  1. 知识补充:

    1. 列表生成式(列表解析):

      a = [i*2 for i in range(10)]

      print(a)

      输出:

      [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

    2. 斐波那契数列:

      def fib(max):

         n, a, b = 0, 0, 1

         while n < max:

             print(b)

             a, b = b, a + b

             n = n + 1

         return 'done'

      fib(10)

      输出:

      1 1 2 3 5 8 13 21 34 55

  2. 生成器特点:

    1. 生成器只有在调用时才会生成相应的数据

    2. 只记录当前位置,用到哪记录到哪

    3. 只有一个方法__next__(),python2 为next()

  3. 生成器的实现:

    1. 方法一:列表生成式。

      a = ( i*2 for i in range(10))

      print(a)

      输出:

      <generator object <genexpr> at 0x054D1F30>

    2. 方法二:在函数定义中包含yield关键字。

    3. 这时,这个函数就不再是一个普通函数,首次调用__next__()的时候执行生成器函数,遇到yield语句时返回,再次执行(__next__()或send()或for、while等)时将从上次返回的yield语句处继续执行。

      def fib(max):

         n, a, b = 0, 0, 1

         while n < max:

             # print(b)

             yield b

             a, b = b, a + b

             n = n + 1

         return "done"

      fib(5)

      print(fib(5))   #此时不会获取return的值

      输出:

      <generator object fib at 0x04F8AF90>


  4. 获取生成器的值:

    1. 使用__next__()

      print(a.__next__())

      print(a.__next__())

      print(a.__next__())

      f = fib(5)

      print(f.__next__())

      print(f.__next__())

    2. for、while循环

      f = fib(5)

      for i in f:

          print(i)

  5. 应用:

    1. 当使用__next__()获取生成器的值的数量超过总的数量时:

      def fib(max):

         n, a, b = 0, 0, 1

         while n < max:

             # print(b)

             yield b

             a, b = b, a + b

             n = n + 1

         return "done"   #作为错误提示信息

      f = fib(100)

      #当获取生成器的值的数量超过总的数量时会报错

      while True:

          x = f.__next__()

          print('f:', x)

      #解决方式:捕获StopIteration错误

      while True:

          try:

              x = f.__next__()

              print('f:', x)

          except StopIteration as e:

              print('Generator return value:', e.value)

              break

    2. 在单线程实现并发运算的效果(携程??)

      补充:send()用于给yield传值,但是send传值时,要求生成器已执行到yield语句处(就是send前面至少要有一个__next__(),这样才能保证生成器运行到yield处

      import time

      def consumer(name):

         print("%s 准备吃包子啦!" %name)

         while True:

             baozi = yield   #这里的yield由send传值

             print("[%s]包子来了,被[%s]吃了!" %(baozi,name))

      def producer(name):

         c = consumer('A')

         c2 = consumer('B')

         c3 = consumer('C')

         c.__next__()

         c2.__next__()

         c3.__next__()

         print("师傅开始蒸包子啦!")

         for i in ["猪肉馅","韭菜馅","白菜馅","豆沙馅"]:

             time.sleep(1)

             print("%s包子出炉了!"%i)

             c.send(i)

             c2.send(i)

             c3.send(i)

      producer("alex")

迭代器

  1. Iterable对象:可以直接作用于for循环的对象统称为可迭代对象

    1. 集合数据类型,如list、tuple、dict、set、str等;

    2. 生成器generator,包括带yield的generator function。

    3. 内置函数:map()、filter()、zip(a,b)

  2. Iterator对象:可以被next()函数调用并不断返回下一个值的对象称为迭代器对象

    1. 生成器generator

    2. 内置函数:map()、filter()、zip(a,b)

  3. 判断一个对象是否是Iterable对象:

    #使用isinstance()

    >>> from collections import Iterable

    >>> isinstance([], Iterable)

    True

    >>> isinstance({}, Iterable)

    True

    >>> isinstance('abc', Iterable)

    True

    >>> isinstance((x for x in range(10)), Iterable)

    True

    >>> isinstance(100, Iterable)

    False


  4. 判断一个对象是否是Iterator对象:

    #使用isinstance()

    >>> from collections import Iterator

    >>> isinstance((x for x in range(10)), Iterator)

    True

    >>> isinstance([], Iterator)

    False

    >>> isinstance({}, Iterator)

    False

    >>> isinstance('abc', Iterator)

    False


  5. 把Iterable对象变成Iterator对象:

    #使用iter()函数:

    >>> isinstance(iter([]), Iterator)

    True

    >>> isinstance(iter('abc'), Iterator)

    True

    #将列表变为iterator对象

    a = [1,2,3,4]

    b=iter(a)

    print(type(b))

    print(b.__next__())

    print(b.__next__())

    #输出

    <class 'list_iterator'>

    1

    2


  6. 你可能会问,为什么list、dict、str等数据类型不是Iterator?

    1. 这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

    2. Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

  7. 补充:

    1. Python的for循环本质上就是通过不断调用next()函数实现的,例如:

      for x in [1, 2, 3, 4, 5]:

         pass

      #等价于

      it = iter([1, 2, 3, 4, 5])   # 首先获得Iterator对象:

      while True:

         try:

             x = next(it)   # 获得下一个值:

         except StopIteration:   # 遇到StopIteration就退出循环

             break



免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

python3 基础(4)-装饰器、生成

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

python3 基础(4)-装饰器、生成

装饰器(本质:函数)定义:为其他函数添加附加功能(装饰器对于被装饰函数是“透明的”、“不存在的”);执行过程:调用被装饰函数实际上是调用修饰函数原则:不能修改被装饰函数的源代码;不能修改被装饰函数的调用方式。实现装饰器的知识补充:函数即“变
2023-01-31

python3基础:生成器

在python中,边循环边计算的机制就称为生成器(generator)。使用生成器当用到数据的时候在生成,这样可以节约空间,提高效率。生成器是一种特殊类型的迭代器,所以也会有__init__()和__next__()两个方法:__iter_
2023-01-31

Python3 迭代器,生成器,装饰器

1.迭代器迭代器有两个基本方法,iter()和next(),next()完成后会引发StopIteration异常a='abcdef'b=iter(a)#创建迭代器对象print(type(b))while True:try:print(n
2023-01-30

python3 迭代器、生成器、装饰器、

本节内容迭代器&生成器装饰器Json & pickle 数据序列化软件目录结构规范作业:ATM项目开发 1.列表生成式迭代器&生成器列表生成式孩子我现在有个需求看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列
2023-01-31

python3基础学习(双色球随机生成器

最近学习了python3的一些基础语法,语法基本搞懂了,因此自己想通过一些小东西进行实战下,以此来加深学习!  实战一:双色球随机生成器,使用语法:python3 xx.py 红球个数 蓝球个数import randomimport sys
2023-01-31

Python装饰器基础详解

装饰器(decorator)是一种高级Python语法。装饰器可以对一个函数、方法或者类进行加工。在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果。相对于其它方式,装饰器
2022-06-04

生成器,迭代器,装饰器

生成器 (generator)概念在Python中, 一边循环一边计算的机制, 称为生成器: generator 创建生成器: G = ( x*2 for x in range(5)) 可以通过 next(生成器) 函数获得生成器的下一个返
2023-01-31

python基础学习12----装饰器

装饰器可以在不修改目标函数代码的前提下, 在目标函数执行前后增加一些额外功能例如有一个简单的函数import timedef func1(): print("这是一个简单的函数") time.sleep(2)想给这个函数增加一个
2023-01-30

python-装饰器&生成器&迭代器&推

一:普通装饰器概念:在不改变原函数内部代码的基础上,在函数执行之前和之后自动执行某个功能,为已存在的对象添加某个功能普通装饰器编写的格式def 外层函数(参数) def 内层函数(*args,**kwargs) #函数
2023-01-31

python基础:迭代器与生成器

一、迭代器迭代器只能向前访问,不能后退字典,列表,元组,字符串,range都是可以迭代的对象。1、创建迭代器`dict={1:3,2:4,3:5,4:6}key = iter(dict)print(key)print(next(key))p
2023-01-31

带参装饰器,迭代器,生成器,枚举对象

一,复习'''函数的嵌套定义:在函数内部定义另一个函数闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.验证执行开放封闭原则: 功能可以拓展,但源代码与调用方式都不可以改变装饰器:装饰器名就是外层函数 @out
2023-01-31

Python基础入门(迭代器和生成器)

1 Python迭代器迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。迭代器有两个基本的方法:iter() 和 next(),且字符串、列表或元组对象都可用于创
2023-01-30

python中的生成器、迭代器、装饰器怎么使用

本篇内容介绍了“python中的生成器、迭代器、装饰器怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、装饰器由于一个函数能实现一种
2023-07-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录