01 迭代器
'''
1、什么是迭代器
迭代的工具
什么是迭代?
迭代是一个重复的过程,每一次重复都是给予上一次结果而进行的
单纯的重复并不是迭代
while True:
print('=====>')
2、为什么要用迭代器
找到一种可以不依赖索引的迭代取值方式
3、怎么用迭代器
可迭代对象?
在Python中,但凡内置有__iter__方法对象,都是可迭代的对象
迭代器对象?
执行可迭代对象下__iter__方法得到的返回值就是一个迭代器对象
迭代器对象内置
__next__方法
__iter__方法,执行该方法得到仍然是迭代器本身,干什么用??
迭代器对象一定是可迭代的对象
可迭代的对象不一定是迭代器对象
'''
# l=['a','b','c']
# l='hello'
# l=('a','b','c','d','e')
# l={'a':1,'b':2,'c':3} #报错,字典是无序
# i=0
# while i < len(l):
# print(l[i])
# i+=1
# a=1
# b=1.1
# #以下都是可迭代的对象
# c='hello'
# d=[1,2,3]
# e=(1,2,3)
# d={'a':1}
# g={1,2,3}
# f=open('aa.py','rb')
# 执行可迭代对象的__iter__方法得到迭代器对象
# dic={'k1':1,'k2':2,'k3':3}
# iter_obj=dic.__iter__()
#
# # print(iter_obj)
#
# print(iter_obj.__next__())
# print(iter_obj.__next__())
# print(iter_obj.__next__())
# print(iter_obj.__next__()) #报错,因为没有第四个字典的key
# f=open('aa.py','rt',encoding='utf-8')
# iter_obj=f.__iter__()
#
# print(iter_obj)
# print(iter_obj.__next__(),end='')
# print(iter_obj.__next__(),end='')
# print(iter_obj.__next__(),end='')
# 基于迭代器的迭代取值方式
dic={'k1':1,'k2':2,'k3':3}
#
# iter_obj=dic.__iter__()
# print(iter_obj) #<dict_keyiterator object at 0x0000000001D94778>
#
# print(iter_obj.__iter__().__iter__().__iter__().__iter__() is iter_obj) #iter_obj.__iter__就是他本身
#
# while True:
# try:
# print(iter_obj.__next__())
# except StopIteration:
# break
# for循环的底层运行机制:for循环可以称之为迭代器循环
# 1、新调用in后那个对象的__iter__方法,得到该对象的迭代器对象
# 2、执行迭代器对象的__next__方法,将得到的返回值赋值in前面的变量名,然后执行一次循环体代码
# 3、循环往复,直到取干净迭代器内所有的值,自动捕捉异常结束循环
# for k in dic: #iter_obj=dic.__iter__()
# print(k)
# for x in 10: #报错,10不是可迭代的
# pass
# f=open('aa.py','rt',encoding='utf-8')
# for line in f:
# print(line)
# 示范一
# dic={'k1':1,'k2':2,'k3':3}
# iter_obj=dic.__iter__()
#
# print('第一次迭代iter_obj')
# for k in iter_obj:
# print(k)
#
# print('第二次迭代iter_obj')
# for k in iter_obj:
# print(k)
'''
第一次迭代iter_obj
k1
k2
k3
第二次迭代iter_obj
'''
# 示范二
# dic={'k1':1,'k2':2,'k3':3}
# iter_obj=dic.__iter__()
# print('第一次迭代iter_obj')
# for k in iter_obj:
# print(k)
#
# iter_obj=dic.__iter__()
# print('第二次迭代iter_obj')
# for k in iter_obj:
# print(k)
'''
第一次迭代iter_obj
k1
k2
k3
第二次迭代iter_obj
k1
k2
k3
'''
# 示范三:1
# dic={'k1':1,'k2':2,'k3':3}
# #每次都会主动先调用in后那个对象的__iter__方法,得到该对象的迭代器对象
# print('第一次迭代')
# for k in dic:
# print(k)
#
# print('第二次迭代')
# for k in dic:
# print(k)
# 迭代器的优缺点:
# 优点:
# 1、提供一种不依赖与索引的迭代取值方式===》应用于for循环
# 2、节省内存
# l=[1,2,3,4,5,6,6,6,6,6,6,6,6,6,6,6]
#一次往下读一行
# obj=l.__iter__()
# f=open('aa.py')
# print(f.__next__())
# print(f.__next__())
# f.readline()
# for line in f:
# print(line)
# for i in range(1,10000):
# print(i)
# 缺点:
# 1、只能往后取,不能往前取,是一次性的,值取干净后无法再次取值,除非重新得到新的迭代器对象
# 没有按索引取值的方式灵活
#
# 2、值取不干净,永远无法预测迭代器的长度
02 生成器
'''
一、什么是生成器
在函数内但凡有yield关键字,再调用函数就不会执行函数体代码,得到 返回值 就是一个 生成器对象
强调:生成器本质就是迭代器
next(g)过程:
会触发生成器g所对应的函数的执行,直到遇到yield才停下来,然后把yield后的返回值当做本次next操作的结果
二、为什么要用生成器:
学习生成器是为了掌握一种自定义迭代器的方式
三、总结yield:
1、yield提供一种自定义迭代器的方式
2、与return对比,都能返回值,都能返回多个值,都没有类型限制,而return只能返回一次值,
而yield可以返回多次值(yield可以帮我们保存函数的执行状态)
'''
# def func():
# print('first')
# yield 1 #<generator object func at 0x0000000002871728>
# print('second')
# yield 2 # # yield 1 <generator object func at 0x0000000002281728>
# print('third')
# g=func()
# print(g)
# res1=next(g) #g.__next__()
# print(res1)
# '''
# first
# 1
# '''
# res2=next(g) #g.__next__()
# print(res2)
# '''
# first
# 1
# second
# 2
# '''
# res3=next(g) #取到third后报错
# '''
# Traceback (most recent call last):
# File "D:/ProgramData/old boy/SH_s1/day05/02 生成器.py", line 44, in <module>
# res3=next(g) #取到third后报错
# StopIteration
# first
# 1
# second
# 2
# third
# '''
# g=func()
# for item in g: #item=next(g)
# print(item)
'''
first
1
second
2
third
'''
range(1,100,2)
def my_range(start,stop,step=1):
print('开始运行')
while start < stop:
yield start
start+=step
print('结束运行')
obj=my_range(1,1000,2)
res1=next(obj)
print(res1)
03 yield的表达式形式应用
def dog(name):
print('粽子%s准备开吃' %name)
food_list=[]
while True: #while True 语句中一定要有结束该循环的break语句
food=yield food_list #暂停 food=yield='骨头'
print('粽子%s 吃了%s' %(name,food))
food_list.append(food)
g=dog('c')
# print(g) #打印生成器对象地址<generator object dog at 0x0000000001DDDFC0>
res1=next(g) #到food=yield food_list暂停了,返回了food_list
print(res1) #打印得到[]
'''
粽子c准备开吃
[]
'''
# res2=next(g)
# print(res2)
'''
粽子c吃了None
[None]
'''
# g.send(None) #完全等同于next(g),强调:对于表达式形式yield的生成器,在使用前必须用next(g)或g.send(None)初始化一次
res2=g.send('骨头') #food=骨头,粽子c 吃了骨头
print(res2) #res2=next(g),粽子c 吃了骨头>>food_list.append('骨头')>>food=yield food_list中断,返回food_list,res2=['骨头']>>print(res2)得['骨头']
res3=g.send('骨头1')
print(res3)
'''
粽子c 吃了骨头1
['骨头','骨头1']
'''
# res4=g.send('骨头2')
# print(res4)
'''
粽子c 吃了骨头2
['骨头', '骨头1','骨头2']
'''
res4=next(g)
print(res4)
'''
粽子c 吃了None
['骨头','骨头1',None]
'''
04 面向过程编程
'''
1、面向过程编程
核心是过程,过程指的是解决问题的步骤,即先干什么,再干什么,后干什么
基于面向过程的思想编写程序好比在设计一条流水线,是一种机械式思维方式
优点:
将复杂的问题流程化,进而简单化
缺点:
修改某一个阶段,其他相关的阶段都有可能受影响,牵一发而动全身,扩展性极差
应用:
应用于对扩展性要求不高的场景
'''
def interactive():
'''接收用户输入的用户名、密码'''
uname=input('username>>>:').strip()
group=input('group>>>:').strip()
pwd=input('password>>>:').strip()
return uname,group,pwd
def auth(uname,group,pwd):
'''认证用户名与密码是否正确'''
if uname == 'm' and pwd == '123' and group == 'master':
return True,uname,group
else:
return False,uname,group
def index(res):
'''如果认证成功,则打印欢迎界面'''
if res[0]:
print('部门:%s 员工:%s 登陆成功' %(res[2],res[1]))
else:
print('部门:%s 员工:%s 登陆失败' %(res[2],res[1]))
uname,group,pwd=interactive()
res=auth(uname,group,pwd)
index(res)
05 三元表达式
x=10
y=30
res=x if x > y else y
print(res)
06 列表生成式、字典生成式、生成器表达式
# 列表生成式
# l=[]
# for i in range(10):
# l.append('egg%s' %i)
#
# print(l) #['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']
# l=['egg%s' %i for i in range(10)]
# print(l) #['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']
# nums=[i**2 for i in range(10)]
# print(nums) #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写
# names=['egon','alex_sb','wupeiqi','yuanhao']
# names=[name.upper() for name in names]
# print(names) #['EGON', 'ALEX_SB', 'WUPEIQI', 'YUANHAO']
# 2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度
# names=['egon','alex_sb','wupeiqi','yuanhao']
# l=[len(name) for name in names if not name.endswith('sb')]
# print(l) #[4, 7, 7]
# 字典生成式
# d={i:i for i in range(10) if i >0}
# print(d) #{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
#
# userinfo=[('egon','123'),('alex','456'),('wxx','678')]
# dic={k:v for k,v in userinfo}
# print(dic) #{'egon': '123', 'alex': '456', 'wxx': '678'}
# 生成器表达式
# g=(i for i in range(1000000000000000000000000000000000))
# # print(g) # <generator object <genexpr> at 0x000000000260DFC0>
# print(next(g))
# print(next(g))
# chicken=('egg%s' %i for i in range(3))
# # print(chicken)
# print(next(chicken))
# print(next(chicken))
# print(next(chicken))
# '''
# egg0
# egg1
# egg2
# '''
# print(next(chicken)) #报错,只有三个值
# '''
# Traceback (most recent call last):
# File "D:/ProgramData/old boy/SH_s1/day05/06 列表生成式、字典生成式、生成器表达式.py", line 50, in <module>
# print(next(chicken))
# StopIteration
# '''
#求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)
# res=max((1,2,3,4,5,6,7))
# print(res)
with open('a.txt','r',encoding='utf-8') as f:
nums=(len(line) for line in f)
# print(nums) #<generator object <genexpr> at 0x0000000001DCDFC0>
# print(nums)
# print(next(nums)) #文件已经关闭,报错,不占用内存。ValueError: I/O operation on closed file.
print(max(nums))
07 匿名函数
# def f1():
# print('from f1')
#
# f1()
# f1()
# def func(x,y):
# return x+y
#
# print(func) #<function func at 0x00000000004F3E18>
# # func(1,2)
# print(func(1,2)) #3
# 匿名
# 注意:
# 1、不会单独使用,会与其他函数配合使用
# 2、匿名函数的精髓在于没有名字,如果没有名字意味着用一次就立即回收,匿名函数仅用于使用一次的场景
# lambda x,y:x+y
# 配合使用的内置函数:max,min,sorted,filter,map
salaries={
'egon':3000,
'alex':10000000,
'wupeiqi':10000,
'yuanhao':2000
}
# 求出最大工资的那个人名
# def func(k):
# return salaries[k]
# print(max(salaries,key=lambda x:salaries[x])) #alex,比的是value,得到的结果是key
# print(min(salaries,key=lambda x:salaries[x])) #yuanhao
# sorted,按照薪资排序,从小到大排
# print(sorted(salaries,key=lambda x:salaries[x])) #['yuanhao', 'egon', 'wupeiqi', 'alex']
# sorted,按照薪资排序,从大到小排
# print(sorted(salaries,key=lambda x:salaries[x],reverse=True)) #['alex', 'wupeiqi', 'egon', 'yuanhao']
# map的应用
names=['alex', 'wupeiqi', 'egon', 'yuanhao']
# l=[name+'_sb' for name in names]
# print(l) #['alex_sb', 'wupeiqi_sb', 'egon_sb', 'yuanhao_sb']
# obj=map(lambda x:x+'_sb',names)
# print(list(obj))
# filter的应用
names=['alex_sb','wupeiqi_sb','egon','yuanhao_sb','liuqingzheng_sb']
l=(name for name in names if name.endswith('sb'))
print(list(l))
# print(l) #<generator object <genexpr> at 0x0000000002861728>
# print(l.__next__()) #alex_sb
# print(l.__next__()) #wupeiqi_sb
# print(l.__next__()) #yuanhao_sb
# print(l.__next__()) #liuqingzheng_sb
# filter会得到names的迭代器对象obj,然后next(obj)将得到的值传给filter第一个参数指定的函数
# 将函数返回值为True的那个值留下
# res=filter(lambda x:x.endswith('sb'),names)
# print(list(res)) #['alex_sb', 'wupeiqi_sb', 'yuanhao_sb', 'liuqingzheng_sb']
0801 模块介绍
一、什么是模块
模块就是一组功能的集合体,模块组织形式有以下几种
1、一个Python文件是一个模块,文件名是module.py,模块名则是module(自定义模块的常见形式)
2、已被编译为共享库或DLL的C或C++扩展
3、使用c编写并链接到Python解释器的内置模块
4、把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)
二、为什么要用模块
1、可以将程序中频繁用来的一些公共的功能组织到一个文件中,从而减少代冗余
2、直接使用内置或者第三方的模块中的功能,这种拿来主义可以提升开发效率
三、如何使用模块
# spam.py
# print('from the spam.py')
__all__=['money','read1'] #from spam import *,控制的就是*所导入的名字
money=1000
def read1():
print('spam模块:',money)
def read2():
print('spam模块')
read1()
def change():
global money
money=0
#当文件被当做脚本执行时__name__的值为"__main__"
# 当文件被导入时__name__的值为"模块名"
print(__name__) #直接执行得到__main__,import spam得到spam
if __name__ == '__main__':
read1()
read2()
change()
0802 import导入模块
# ==============================第一部分
x=1
y=2
# from spam import money,read1,read2,change
# 1、from 。。。import。。。首次导入模块也做三件事:
# 1.1 首先产生一个模块的名称空间
# 1.2 会执行模块文件的代码,将产生的名字放到模块的名称空间中
# 1.3 会在当前名称空间中直接拿到一个模块名称空间中的名字
# money=1 # print(money) 结果为1===》》容易与当前名称空间中的名字冲突
# 2、可以不加前缀直接使用
# print(money)
# print(read1)
# print(read2)
# print(change)
'''
1000
<function read1 at 0x0000000002838268>
<function read2 at 0x0000000002838840>
<function change at 0x0000000002838B70>
'''
# 优点:简洁
# 缺点:容易与当前名称空间中的名字冲突
#强调强调强调:来自于模块名称空间中的函数一定是模块的名称空间为准
# read1() #spam模块: 1000
# change()
# read1() #spam模块: 0
# print(money) #1,change不会改变当前money的值
# =======================第二部分
# from spam import *
# #不推荐使用*,除非在我们需要引入模块中很多名字时,可以用*起到一个节省代码的作用
# print(money)
# print(read1)
# print(read2)
# print(change)
# '''
# 1000
# <function read1 at 0x0000000002898840>
# <function read2 at 0x0000000002898B70>
# <function change at 0x0000000002898BF8>
# '''
# ==========================第三部分(了解)
# from spam import *
# #spam.py中添加__all__=['money','read1']
# print(money,read1) #1000 <function read1 at 0x0000000002848840>
# print(read2) #报错,NameError: name 'read2' is not defined
# '''
# 1000 <function read1 at 0x0000000002848268>
# <function read2 at 0x0000000002848840>
# '''
# =========================第四部分
from spam import money as m
print(m) #1000