目录:

一、Debug操作

二、函数的装饰器

三、迭代器

四、生成器

一、Debug操作:

程序出问题的时候可以用debug来看一下代码运行轨迹,然后找找问题在哪里

1.先给即将debug的代码打上断点:

 2.打完断点之后右键点击debug:

 3.然后依次点击开始按钮让程序开始一步步运行:

二、函数的装饰器:

定义:装饰器为其他函数添加附加功能,本质上还是一个函数

原则:①不修改被修饰函数的源代码

      ②不修改被修饰函数的调用方式

有这样一个函数:demo()

先导入时间模块,然后函数执行时先睡两秒,在执行打印

 import time
def demo():
time.sleep(2)
print("welcome sir")
demo()

现在想为demo()函数添加一个统计函数运行时间的功能,但是要遵循开放封闭原则

初步思想:

 import time
def demo():
start_time = time.time()
time.sleep(2)
print("welcome sir")
end_time = time.time()
print("运行时间%s" %(end_time-start_time))
demo()

这样就完美解决了,但是,我们要用可持续发展的眼光来看,假如有十万个代码,我们这样一个一个添加,你不加班谁加班?

这个时候我们可以用函数的思维来解决

进步思想:

 import time
def demo():
time.sleep(2)
print("welcome sir")
def timmer(func_name):
def inner():
start_time = time.time()
func_name()
end_time = time.time()
print("运行时间%s" %(end_time-start_time))
return inner
res = timmer(demo)
res()

这样看起来非常Nice,用到了高阶函数,嵌套函数,函数闭包,但是我们违反了开放封闭原则,这个时候把res 改成 demo 就可以了

在这里有一个命令,可以直接略过这个赋值,让代码看起来更美观,执行效率更高

 import time
def timmer(func_name):
def inner():
start_time = time.time()
func_name()
end_time = time.time()
print("运行时间%s" %(end_time-start_time))
return inner
@timmer
def demo():
time.sleep(2)
print("welcome sir")
demo()

ok,代码完成,这其实就是一个函数装饰器,我们来解释一下代码运行顺序

为装饰器加上返回值:

 import time
def timmer(func_name):
def inner():
start_time = time.time()
res = func_name()
end_time = time.time()
print("运行时间%s" %(end_time-start_time))
return res
return inner
@timmer
def demo():
time.sleep(2)
return '函数demo的返回值'
val = demo()
print(val)

有参数的装饰器:

 import time
def timmer(func_name):
def inner(*args,**kwargs):
start_time = time.time()
res = func_name(*args,**kwargs)
end_time = time.time()
print("运行时间%s" %(end_time-start_time))
return res
return inner
@timmer
def demo(name,age):
time.sleep(2)
return '函数demo的返回值,姓名:%s,年龄:%s' %(name,age)
val = demo('zrh',20)
print(val)

图示流程:

三、迭代器: 

可迭代协议:只要包括了"_iter_"方法的数据类型就是可迭代的

 print([1,2,3].__iter__())  #打印结果:<list_iterator object at 0x000002E7F803DE88>

iterable 形容词 可迭代的

 from collections import Iterable  #检测一个对象是否可迭代
print(isinstance('aaa',Iterable))
print(isinstance(123,Iterable))
print(isinstance([1,2,3],Iterable))

迭代器协议:迭代器中有 __next__ 和 __iter__方法 

iterator 名词 迭代器,迭代器 就是实现了能从其中一个一个的取出值来

检测参数是不是个迭代器:

 from collections import Iterator
print(isinstance(lst_iterator,Iterator))
print(isinstance([1,2,3],Iterator))

在python里,目前学过的所有的可以被for循环的基本数据类型都是可迭代的,而不是迭代器。

迭代器包含可迭代对象

可迭代对象转换为迭代器:

可迭代对象._iter_()  这样就变成可一个迭代器

lise_case = [1,2,3].__iter__()

迭代器存在的意义:

