装饰器

不得不说,这是对初学者最难以理解的概念了,虽然我学过面向对象,但还是被搞懵逼了。。前面还好理解,主要是后面“装饰器的装饰器”我理解不了。装饰器工厂,根据传入的参数不同去返回不同的装饰器,我不得不在网上查了很多资料去弄懂它,如果没搞清楚这个概念,我是没法安安心心往下学的~~

这里特别要感谢刘志军的这篇文章,完美的解决了我的疑惑:

https://zhuanlan.zhihu.com/p/27449649

装饰器可以在不修改源代码,和原调用方式的基础上,给原有函数增加功能。当然,可以增加功能,只能在原有函数的前面或者后面增加功能,但是没办法改变原有函数的逻辑。要实现一个装饰器,要先掌握几个基本的概念:

1.函数也是一种“变量”    2.高阶函数   3.嵌套函数   4,闭包。

1.函数也是一种“变量”如何理解?

例如,def  sayhi()

      print ("hello,everyone!")

如果打印sayhi,就是0x0000000001ECE730,一个内存地址。

如果调用sayhi(),内存地址后面加个括号就调用这个函数。

函数定义,把函数体当成字符串存放在内存中,用函数名指向它,调用之前,并不会管函数体是什么内容

2.高阶函数。把一个函数名当做参数传给另一个函数,或者返回值中包含函数名

def  dec(func):

  print("in  decorator")

  func()

函数名作为参数传给函数

3,引用计数。

Python内存回收机制,当没有变量名指向某个常量时,即改常量引用计数为0,Python就回收该常量,函数也是一样,没有函数名指向它,或者程序结束就回收该函数体内容

匿名函数  lambda x : x*3 没有函数名指向它,如果给它赋值,calc = lambda x:x*3 就不会马上回收

4.嵌套函数。在函数里定义一个新函数,并返回新函数

def  dec(func):

  def wrapper(*args, **kwargs):

    #  原函数前面增加功能

    res = func(*args,  **kwargs)

    #  原函数后面增加功能

    return res

  return wrapper

这就是个装饰器decorator,在被装饰函数前面加上:func = dec(func)

改成方便的语法糖写法:@dec

5 .闭包closure

def  closure(str):

  def decrator(func):

    def wrapper():

      ....

      if (str)

        func()

      else

        ....

      ....

    return wrapper

  return decrator

@closure(str='1') 相当于  func = closure('1')(func)

@closure(str='2') 相当于  func = closure('2')(func)

把参数给了装饰器,可以生产各种类型的装饰器。。根据传的值str判断

生成器

生成器是一次生成一个值的特殊类型函数(是一个函数的内存地址)。可以将其视为可恢复函数。调用该函数将返回一个可用于生成连续 x 值的生成器【Generator】
简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。

列表生成式:gen = [i  for i in range(10)]  生成一个list 名为gen = [0 , 1, 2, 3, 4, 5, 6, 7, 8, 9]这个列表已经保存在内存中,可以根据下标访问其中任意一个元素。

想一下,如果元素有几百万个,是不是都要全部在内存中放着准备取用呢?而且可能并不会用到第几百万个元素,该如何解决内存问题呢??

这时候生成器generator就产生了:

在上面列表生成式方括号改为圆括号变成一个生成器   gen =  (i   for i in range(10))

这时候gen = generator object <genexpr> at 0x0000000001DF87D8变成了一个地址。当然也就无法通过下标去访问某个元素了。

要访问某个元素就只能通过gen.next()方法去访问。访问一个生成一个。直到出现你想访问的元素。把上面的列表生产式改写一下,换一种写法:

def gen(i):
"i表示长度,而且每次取数据都是从1开始循环,从1取到i,yield返回n并记录该中断点"
n = 1
while n <= i:
yield n
n += 1
return "done-----" genner = gen(10) # 第一种调用生成器的方式,用whil true + next
while True: # 循环到第10个以后就不能next了,因为跳出了while循环yield不了,就抛异常StopIteration
try:
print(genner.__next__())
except StopIteration as e:
print(e.value)
break # 第二种调用生成器的方式,用for循环,这里看出gen(10)是一个迭代器了
for i in gen(10):
print(i)

