python基础-函数之装饰器、迭代器与生成器
1. 函数嵌套
1.1 函数嵌套调用
函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数
def bar():print("from in the bar.")def foo():print("from in the foo.")bar()foo()
1.2 求函数最大值
def max2(x,y):if x > y:return xelse:return ydef max4(a,b,c,d):res1 = max2(a,b)res2 = max2(res1,c)res3 = max2(res2,d)return res3res = max4(2,5,3,-4) print(res)
1.3 函数嵌套定义
函数的嵌套定义:在一个函数的内部,又定义另外一个函数
def f1():x = 1def f2():print("from f2.")f2() # 只能在函数内部调用 f1()
2. 名称空间
2.1 介绍
名称空间:存放名字的地方,准确的说名称空间是存放名字与变量值绑定关系的地方。
内置名称空间:在python解析器启动时产生,存放一些python内置的名字。
全局名称空间:在执行文件时产生,存放文件级别定义的名字。
局部名称空间:在执行文件的过程中,如果调用了函数,则会产生该函数的局部名称空间,用来存放该函数内定义的名字,该名字在函数调用时生效,在函数调用结束后失效。
2.2 加载、查找顺序
加载顺序:内置名称空间 --> 全局名称空间 --> 局部名称空间
查找顺序:局部名称空间 --> 全局名称空间 --> 内置名称空间
3. 作用域
3.1 基本概念
作用域:作用的范围
全局作用域:全局存活、全局有效
局部作用域:临时存活、局部有效
查看作用域:globals(),locals()
查看全局作用域:globals()
查看局部作用域:locals()
3.2 global
局部修改全局的名字:global
针对全局不可变类型,用global进行修改
针对全局可变类型,在函数内部可以直接修改全局变量的内容
利用global,在函数内部进行修改全局变量;此种方法慎用;以后尽量避免利用局部修改全局的名字
# 不可变类型,利用global进行修改全局变量值 x = 20 def foo():global xx = 30 foo() print(x) # 此时x的值已经被修改,变为30# 可变类型的全局变量,在函数内部进行直接修改 l = [] def foo():l.append("jack") foo() print(l) # 此时l已经变为:['jack']
3.3 nonlocal
nonlocal,修改的局部变量的上一层变量,只是修改局部的变量;
x = 0 def f1():x = 100def f2():x = 200def f3():nonlocal xx = 300f3()print(x) # 利用nonlocal定义的变量 进行修改上一层的局部变量 f2()print(x) # nonlocal只修改上一层局部变量,此时打印f1定义的变量 f1()
3.2 作用域关系
作用域关系:在函数定义时就已经确定,与调用位置无关;在调用函数时,必须回到函数原来定义的位置去找作用域关系
x = 1 def f1():def f2():print(x)return f2func = f1() x = 10000 func() # 此时打印1000,只是打印的是x = 1定义的地方,只是在后面进行修改 x = 10000# 作用域关系,在定义阶段就已经确定,与调用位置无关 x = 1 def f1():def f2():print(x)return f2def foo(func):x = 30000func() # 相当于调用f2,打印x为1 foo(f1())
4. 闭包函数
4.1 定义
闭包函数简单理解就是:闭合、包裹的函数
闭包函数:定义在函数内部的函数,包含对外部作用域名字的引用,而不是对全局作用域名字的引用,那么该内部函数就称为闭包函数
4.2 实例
# wrapper称为闭包函数,定义deco内部的函数,并对外部x的引用,而变量x不是全局变量 def deco():x = 1000def wrapper():print(x)return wrapperfunc = deco() func()
4.3 闭包应用-惰性计算
爬网页的简单程序
import requests # pip3 install requests def index(url):def wrapper():# return requests.get(url).textprint(requests.get(url).text)return wrapperpython_web = index("https://www.python.org") baidu_web = index("https://www.baidu.com")python_web() baidu_web()
4.4 查看闭包函数参数
查看闭包函数外面包裹的参数
import requests # pip3 install requests def index(url):def wrapper():print(requests.get(url).text)return wrapper python_web = index("https://www.python.org") print(python_web.__closure__) # (<cell at 0x00000000021A7528: str object at 0x0000000002209DB0>,) print(python_web.__closure__[0].cell_contents) # 查看闭包函数的包裹的参数 https://www.python.org
5. 装饰器
5.1 基本概念
开放封闭原则:对扩展是开放的,对修改是封闭的
装饰器:装饰其他对象的工具
装饰器本身可以是任意可调用对象,被装饰的对象也可以是任意可调用对象
装饰器的遵循的原则:
1.不修改被装饰对象的源代码
2.不修改被调用对象的调用方式
装饰器的目的是:
在遵循1和2原则的前提,为其他可调用对象添加新功能
装饰器名:必须写在被装饰对象的正上方,并且是单独一行
5.2 装饰器前奏
5.2.1 修改源代码
import time def index():start_time = time.time()time.sleep(2)print("from in index")stop_time = time.time()print("run time is %s" % (stop_time - start_time)) index()
5.2.2 修改了调用方式
import time def wrapper(func):start_time = time.time()time.sleep(2)func()stop_time = time.time()print("run time is %s" % (stop_time - start_time))def index():time.sleep(2)print("from in index.")wrapper(index) # 修改了函数的调用方式
5.2.3 应用实例
import time def timmer(func):def wrapper():start_time = time.time()func()stop_time = time.time()print("run time is %s" %(stop_time - start_time))return wrapper @timmer # index=timmer(index) def index():time.sleep(2)print("from in index") @timmer # home=timmer(home) def home():time.sleep(2)print("from in home")index() home()
运行结果:
from in index run time is 2.0001142024993896 from in home run time is 2.0001144409179688
5.3 被装饰的对象有参数
解决装饰器的闭包函数,能够适应有参数、无参数、各种各样的参数的形式
import time def timmer(func):def wrapper(*args, **kwargs):start=time.time()func(*args, **kwargs)stop=time.time()print('run time is %s' %(stop-start))return wrapper@timmer # home=timmer(home) def home(name):time.sleep(2)print('welcome %s to home page' %name)home('jack') # hom('jack') wrapper('jack')
5.4 被装饰的对象有返回值
有返回值的情况,需要在装饰器处理有返回值的情况,也就是在wrapper最后,利用return进行返回处理结果
import time def timmer(func):def wrapper(*args, **kwargs):start=time.time()res=func(*args, **kwargs)stop=time.time()print("run time is %s" %(stop-start))return resreturn wrapper@timmer # home=timmer(home) def home(name):time.sleep(2)print("welcome %s to home page" %name)return "from home return ok."res = home('jack') # wrapper('jack') print(res) # from home return ok.
5.5 装饰器:登录认证
实行认证功能的装饰器,需要对用户输入用户名和密码进行验证,在输入正确的情况下,才执行被装饰函数的内容。
5.5.1 无参数装饰器实现认证
current_user={'user':None} def auth(func):def wrapper(*args, **kwargs):if current_user['user']: # 自带bool判断功能return func(*args, **kwargs)name=input('name: ').strip()password=input('password: ').strip()with open('db.txt', encoding='utf-8') as f:user_dic = eval(f.read())if name in user_dic and password == user_dic[name]:res=func(*args,**kwargs)current_user['user']=namereturn reselse:print('user or password error')return wrapper@auth #index=auth(index) index=wrapper def index():print('from index') @auth def home(name):print('welcome %s' %name)index() #wrapper() home('jack')
5.5.2 有参函数装饰器
current_user={"user":None} def auth(auth_type="file"):def deco(func):def wrapper(*args, **kwargs):if auth_type == "file":if current_user["user"]:return func(*args, **kwargs)name = input("name: ").strip()password = input("password: ").strip()with open("db.txt", encoding="utf-8") as f:user_dic = eval(f.read())if name in user_dic and password == user_dic[name]:res = func(*args, **kwargs)current_user["user"] = namereturn reselse:print("user or password error")elif auth_type == "mysql":print("mysql")elif auth_type == "ldap":print("ldap")else:print("not valid auth_type")return wrapperreturn deco @auth(auth_type="mysql") #@deco #index=deco(index) def index():print("from index") @auth(auth_type='file') def home(name):print("welcome %s" %name) index() #wrapper() home('jack')
5.6 装饰器的其他属性
5.6.1 被装饰函数的注释信息
需要导入functools模块,在被装饰的函数上方加@wraps(func)
from functools import wraps def decorator(func):@wraps(func)def wrapper(*args,**kwargs):res = func(*args,**kwargs)return resreturn wrapper@decorator def index():'''这是注释index信息'''print('from to index')return "in the index"print(index.__doc__) # print(help(index))
5.6.2 一个函数被多个装饰器装饰
一个函数的多个装饰器,在上面的装饰器先执行,在下面的装饰器后执行
def timmer(func):def wrapper(*args, **kwargs):print("this is timmer.")res=func(*args,**kwargs)return resreturn wrapper def auth(auth_type='file'):def deco(func):def wrapper(*args, **kwargs):print("this is auth.")return func(*args, **kwargs)return wrapperreturn deco@timmer #index=timmer(wrapper) @auth() # @deco #index=deco(index) #wrapper def index():'''这是index函数'''print('welcome to index')return "from in index"index()
6. 迭代器
6.1 解析
迭代:是一个重复的过程,每一次重复,都是基于上一次的结果而来;取出序列类型的元素,就是迭代
序列类型:列表、元组、字符串
下面的方法按照索引的取值方式,不适用没有索引的数据类型
l=['aa','bb','cc','dd'] count=0 while count < len(l):print(l[count])count+=1
不依赖索引方式,进行取值,就是迭代器;迭代非序列类型编程可能。
6.2可迭代对象
可迭代对象iterable:凡是对象下有__iter__方法:对象.__iter__,该对象就是可迭代对象
s='hello ' # 字符串 l=['a','b','c','d'] # 列表 t=('a','b','c','d') # 元组 dic={'name':'egon','sex':'m'} # 字典 set1={1,2,3} # 集合 f=open('db.txt') # 文件 s.__iter__() l.__iter__() t.__iter__() dic.__iter__() set1.__iter__() f.__iter__()
6.3迭代器对象
迭代器对象:可迭代对象执行内置的__iter__方法,得到的结果就是迭代器对象
迭代器:本身也是可迭代对象
什么是迭代器对象:
1.有__iter__,执行得到仍然是迭代本身
2.有__next__方法
dic = {'name': 'egon', 'sex': 'm', "age": 18} i = dic.__iter__() # print(i) #iterator迭代器# i.__next__() #next(i) print(next(i)) print(next(i)) print(next(i)) print(next(i)) # StopIteration l = ['a', 'b', 'c', 'd']i = l.__iter__() print(next(i)) print(next(i)) print(next(i)) print(next(i)) print(next(i)) # StopIteration
可以不依赖于索引的取值方式
l=['a','b','c','d'] dic={'name':'egon','sex':'m',"age":18} iter_l=iter(l) iter_dic=iter(dic) while True:try:# print(next(iter_l))k=next(iter_dic)print(k,dic[k])except StopIteration:break
6.4迭代器优缺点
迭代器对象的优点
1:提供了一种统一的(不依赖于索引的)迭代方式
2:迭代器本身,比起其他数据类型更省内存
l = ['a', 'b', 'c', 'd'] i = iter(l)dic = {'a': 1, 'b': 2} x = dic.keys() print(x) i = x.__iter__() # 执行__iter()__,成为迭代器对象;可以对i执行next()的方法# 文件是迭代器对象 with open('a.txt') as f:# print(next(f))# print(next(f))# print(next(f))f.read()
迭代器对象的缺点
1:一次性,只能往后走,不能回退,不如索引取值灵活
2:无法预知什么时候取值结束,即无法预知长度
l=['a','b','c','d'] i=iter(l) print(next(i)) print(next(i)) print(next(i))
6.5 for循环原理
for循环遵循迭代器协议,有__iter__方法,还有__next__方法。
for循环,利用迭代器,进行循环;for,可跟可迭代对象的数据类型;自动进行捕捉异常,自动调用__iter__方法
例如列表:for循环,先调用__iter__方法,变为迭代器对象,然后再进行循环
迭代器:有__iter__方法,为for循环准备的。
l=['a','b','c','d'] for item in l: #iter_l=l.__iter__()print(item)for item in {1,2,3,4}: # 可循环集合print(item)with open('a.txt') as f:# for line in f: #i=f.__iter__() 可循环文件 把文件变成可迭代对象# print(line)print(f is f.__iter__())
6.6 判断可迭代对象、迭代器对象
需要利用模块Iterable、Iterator进行判断
from collections import Iterable,Iterator s='hello' l=['a','b','c','d'] t=('a','b','c','d') dic={'name':'egon','sex':'m',"age":18} set1={1,2,3} f=open('a.txt')# 判断是否可迭代对象;所有对象都是可迭代对象 print(isinstance(s,Iterable)) print(isinstance(l,Iterable)) print(isinstance(t,Iterable)) print(isinstance(dic,Iterable)) print(isinstance(set1,Iterable)) print(isinstance(f,Iterable))# 判断是否迭代器对象 print(isinstance(s,Iterator)) print(isinstance(l,Iterator)) print(isinstance(t,Iterator)) print(isinstance(dic,Iterator)) print(isinstance(set1,Iterator)) print(isinstance(f,Iterator)) #只有文件是迭代器对象
7. 生成器
7.1 简介
生成器:在函数内部包含yield关键,那么该函数执行的结果是生成器
生成器就是迭代器
yield的功能:
1 把函数的结果做成迭代器(以一种优雅的方式封装好__iter__,__next__)
2 函数暂停与再继续运行的状态是由yield保存
7.2 应用实例
实例1:
def func():print("first")yield 111print("second")yield 222print("third")yield 333print("forth")g = func() from collections import Iterator print(isinstance(g,Iterator)) # 生成器就是迭代器# print(next(g)) # print('======>') # print(next(g)) # print('======>') # print(next(g)) # print('======>') # print(next(g)) for i in g: #i=iter(g)print(i)
实例2:
产生无穷无尽的值,是个重复的过程。利用生成器解决此问题。
def func(n):print('我开动啦')while True:yield nn+=1 g = func(0) # 没有任何执行效果 # print(next(g)) # print(next(g)) for i in g:print(i)
实例3:
模拟range功能,在python3中,range只是一个迭代器对象,并没有产生所需数据。
def my_range(start,stop):while True:if start == stop:raise StopIterationyield startstart+=1g = my_range(1,5) # 是个生成器,就是一个迭代器 print(next(g)) print(next(g)) print(next(g))for i in my_range(1,5):print(i)
7.3 yield与return的比较
相同:都有返回值的功能
不同:return只能返回一次值,而yield可以返回多次值
7.4 模拟tail、grep
# python3 tail.py -f access.log | grep 'error' import timedef tail(filepath):with open(filepath, 'r') as f:f.seek(0, 2)while True:line = f.readline()if line:yield lineelse:time.sleep(0.2)def grep(pattern,lines):for line in lines:if pattern in line:print(line,end='')grep('error',tail('access.log'))
8. 三元表达式
def foo(x):if x > 3:return 'ok'else:return 'no'# 利用三元表达式,使代码更简洁 x = 5 res = x if x > 3 else 'no' print(res)def max2(x,y):return x if x > y else y print(max2(1,3))name='egon' print('SB' if name == 'alex' else 'shuai')
9. 列表解析
列表解析,也就是列表生成式
列表解析,直接在列表中,写for循环进行生产列表
l=[] for i in range(10):l.append('egg%s' %i) print(l)# 产生10个值的列表 l=['egg%s' %i for i in range(10)] print(l)# 按照条件,产生一个列表,支持if判断,不支持else l=['egg%s' %i for i in range(10) if i > 5] # 只有条件成立执行,不支持else print(l)# 对原列表进行附加操作,进行生产新列表 nums=[1,2,3,4,5,6] nums_new=[item**2 for item in nums if item > 3] print(nums_new)# 对原列表根据条件进行筛选,生产新列表 names=['alex_sb','wupeiqi_sb','egon','yuanhao_sb'] names_new=[name for name in names if name.endswith('sb')] print(names_new)
10. 生成器表达式
g=('egg%s' %i for i in range(1000))
上面就是生成器,其实就是迭代器;每次在内存中就只有一条值
场景:数据量大的场景,
生成器:就是生成值。
生成器表达式:就是拿到生产数据的机器。
实例1:
g=('egg%s' %i for i in range(1000)) print(g) print(next(g)) print(next(g)) print(next(g))
实例2:
# 获取文件最长一行的值 with open('db.txt',encoding='utf-8') as f:res = max(len(line) for line in f) #python提供简写的形式,去掉多余的小括号print(res)
实例3:
模拟求总价
with open('a.txt',encoding='utf-8') as f:l = ( float(line.split()[1]) * int(line.split()[2]) for line in f) # 解决文件过大的问题print(sum(l)) #等价于 with open('a.txt', encoding='utf-8') as f:l=[]for line in f:goods=line.split()price=float(goods[1])count=int(goods[2])cost=price * countl.append(cost)print(sum(l)) #196060.0
实例4:
模拟数据库查询,根据条件进行查询
# [{'name': 'apple', 'price': 333, 'count': 3}, ] with open('a.txt',encoding='utf-8') as f:info=[{'name':line.split()[0],'price':float(line.split()[1]),'count':int(line.split()[2])} for line in f if float(line.split()[1]) >= 30000]print(info)
转载于:https://www.cnblogs.com/goodshipeng/p/7226986.html
python基础-函数之装饰器、迭代器与生成器相关推荐
- python的装饰器迭代器与生成器_python3 装饰器、列表生成器、迭代器、内置方法详解等(第四周)...
前言: 为什么要学习python3? 原因: 1.学习一门语言能力 2.通过该语言能力完成测试自动化以及独立完成自测框架知识 那么我要做什么呢? 1.每天花十个小时完成python3的学习 要在什么地 ...
- python 二——函数、装饰器、生成器、面向对象编程(初级)
本节内容 1.函数 2.装饰器 3.生成器 4.类 一.函数 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强... ...
- python find函数_Python 装饰器填坑指南 | 最常见的报错信息、原因和解决方案
本文为霍格沃兹测试学院学员学习笔记,进阶学习文末加群. Python 装饰器简介 装饰器(Decorator)是 Python 非常实用的一个语法糖功能.装饰器本质是一种返回值也是函数的函数,可以称之 ...
- python log函数_python装饰器的使用
1. 装饰者模式 装饰者模式是常用的软件设计模式之一.通过此设计模式,我们能够在不修改任何底层代码情况下,给已有对象赋予新的职责.python中可以用装饰器简单地实现装饰者模式. 1.1 将函数作为参 ...
- python之函数三装饰器
装饰器形成的过程 装饰器的作用:不想修改函数的调用方式,但是还想在原来的函数前后加功能 原则:开发封闭原则 开发:对扩展是开发的 封闭:对修改是封闭的 装饰器的固定模式 计算运行时间 1 import ...
- python基础二 函数 递归 装饰器 迭代器 生成器 内置函数 二分法应用
函数 迭代器 生成器 拆包和装包 tup=("j1","a1","c1","k1") a,b,c,d=tup print ...
- python魔法函数和装饰器_python魔法方法、构造函数、序列与映射、迭代器、生成器...
在Python中,所有以__双下划线包起来的方法,都统称为"魔术方法".比如我们接触最多的__init__,魔法方法也就是具有特殊功能的方法. 构造函数 构造函数不同于普通方法,将 ...
- python基础教程:装饰器的高级应用
装饰器和装饰器模式 装饰器模式是面向对象的一种设计模式,支持将行为动态增加到已经存在的对象上.当装饰一个对象的时候,就表示独立与其他类实例对象,为该对象扩展了新的功能. python的装饰器不是装饰器 ...
- python的装饰器迭代器与生成器_详解python中的生成器、迭代器、闭包、装饰器
迭代是访问集合元素的一种方式.迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 1|1可迭代对象 以直接作用于 for ...
最新文章
- web app开发技巧总结
- 方差分析中怎么看有无显著性影响_用R语言做单因素方差分析及多重比较
- mysql connector api_mysql connector c++ 1.1 API初步体验
- matlab脑电信号处理,基于matlab的脑电信号处理
- 修改unity变量名但不丢失序列化值
- 一样入职的应届生工资不一样_刘涛入职阿里:为什么阿里要招聘明星?明星入职和普通人一样吗...
- 设置最大值_变频器用远传压力表控制恒压供水参数设置
- 万网域名注册查询接口(API)的说明
- Quartus II 9.0sp1之功能仿真
- The specified JRE installation does not exist异常的原因和解决办法
- 【muduo源码分析 】 MutexLock和MutexLockGuard封装
- Window操作系统注册表学习
- SVN 客户端的安装与配置
- 美洽SDK通过广播结束消息提示
- oracle分析函数结构,oracle之分析函数解析及其应用场景
- 计算机保存文件夹纵向排序,文件夹怎么自己排序,文件夹里怎么排序
- html动画3d背景图片,jQuery和CSS3全屏3D背景图片视觉差特效
- 棋盘覆盖问题 (分治)
- redis的nodejs客户端ioredis初识
- 朋友圈被公司“无偿征用”,该怎么办?
热门文章
- note3 android system recovery,三星note3 N900v刷第三方rom
- 用java语言编写石头剪刀布获胜法_石头剪刀布Java实现
- wxhtmltopdf 图片路径问题_图片引入路径问题
- oracle flex asm ceph,关于12c flex cluster及 flex asm疑问
- 喷水装置2(nyoj12)
- Linux学习笔记---记一次rootfs根文件系统下载时掉进的大坑
- Android学习笔记(九)——Activity的跳转和数据传递
- Redmine 126邮件服务器的配置
- cctype 头文件定义 函数列表
- 吴恩达深度学习5.3练习_Sequence Models_Neural machine translation with attention