1.能够对python中的基本数据类型进行统一的遍历,不需要关心每一个值分别是什么
2.它可以节省内存 —— 惰性运算

for循环的本质:

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

只不过for循环之后如果参数是一个可迭代对象,python内部会将可迭代对象转换成迭代器而已。

四、生成器:

Iterator 迭代器

Gerator 生成器

生成器其实就是迭代器,生成器是用户写出来的

 def generator_func():    #生成器函数
print(123)
yield 'aaa'
generate = generator_func()
print(generate)
print(generate.__next__())
# 打印结果:
# <generator object generator_func at 0x0000018F3942E8C8>
#
# aaa

带yield关键字的函数就是生成器函数,包含yield语句的函数可以用来创建生成器对象,这样的函数也称为生成器函数。

yield语句与return语句的作用相似,都是用来从函数中返回值,return语句一旦执行会立刻结束函数的运行

而每次执行到yield语句并返回一个值之后会暂停或挂起后面的代码的执行,下次通过生成器对象的__next__()、for循环或其他方式索要数据时恢复执行

生成器具有惰性求值的特点

生成器运行顺序:

生成器问题注意1:

 def generator_func():    #生成器函数
print(123)
yield 'aaa'
print(456)
yield 'bbb'
ret_1 = generator_func().__next__()
print(ret_1)
ret_2 = generator_func().__next__()
print(ret_2)
# 输出结果:
#
# aaa
#
# aaa
def generator_func(): #生成器函数
print(123)
yield 'aaa'
print(456)
yield 'bbb'
generate_1 = generator_func()
ret_1 = generate_1.__next__()
print(ret_1)
ret_2 = generate_1.__next__()
print(ret_2)
# 输出结果:
#
# aaa
#
# bbb

第6行和第8行相当于创建了两个生成器,第20行创建了一个生成器,21行和23行都用的是第20行创建的生成器,所以输出结果不一样

生成器问题注意2:

for循环完了之后生成器数据就取完了,再继续print数据的话,就会报错,因为没有数据可以读了。

一个函数有两个以上的yield,才算一个必要的生成器,如果只有一个yield,那还不如老老实实的去写return

生成器实例:

需求:写一个实时监控文件输入的内容,并将输入内容返回的函数

 def tail(filename):
f = open(filename,encoding='utf-8')
f.seek(0,2)
while True:
line = f.readline()
if not line:continue
yield line
tail_g = tail('file_1')
for line in tail_g:print(line,end='')

生成器send用法:

1.send和next工作的起止位置是完全相同的
2.send可以把一个值作为信号量传递到函数中去
3.在生成器执行伊始,只能先用next
4.只要用send传递参数的时候,必须在生成器中还有一个未被返回的yield

 def average_func():
total = 0
count = 0
average = 0
while True:
value = yield average
total += value
count += 1
average = total/count
g = average_func()
print(g.__next__())
print(g.send(30))
print(g.send(20))

代码解释:

装饰器生成激活函数装置:

 def wrapper(func):
def inner(*args,**kwargs):
g = func(*args,**kwargs)
g.__next__()
return g
return inner
@wrapper
def average_func():
total = 0
count = 0
average = 0
while True:
value = yield average
total += value
count += 1
average = total/count
g = average_func()
print(g.send(30))

利用函数装饰器写了一个函数激活装置,就不用在18行之前的send前使用 next 了,next 在第4行已经实现了。