是不是可以认为,生成器用for循环的方式去访问,就叫做“迭代器”??????

注意:生成器的牛逼之处在于yield关键字,你定义的时候就指明了这个生成器的长度。后面每次next()都是接着上一个netx()的后面。所以可以在next()中间做其他事情,因为不会影响结果。

还可以利用send()给yield关键字传值并激活yield,   next()只能激活yield

生成器的并行计算:

'''
简单的消费者生产者模型,又是一个简单的协程。 send(a)的作用是将a的值传给yield,并且激活yield。而next()的作用只是激活yield。 消费者模型中,有Alex和Lee两个消费者,吃包子的过程实际上是顺序执行的,只是计算机的速度太快 如果把他们分开显示,可以看成是同步发生的,这就是一个简单的协程
''' import time def consummer(name):
print("%s,准备开始吃包子了!!" % name)
while True:
baozi = yield
print("包子%s 来了,被%s 吃了!" %(baozi, name)) def producer(name):
c1 = consummer("Alex")
c2 = consummer("Lee")
c1.__next__()
c2.__next__()
for i in range(6):
time.sleep(1)
print("%s 做了包子%s分两半。。。。。。。。" %(name, i))
c1.send(i)
c2.send(i) producer("bob")
------------------------------执行结果-------------------------------------

Alex,准备开始吃包子了!!
Lee,准备开始吃包子了!!
bob 做了包子0分两半。。。。。。。。
包子0 来了,被Alex 吃了!
包子0 来了,被Lee 吃了!
bob 做了包子1分两半。。。。。。。。
包子1 来了,被Alex 吃了!
包子1 来了,被Lee 吃了!
bob 做了包子2分两半。。。。。。。。
包子2 来了,被Alex 吃了!
包子2 来了,被Lee 吃了!
bob 做了包子3分两半。。。。。。。。
包子3 来了,被Alex 吃了!
包子3 来了,被Lee 吃了!
bob 做了包子4分两半。。。。。。。。
包子4 来了,被Alex 吃了!
包子4 来了,被Lee 吃了!
bob 做了包子5分两半。。。。。。。。
包子5 来了,被Alex 吃了!
包子5 来了,被Lee 吃了!

迭代器

1可迭代对象(Iterable): 可直接作用于for循环的对象统称为Iterable可迭代对象,例如 list tuple  dict  set   str 等,判断方法 isinstance(xxx, Iterable)

2.迭代器(Iterator):可以被next()函数调用并不断返回下一个值的对象,它们表示一个惰性的计算序列,可以看出:生成器一定是迭代器,而迭代器不一定是生成器   判断方法:  isinstance(xxx,Iterator)

3.Iterable变为Iterator: iter()方法

from collections import Iterator, Iterable

def gen(i):
"i表示长度,而且每次取数据都是从1开始循环,从1取到i,yield返回n并记录该中断点"
n = 1
while n <= i:
yield n
n += 1
return "done-----" genner = gen(10)
list1 = [5,2,3,4,5,6,9] print(isinstance(genner, Iterator)) # 判断是否为迭代器
print(isinstance(genner,Iterable)) # 判断是否为可迭代对象
lst = iter(list1) # 用iter()方法把list1变成迭代器
print(lst.__next__()) # 打印结果5

为什么list   dict  str  等不是迭代器???

因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被netx()函数调用并不断返回下一个数据,知道没有数据时抛出StopIteration错误。

可以把数据流看成一个有序序列,但不知道序列的长度,只能不断通过netx()按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要下一个数据时才计算

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

