一. iter&yield迭代器

    1.1 iter

 names = iter(['zeng', 'chun', 'yun'])
print(names)
print(names.__next__())
print(names.__next__())
print(names.__next__())
print(names.__next__()) #第一个输出打印迭代器对象
#第二三四次next方法每次都去获取迭代对象的值,每次往下取一个值,直到取完
#第五次输出 print(names.__next__())
#StopIteration,因为迭代器里面的对象已经取完了,所以出现这个异常

  1.2 yield

 def fei(num):
x, y, z = 0, 0, 1
while x < num:
if x == 0: # 当第一次循环时,返回数列0
yield y # 生成器返回一个迭代器对象
else: # 否则返回z
yield z
y, z = z, y + z
x += 1 print(fei(9).__next__()) # 只从迭代器里面取一次值
# fei(9).__next__()
for i in fei(9): # 通过遍历获取迭代器内容
print(i)

   1.3  生成器的异步应用

import time

def consumer(name):  # 定义消费者函数
print("%s 准备吃包子啦!" % name) # 打印消费者名字
while True:
baozi = yield # 当代码运行到这时,返回一个迭代器对象,当对象第二次调用时,会接收值并赋值给baozi
print("包子[%s]来了,被[%s]吃了!" % (baozi, name)) # 打印当前使用的迭代器对象,及接收的值 def producer(*name): # 定义一个生产者函数,并使用动态参数
if len(name) == 3: # 当传入三个参数时,调用三次消费者函数方法
c = consumer(name[0])
c2 = consumer(name[1])
c3 = consumer(name[2])
c.__next__() # 通过函数内置方法获取迭代器内部元素
c2.__next__()
c3.__next__()
print("老子开始准备做包子啦!")
for i in range(1, 11):
time.sleep(1)
print("做了%s个包子!" % len(name))
c.send(i) # 通过迭代器方法的send属性给生成器传送值
c2.send(i)
c3.send(i) producer("alex", 'zengchunyun', 'peiqi') # 创建一个生产者对象,并传入三个消费者名字

  二. 装饰器

    2.1 首先了解一下函数

def func():
print('hello') print(func) # 第一次输出的是一个函数对象
print(type(func)) #第二次输出的是一个类型为函数
func() # 第三次才是执行这个函数
print(func()) #第四次则是执行函数后,并打印函数的返回结果,函数没有指定返回内容,所以使用默认返回值,None
print(type(func())) # 第五次也是先执行函数,然后打印返回值对象的类型,所以可以看出,返回值对象类型是NoneType # 第一次
#<function func at 0x100756f28>
# 第二次
#<class 'function'>
# 第三次
#hello
# 第四次
#hello
#None
# 第五次
#hello
#<class 'NoneType'>

    通过上述总结一句话,函数不加括号是没有执行的,这时的这个函数名只是一个函数对象,而加括号后,函数将会执行函数体代码,

  最终这个函数则是函数执行完后的返回的对象

    2.2 装饰器

    有了上面这个基础后,我们再来看看装饰器

 def wrapper(func):
print(func) # 打印参数
return func # 返回参数 @wrapper # 使用装饰器
def index():
print('welcome') index() # 执行顺序是,解释器从上往下读取代码
# 遇到函数时,只加载定义的函数对象,并不执行函数体代码
# 然后遇到装饰器@wrapper时
# 解释器会跳到这个wrapper函数
# 然后执行这个wrapper函数内部代码
# 我们通过观察得知,这个wrapper函数一定会传入一个参数,因为测试发现,不传入一个参数,程序执行会抛出需要一个参数的异常错误.
# 通过分析这个参数,发现这个参数打印结果是一个函数对象
# 然后wrapper函数体代码执行完毕后,继续往下执行,遇到函数index,
# 也是只是加载这个函数对象,并不执行内部函数体代码
# 当遇到代码index()时,结合到我们之前积累的函数基础知识,
# 这个写法实际是开始执行一个函数,所以解释器会跳到指定的index函数对象
# 然后开始执行这个函数体代码块,
# 整个执行过程就结束了 # 以下为代码执行结果
# <function index at 0x1010ed0d0>
# welcome

    可能你对上面这个过程还是不够了解装饰器,那么我们再通过下面这个例子说明装饰器的工作原理

 def wrapper(func):