python-Debug、函数装饰器的更多相关文章

  1. python基础—函数装饰器

    python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...

  2. Decorator——Python初级函数装饰器

    最近想整一整数据分析,在看一本关于数据分析的书中提到了(1)if __name__ == '__main__' (2)列表解析式 (3)装饰器. 先简单描述一下前两点,再详细解说Python初级的函数 ...

  3. python基础-----函数/装饰器

    函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...

  4. python 复习函数 装饰器

    # 函数 —— 2天 # 函数的定义和调用 # def 函数名(形参): #函数体 #return 返回值 #调用 函数名(实参) # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),* ...

  5. day11 python之函数装饰器

    一,什么是装饰器? 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事 ...

  6. python 匿名函数&装饰器

    匿名函数 关键字lambda表示匿名函数,冒号前面的x表示函数参数匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果. >>> list(map(l ...

  7. python闭包函数&装饰器

    一.函数引用 函数可以被引用 函数可以被赋值给一个变量 def hogwarts(): print("hogwarts") # hogwarts() # 函数调用 print(ho ...

  8. Python之函数装饰器

    在实际中,我们可能需要在不改变函数源代码和调用方式的情况下,为函数添加一些新的附加功能,能够实现这种功能的函数我们将其称之为装饰器.装饰器本质上其实还是是一个函数,用来装饰其它函数,为函数添加一些附加 ...

  9. python 之 函数 装饰器

    5.8 装饰器 1 开放封闭原则 软件一旦上线后,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能的扩展是开放的 也就是说我们必须找到一种解决方案: 能够在不修改一个功能源代码以及调用方式的前提 ...

  10. Python中函数装饰器及练习

    )])   ,,],)

随机推荐

  1. Spring入门(十四):Spring MVC控制器的2种测试方法

    作为一名研发人员,不管你愿不愿意对自己的代码进行测试,都得承认测试对于研发质量保证的重要性,这也就是为什么每个公司的技术部都需要质量控制部的原因,因为越早的发现代码的bug,成本越低,比如说,Dev环 ...

  2. QTP8.2--安装流程

    一.安装说明: 1.进入安装文件夹,运行QTP8.2安装文件setup,进入安装向导后直接单击“QuickTest Professional 安装”选项,由于破解文件存在缺陷,所以请不要改变安装路径c ...

  3. javaweb中文中乱码分析与解决

    要想解决乱码的问题, 最好的办法是先弄清楚javaweb中数据传送的原理. 本文件将简单的讲解客户端的请求和服务器响应中编码的转换过程, 以及如何解决乱码的 问题. request(req):  se ...

  4. Linux 远程登录命令telnet

    一.telnet简介: telnet命令通常用来远程登录.telnet程序是基于TELNET协议的远程登录客户端程序.Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准 ...

  5. 如何增强VR的vection/self-motion?

    上一节讲到了vection是给玩家带来“移动感”的因素,它提供良好VR体验的关键之一.那么VR中我们一般用哪些方式来提供vection呢?1 首先来简单了解一下人体和空间相关的感知机制. 视觉线索 v ...

  6. jq方法写选项卡的基本原理以及三种方法

    使用jq写选项卡,告别了繁琐的循环以及命名规范 基本原理: 1.当某一个btn被选中时,将这个btn的背景颜色设为橘色,其余兄弟btn背景颜色设为空(none) 2.如果子div与btn的索引相同,就 ...

  7. JAVA-JDBC-c3p0连接池配置

    配置c3p0数据源的方式有三种,分别是手动配置,xml文件配置和properties文件配置,这三种配置方式存在一种即可. 通常来讲,用文件配置更方便书写和阅读 配置如下: 注:*号部分写自己的配置 ...

  8. 【Java】Java 单文件下载及重命名

    代码(仅供参考): /* * 另存为 */ @RequestMapping("/saveAs.do") public @ResponseBody void saveAs(Strin ...

  9. JavaScript中闭包的使用和各种继承介绍

    一.什么是闭包?     (1)闭包的概念:a.闭包就是函数嵌套时,让局部变量变成自由变量的环境,是一种让局部变量进化的方式.                 b.定义在一个函数内部的函数.      ...

  10. day 20作业

    目录 1.下面这段代码的输出结果将是什么?请解释. 2.多重继承的执行顺序,请解答以下输出结果是什么?并解释. 3.什么是新式类,什么是经典类,二者有什么区别?什么是深度优先,什么是广度优先? 4.用 ...