python基础第四篇
来源:互联网 发布:上瘾网络剧第十六集 编辑:程序博客网 时间:2024/06/15 23:52
python基础 (四)
真心觉得python这门语言是业界良心:
- 生成器
- 迭代器
- 装饰器
一、生成器
首先来看一下列表生成式:
num_list=[i**2 for i in range(5)]print(num_list)#输出#[0, 1, 4, 9, 16]
列表生成式可以让我们很方便的生成一个列表,但是若是创建一个含有100万的元素的列表,其中有些元素经常用,有些元素几百年才用一回,这样就会浪费很大的存储空间。那么生成器就可以用来解决这种困惑。
列表元素可以按照某种算法推算出来,而不是一下子就创建好,这样一边计算一边循环。将上面列表生成式稍微改一下就成了一个简单的生成器。
num_g=(i**2 for i in range(5))print(num_g)#输出#<generator object <genexpr> at 0x7f277b807620>
那么怎么提取元素呢,通过next()函数获取generator的下一个值:
next(num_g)#输出 0next(num_g)#输出 1next(num_g)#输出 4
每次调用next()函数就会计算下一个返回值,直到最后一个元素,没有更多元素时,抛出StopIteration的错误。我们一般通过for循环来调用:
for i in num_g: print(i)#输出#0#1#4#9#16
generator另一种构建方式是用yield,这里有斐波那契数列作为例子。
#斐波那契数列:#1, 1, 2, 3, 5, 8, 13, 21, 34, ..def fib(max): n,a,b=0,0,1 while n<max: yield b a,b=b,a+b n+=1 return "done"#当取生成器元素发生错误时,返回donef=fib(5)for i in f: print(i)
输出:
11235
生成器内含一个next()方法,每次调用时执行到yield结束,再执行时从上次结束的yield处开始。
f=fib(5)print(f.__next__())print(f.__next__())print("做个其他事再去排数列")print(f.__next__())
输出:
11做个其他事再去排数列2
上面这个例子还是很神奇的,函数执行到yield就跳出,这时竟然还能够另外执行主程序中的其他命令。
二、 迭代器
给定一个list或tuple,可以通过for循环来遍历,那么这种遍历成为迭代(Iteration)。可迭代的对象(Iterable)有:
- 集合数据类型,如list、tuple、dict、set、str等
generator生成器
可以用isinstance()判断是否是一个可迭代对象(Iterable)。
from collections import Iterableisinstance([],Iterable)isinstance({},Iterable)isinstance("afsdg",Iterable)isinstance((x for x in range(12)),Iterable)isinstance(100,Iterable)
输出:
输出:
TrueTrueTrueTrueFalse
可以被next()函数调用并不断返回下一个值的对象称为迭代器
可以用isinstance()判断是否是一个迭代器对象(Iterator)
from collections import Iteratorisinstance([],Iterator)isinstance({},Iterator)isinstance("afsdg",Iterator)isinstance((x for x in range(12)),Iterator)
输出:
输出:
FalseFalseFalseTrue
所以生成器是迭代对象,而list,tuple,dict,str虽然是Iterable,但不是Iterator。
总之:
- 凡是可作用于for循环的对象都是Iterable类型;
- 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
- 集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象
三、装饰器
装饰器是什么?下面通过一个例子来说明。自己构建一个教学网站,那么首先有主页,再通过主页可以进入教学视频专区和论坛学术交流专区。
def home(): print("欢迎来到我的网站!")def edu_zone(): print("已进入课程专区")def bbs(): print("已进入论坛专区")
建立了这个也不够,必须对学员进行用户认证才行,为了学员的方便,应当在每个版块都能实现用户认证,那么先写出用户认证的方法:
global user_logindef login(): _username = "王柯南" _password = "666666" user_login = False if not user_login: username = input("用户名:") password = input("密码:") if username == _username and _password == password: print("登录成功") user_login = True else: print("用户名或者密码错误") else: print("您已经登录了")
那么为了让每个版块都具有用户验证的功能,可以在每个版块中加入login函数
def home(): login() print("欢迎来到我的网站!")def edu_zone(): login() print("已进入课程专区")def bbs(): login() print("已进入论坛专区")
但是这样的话违反了软件开发中的一个原则“开放-封闭”原则,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,那么很low的改进一下:
global user_logindef login(func): _username = "王柯南" _password = "666666" user_login = False if not user_login: username = input("用户名:") password = input("密码:") if username == _username and _password == password: print("登录成功") user_login = True func() else: print("用户名或者密码错误") else: print("您已经登录了")def home(): print("欢迎来到我的网站!")def edu_zone(): print("已进入课程专区")def bbs(): print("已进入论坛专区")login(home)login(edu_zone)login(bbs)
这里虽然没有改变原有的功能代码,但是改变了调用方式,倘若版块增多,增加调用也是很繁琐的事情,那么有什么能既不改变功能代码,又不改变调用方式,一劳永逸的方法呢?
#只要能做到以下三个等式#home()==login(home)#edu_zone()==login(edu_zone)#bbs()==login(bbs)#可以利用嵌套函数global user_logindef auth(func): def login(): _username = "王柯南" _password = "666666" user_login = False if not user_login: username = input("用户名:") password = input("密码:") if username == _username and _password == password: print("登录成功") user_login = True func() else: print("用户名或者密码错误") else: print("您已经登录了") return logindef home(): print("欢迎来到我的网站!")def edu_zone(): print("已进入课程专区")def bbs(): print("已进入论坛专区")# home=auth(home)==login 由于是嵌套函数auth会把home传递给loginhome = auth(home)edu_zone = auth(edu_zone)bbs = auth(bbs)home()edu_zone()bbs()
那么就实现了既不改变功能代码,又不改变调用方式,再优化下代码。
#只要能做到以下三个等式#home()==login(home)#edu_zone()==login(edu_zone)#bbs()==login(bbs)#可以利用嵌套函数global user_logindef auth(func): def login(): _username = "王柯南" _password = "666666" user_login = False if not user_login: username = input("用户名:") password = input("密码:") if username == _username and _password == password: print("登录成功") user_login = True func() else: print("用户名或者密码错误") else: print("您已经登录了") return logindef home(): print("欢迎来到我的网站!")def edu_zone(): print("已进入课程专区")def bbs(): print("已进入论坛专区")@auth#home = auth(home)home()@auth#edu_zone = auth(edu_zone)edu_zone()@auth#bbs = auth(bbs)bbs()
那么这就是装饰器了。但是又有问题了,如果我们的功能函数现在具有了形参,那么装饰器该如何改变?
#现在home函数中新增了name形参,而edu_zone和bbs函数还是保持原样def home(name): print("欢迎%s来到我的网站!"%name)def edu_zone(): print("已进入课程专区")def bbs(): print("已进入论坛专区")#只要能做到以下三个等式#home(name)==login(home,name)#edu_zone()==login(edu_zone)#bbs()==login(bbs)global user_logindef auth(func): def login(*args): _username = "王柯南" _password = "666666" user_login = False if not user_login: username = input("用户名:") password = input("密码:") if username == _username and _password == password: print("登录成功") user_login = True func(args) else: print("用户名或者密码错误") else: print("您已经登录了") return login@auth#home = auth(home)==login嵌套函数将home传递给login#home(name)==login(name)home("xzx")@auth#edu_zone = auth(edu_zone)edu_zone()@auth#bbs = auth(bbs)bbs()
最后还有一个问题,该登录方式只允许用户使用,内部人员使用要用其他登录方式,那又该怎么改进呢?
#用auth_type代表登录人员的类型#若是auth函数新增加了别的形参,装饰器@auth就失去了功能#但是auth_type又必须传入给login函数去判断#那就应该再增加一个嵌套函数用来传auth_type#只要能做到等式#home(name)==login(auth_type,home,name)global user_logindef auth_login(auth_type): def auth(func): def login(*args): if auth_type == "user": _username = "王柯南" _password = "666666" user_login = False if not user_login: username = input("用户名:") password = input("密码:") if username == _username and _password == password: print("登录成功") user_login = True func(*args) else: print("用户名或者密码错误") else: print("您已经登录了") else: print("您是内部工作人员,请更换登录系统") return login return auth@auth_login("user")#auth_login("user")==auth 参数user传递给了auth#home=auth(home)==login 参数user和home都传递给了login#@auth_login("user")=>home=auth_login("user")(home)def home(name): print("欢迎%s来到我的网站!"%name)@auth_login("staff")def edu_zone(): print("已进入课程专区")@auth_login("user")def bbs(): print("已进入论坛专区")home("xzx")edu_zone()bbs()
输出:
用户名:王柯南密码:666666登录成功欢迎xzx来到我的网站!您是内部工作人员,请更换登录系统用户名:王柯南密码:666666登录成功已进入论坛专区
- python基础第四篇
- Python基础第四课
- Python(基础)第四天
- Python基础学习--第四篇(条件判断和循环)
- Android基础第四篇
- python第四篇-if
- 笔试题基础(第四篇
- ICE第四篇-----python版本
- Python新手引导 第四篇
- python 基础第四天(模块 序列化)
- 《利用Python进行数据分析》第四章-numpy基础
- 【七月Python入门】 第四课面向对象基础
- 【Python】Python基础篇
- (基础篇) 第四章 输出文字
- java基础第四篇(续1)
- 【Java 基础篇】【第四课】初识类
- 第四篇 小曹学spring--Spring AOP 基础
- 第四章 C++基础篇之常量
- 代码优化片段--多处使用同一个对象时
- LeetCode 98 Validate Binary Search Tree(Python详解及实现)
- centos7自学之2-jdk配置
- java实现udp打洞,服务器转发消息
- Java 内存模型与线程
- python基础第四篇
- Go语言程序记录日志
- 浅谈 uninitialized_copy() 的参数类型
- POJ 1639
- PHP cookie管理
- JVM优化
- java 判断线程都执行完了(非线程池方式)
- js面试题(一)
- Eclipse使用Maven搭建Java Web项目并直接部署Tomcat8(全实战)