print(func) # 打印参数
# return func # 返回参数 ,现在注释掉这个返回值 @wrapper # 使用装饰器
def index():
print('welcome') print(type(index)) # 加上一句输出类型代码的语句
index() #我们在上面这个例子中,把函数wrapper中的返回值给注释掉了,代码执行结果 # function index at 0x1011ed0d0>
# <class 'NoneType'>
# Traceback (most recent call last):
# File "/Users/zengchunyun/PycharmProjects/s12/day4/noteext.py", line 68, in <module>
# index()
# TypeError: 'NoneType' object is not callable # 首先我们来分析一下这个结果
# 你会不会很惊讶?我们只是针对第一个例子的代码仅仅只是注释掉一个返回值而已,代码就不能工作了 # 首先解释器还是从上往下读取代码
# 遇到函数时,只加载定义的函数对象,并不执行函数体代码
# 然后遇到装饰器@wrapper时
# 解释器会跳到这个wrapper函数
# 然后执行这个wrapper函数内部代码
# 通过分析这个参数,发现这个参数打印结果是一个函数对象
# 然后wrapper函数体代码执行完毕后,继续往下执行,遇到函数index,
# 也是只是加载这个函数对象,并不执行内部函数体代码
# 关键点来了
# 代码执行到打印对象类型的语句时,结果却是一个NoneType的类型,根据我们之前对函数的基本介绍,这里的类型应该是一个函数类型才对啊
# 怎么回事呢?我们明明定义了index函数,怎么打印的类型却是NoneType类型?
# 我们之前也看到只有函数没有返回值时,函数默认会返回一个None对象,故而这个对象的类型也就是NoneType类型了,
# 我们仅仅只是加了一个装饰器代码@wrapper,其他都没有变,为什么会出现这个情况呢
# 我们上一个例子已经说明,这个装饰器会携带一个参数,这个参数为一个函数对象,
# 实际上,这个时候这个装饰器会对引用装饰器的函数,也就是我们这里的index函数进行重构,
# 所以如果我们如果不返回一个函数对象时,那么这个时候的index实质是一个普通的对象,不是函数类型了
# 它已经被赋予None这个值了,而None不是一个函数对象,所以就没有调用方法,就不能以括号方式执行
# 这时解释器读到index()这句代码,大家依据之前的理念,都能看出这个是去执行index这个函数内部代码块的语句
# 但是这个时候,解释器却在这个时候抛出异常了
# 返回类型错误,TypeError: 'NoneType' object is not callable
# 这个错误说我们的index执行后,是不能被调用的,只有对象类型为函数才有内置调用方法
# 因为这个index已经被重构,返回值已经变成了None,也就是说,index 对象目前仅仅是一个普通标识符,不是函数

    2.3 装饰器的高级应用

      我们通过上面的事咧可知,只要代码执行到装饰器标识符,都会去执行装饰器函数体,但是这个不是我们想要的,我们希望的是

    只有我们调用引用装饰器的函数时,才去执行这个装饰器函数体,那怎么办呢?我们知道,只有类型是函数对象时,代码是不会被执行,

    只是加载到内存而已,那好吧,我们直接返回一个函数对象不就好了?

      我们来看看代码实现

 def wrapper(func):