Python学习第二阶段,day1, 装饰器,生成器,迭代器的更多相关文章

  1. Python自动化 【第四篇】:Python基础-装饰器 生成器 迭代器 Json & pickle

    目录: 装饰器 生成器 迭代器 Json & pickle 数据序列化 软件目录结构规范 1. Python装饰器 装饰器:本质是函数,(功能是装饰其它函数)就是为其他函数添加附加功能 原则: ...

  2. python学习之day5,装饰器,生成器,迭代器,json,pickle

    1.装饰器 import os import time def auth(type): def timeer(func): def inner(*args,**kwargs): start = tim ...

  3. 跟着ALEX 学python day4集合 装饰器 生成器 迭代器 json序列化

    文档内容学习于 http://www.cnblogs.com/xiaozhiqi/  装饰器 : 定义: 装饰器 本质是函数,功能是装饰其他函数,就是为其他函数添加附加功能. 原则: 1.不能修改被装 ...

  4. Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化

    本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解 ...

  5. python基础-函数之装饰器、迭代器与生成器

    1. 函数嵌套 1.1 函数嵌套调用 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数 def bar(): print("from in the bar.") def f ...

  6. python三大器(装饰器/生成器/迭代器)

    1装饰器 1.1基本结构 def 外层函数(参数): def 内层函数(*args,**kwargs); return 参数(*args,**kwargs) return 内层函数 @外层函数 def ...

  7. Python三大神器:装饰器,迭代器,生成器

    一.装饰器 由于一个函数能实现一种功能,现在想要在不改变其代码的情况下,让这个函数进化一下,即能保持原来的功能,还能有新的"技能",怎么办? 现已经存在一个自定义的函数func1, ...

  8. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

  9. python学习笔记之装饰器、生成器、内置函数、json(五)

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里面 ...

  10. python第四周:装饰器、迭代器、内置方法、数据序列化

    1.装饰器 定义:本质是一个函数,(装饰其他函数)就是为其他函数添加附加功能 原则:不能修改被装饰函数的源代码,不能修改被装饰函数的调用方式 实现装饰器的知识储备: 函数即“变量”.每当定义一个函数时 ...

随机推荐

  1. 上百例Silverlight网站及演示汇总,供友参考

    毁灭2012 博客园 首页 新闻 新随笔 联系 管理 订阅 随笔- 125  文章- 0  评论- 446  上百例Silverlight网站及演示汇总,供友参考   今天我将发现的Silverlig ...

  2. android 使用AlarmManager定时启动service

    private static AlarmManager am; private static PendingIntent pendingIntent; /** * 使用 AlarmManager 来 ...

  3. [noi.ac_D1T2]sort

    https://www.zybuluo.com/ysner/note/1289967 题面 定义"翻转排序":每次操作均为把区间\([l,r]\)中所有数倒过来,即\(swap(a ...

  4. 正则表达式:(?=a)是什么意思?

    1.(?=a) 表示我们需要匹配某样东西的前面. 2.(?!a) 表示我们需要不匹配某样东西. 3.(?:a) 表示我们需要匹配某样东西本身. 4.(?<=a) 表示我们需要匹配某样东西的后面. ...

  5. Builder Design pattern

    string assemblyName = ConfigurationSettings["BuilderAssembly"]; string builderName = Confi ...

  6. 如何彻底卸载Vs2015

    当我们卸载了VS2015想再安装VS软件的时候,发现安装路径根本更改不了. 网上查的由很多方法. 要真的找注册表去完全删除时非常繁琐的这里可以使用的方法就是 先下载卸载软件 https://githu ...

  7. bzoj 4809: 皇后【dfs】

    爆搜卡线过 并不知道正解是啥 #include<iostream> #include<cstdio> using namespace std; const int N=40; ...

  8. 牛客网NOIP赛前集训营 提高组(第七场)

    中国式家长 2 链接:https://www.nowcoder.com/acm/contest/179/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K, ...

  9. P3207 [HNOI2010]物品调度

    传送门 完了题目看错了--还以为所有的\(x,y\)都要一样--结果题解都没看懂-- 先考虑如果已经求出了所有的\(pos\)要怎么办,那么我们可以把\(0\)也看做是一个箱子,然后最后每个箱子都在一 ...

  10. [JOI2014] 小笼包

    题面 : https://www.ioi-jp.org/joi/2013/2014-yo/2014-yo-t6/2014-yo-t6.html 题解 dp + 康托展开 一看这题不知道怎么处理 只能枚 ...