python-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、函数装饰器的更多相关文章
- python基础—函数装饰器
python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...
- Decorator——Python初级函数装饰器
最近想整一整数据分析,在看一本关于数据分析的书中提到了(1)if __name__ == '__main__' (2)列表解析式 (3)装饰器. 先简单描述一下前两点,再详细解说Python初级的函数 ...
- python基础-----函数/装饰器
函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...
- python 复习函数 装饰器
# 函数 —— 2天 # 函数的定义和调用 # def 函数名(形参): #函数体 #return 返回值 #调用 函数名(实参) # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),* ...
- day11 python之函数装饰器
一,什么是装饰器? 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事 ...
- python 匿名函数&装饰器
匿名函数 关键字lambda表示匿名函数,冒号前面的x表示函数参数匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果. >>> list(map(l ...
- python闭包函数&装饰器
一.函数引用 函数可以被引用 函数可以被赋值给一个变量 def hogwarts(): print("hogwarts") # hogwarts() # 函数调用 print(ho ...
- Python之函数装饰器
在实际中,我们可能需要在不改变函数源代码和调用方式的情况下,为函数添加一些新的附加功能,能够实现这种功能的函数我们将其称之为装饰器.装饰器本质上其实还是是一个函数,用来装饰其它函数,为函数添加一些附加 ...
- python 之 函数 装饰器
5.8 装饰器 1 开放封闭原则 软件一旦上线后,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能的扩展是开放的 也就是说我们必须找到一种解决方案: 能够在不修改一个功能源代码以及调用方式的前提 ...
- Python中函数装饰器及练习
)]) ,,],)
随机推荐
- php下api接口的并发http请求
php下api接口的并发http请求 ,提高app一个页面请求多个api接口,页面加载慢的问题: func_helper.php/** * 并发http请求 * * [ * 'url' //请求地址 ...
- 在wxml中直接写js代码(wxs)
我们在h5开发中,很多时候要在html中写到js代码,这个很容易实现.但是在微信小程序开发中,是不能直接在wxml中写js代码的,因此就有了wxs.在wxml中用wxs代码,有以下几种方式(在小程序文 ...
- OpenGL在ubuntu下的成功配置
sudo apt-get update sudo apt-get install build-essential sudo apt-get install libgl1-mesa-dev sudo a ...
- python实现感知机线性分类模型
前言 感知器是分类的线性分类模型,其中输入为实例的特征向量,输出为实例的类别,取+1或-1的值作为正类或负类.感知器对应于输入空间中对输入特征进行分类的超平面,属于判别模型. 通过梯度下降使误分类的损 ...
- Java之字符流读写文件、文件的拷贝
字符流读数据 – 按单个字符读取 创建字符流读文件对象: Reader reader = new FileReader("readme.txt"); 调用方法读取数据: int d ...
- java8 Optional使用总结
[前言] java8新特性 java8 函数接口 java8 lambda表达式 Java 8 时间日期使用 java8 推出的Optional的目的就是为了杜绝空指针异常,帮助开发者开发出更优雅的代 ...
- linux 指定tomcat的具体路径
1.直接修改catalina.sh中对应的变量 CATALINA_HOME=/xx/xxCATALINA_BASE=/xx/xx (该方法需要找到所有的变量进行修改,不适合,推荐使用方式2) 2.在p ...
- Python内置函数之enumerate() 函数
enumerate() 函数属于python的内置函数之一: python内置函数参考文档:python内置函数 转载自enumerate参考文档:python-enumerate() 函数 描述 e ...
- js 验证数据类型的4中方法
1.typeof 可以检验基本数据类型 但是引用数据类型(复杂数据类型)无用: 总结 : typeof 无法识别引用数据类型 包括 bull; 2.instanceof是一个二元运算符,左操作数 ...
- python串口助手
最近项目中要使用模拟数据源通过向外发送数据,以前都是用C#编写,最近在研究python,所以就用python写了一个串口助手,方便以后的测试. 在电脑上通过虚拟串口助手产生两个虚拟串口,运行编写的串口 ...