def inner():
print(func) # 输出是一个函数对象
func() # 这里实际是执行我们这个例子中原先定义的index函数对象的函数体
return inner
# print(func) # 打印参数
# return func # 返回参数 ,现在注释掉这个返回值 @wrapper # 使用装饰器
def index():
print('welcome') print(type(index)) # 加上一句输出类型代码的语句
index() # 首先看看这种情况
# 代码执行到index()时,啥也没有,我们明明打印了一句welcome,为什么没有输出信息,这也就再次证明了,
# 实质是这个index已经等价于装饰器的inner这个函数了,因为装饰器返回的是inner这个函数对象
# 我们既想用装饰器,又想执行调用装饰器的内部代码时怎么办呢?
# 我们已经知道,装饰器会携带一个参数,这个参数是引用装饰器对象的一个函数对象
# 既然是一个函数对象,那我们是不是可以直接执行这个函数对象呢?
# 答案是肯定的,所以我们直接在这个装饰器里执行这个函数对象,等于就是执行我们原先那个函数的函数体
# 这个例子就满足了我们的需求,当我们不调用index函数时,得到的仅仅是一个函数对象,并不会执行函数体代码

  有参数的函数,或装饰器实现传参实例

 # 无参装饰器,有参函数
def wrapper(func):
def inner(name): # 这个参数最终会传给这个函数体内部需要调用参数的对象
func(name) # 这个参数个数是由原来的函数,也就是我们这里的index函数决定参数个数的
return inner @wrapper # 使用装饰器
def index(name): # 传入一个参数
print('welcome %s' % name) index('zengchunyun')

无参装饰器,有参函数

 # 无参装饰器,多参函数
def wrapper(func):
def inner(*args): # 使用动态参数
func(*args)
return inner @wrapper # 使用装饰器
def index(*args): # 传入一个参数
print('welcome %s' % ' '.join(args)) index('zengchunyun', 'goodbye')

无参装饰器,多参函数

 # 无参装饰器,多参函数2
def wrapper(func):
def inner(*args, **kwargs): # 使用动态参数
func(*args, **kwargs)
return inner @wrapper # 使用装饰器
def index(*args, **kwargs): # 传入一个参数
print('welcome %s' % ' '.join(args)) index('zengchunyun', 'goodbye')

无参装饰器,多参函数2

 # 有参装饰器,多参函数
def one():
print('one') def two():
print('two') def func(arg1, arg2):
def wrapper(oldfunc):
def inner(*args, **kwargs): # 使用动态参数
arg1()
arg2()
oldfunc(*args, **kwargs)
return inner
return wrapper @func(one, two) # 使用装饰器
def index(*args, **kwargs): # 传入一个参数
print('welcome %s' % ' '.join(args)) index('zengchunyun', 'goodbye') # 解释器遇到装饰器,由于这个装饰器是一个可执行函数
# 故而先执行函数,再次就成了我们所认知的普通装饰器了

# 有参装饰器,多参函数

最新文章

  1. WPF简单模拟QQ登录背景动画
  2. listview的ViewHolder优化
  3. HDOJ 1561 The more, The Better
  4. Uva 11090 在环中
  5. iOS开发Block的使用
  6. Colored Linux Man pages
  7. 如何写一个网页标题title的闪动提示(转)
  8. ICT测试原理
  9. linux基本语法和常用运维命令
  10. salesforce lightning零基础学习(三) 表达式的!(绑定表达式)与 #(非绑定表达式)
  11. 集群通信组件Tribes之整体介绍
  12. 随手记-egg入门
  13. https://finance.sina.com.cn/realstock/company/sh600522/nc.shtml
  14. WebClient, HttpClient, HttpWebRequest ,RestSharp之间的区别与抉择
  15. Web系统大规模并发——秒杀与抢购 秒杀系统优化与预防措施
  16. Python操作redis学习系列之(集合)set,redis set详解 (六)
  17. [leetcode]91. Decode Ways解码方法
  18. 关于bottle WEB框架中签名cookie的一点理解
  19. iOS 技术篇:渐变色的简单实现方式
  20. Redis搜索引擎设计

热门文章

  1. 解决css样式被内置样式覆盖的问题
  2. git checkout 命令详解
  3. 【SSH】 之 Struts2
  4. UML 之 四种关系
  5. TOMCAT配置外部应用
  6. SU Demos-06Selecting Traces
  7. nodejs随记02
  8. CSS3-网站导航,transform,transition
  9. 10324 Global Warming dfs + 二分
  10. delphi override、overload、reintroduce的区别-0613.txt