今日内容:
1、 迭代器(****)
2、 生成器(***)
3、 生成器表达式(*****)
4、 面向过程编程(*****)
5、 包的使用(**)
6、 常用模块
Loggin(*****)
Re(*****)
【1】、迭代器
1. 什么是迭代器
迭代器就是取值的一种工具
迭代器是一个重复的过程,但是每一个重复都是基于上一次结果而进行
2. 为何要用迭代器
针对没有索引的数据类型,比如字典、集合、文件,想要迭代取出其中包含的一个个值,python解释器必须提供一种能够不依赖索引迭代取值的工具
l=['frank','sunny','franksunny']
count=0
while count<len(l):
print(l[count])
count+=1
3. 如何使用迭代器
可迭代的对象:内置有__iter__方法的对象都可以称之为迭代器对象
x=1
y=3
#以下都是可迭代对象
strl='hello'
list1=['a','b','c']
t1=('a','b','c')
dic={'x':1,'y':2}
set1={'m','n'}
f=open('a.txt',mode='rt',encoding='utf-8')
strl.__iter__()
list1.__iter__()
t1.__iter__()
dic.__iter__()
set1.__iter__()
f.__iter__()
迭代器对象:
1、 内置有__iter__方法,调用迭代器对象的__iter__方法得到的仍然是迭代器本身
文件对象本身就是一个迭代器对象
2、 内置有__next__方法
dic={'x':1,'y':2}
iter_dic=iter(dic) #iter_dic=dic.__iter__()
print(iter_dic)
总结迭代器的优点:
一、提供了一个不依赖索引的、通用的迭代取值方式
补充:for循环可以称之为迭代器循环
For循环的工作流程
1、 调用in后面那个对象的__iter__方法,拿到一个迭代器对象
2、 调用迭代器对象的__next__方法,拿到一个返回值赋值给变量名item
3、 循环反复,直到抛出异常,for循环才会自动捕获异常结束循环
二、节省内存
总结迭代器的缺点:
1、 针对同一个迭代器只能取完一次,不能按照索引或者key取值方式灵活
2、 无法预测迭代器多想所包含数值的个数
list1=['a','b','c']
iter_list1=iter(list1)
print('---------->1')
while True:
try:
k=next(iter_list1)
print(k)
except StopIteration: #StopIteration标志取值结束
break
print('---------->2')
while True:
try:
k=next(iter_list1)
print(k)
except StopIteration: #StopIteration标志取值结束
break
执行结果:
【2】生成器
1. 什么是生成器
在函数中但凡出现yield关键字,在调用函数就不会触发函数体代码执行了
会得到一个返回值,该返回值就是一个生成器对象,
而生成器对象本质就是迭代器
2. 为什么要用生成器
生成器就是自定义迭代器
3. 如何用生成器
def foo():
print('first')
yield 1
print('second')
yield 2
print('third')
yield 3
print('fourth')
g=foo() #g就是生成器=》迭代器
# print(g)
# g.__next__()
# g.__next__()
# g.__next__()
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# for item in g: #item=g.__next__()
# print(item)
# print(g.__iter__().__iter__() is g)
g.__next__()会触发g对应的函数的函数体代码执行,知道遇到一个yield就暂停住,就该yield后的值当做本次__netx__的返回值返回
总结yield功能:
1、 提供了一个自定义迭代器方式
2、 可以用于返回值
Yield与return的区别
相同点:都可以用于返回值,个数和类型没有限制
不同点:yield可以返回多次值,return只能返回一次值整个函数就结束了
3、 函数暂停以及继续执行的状态是由yield保存的
def my_range(start,stop,step=1):
while start < stop:
yield start
start+=step
obj=my_range(1,4,)
print(next(obj))
print(next(obj))
print(next(obj))
执行结果:
Yield功能使用
def my_range(start,stop,step=1):
while start < stop:
yield start
start+=step
for i in my_range(1,5,2):
print(i)
执行结果:
Yield功能使用
def dog(name):
print('狗[%s]准备开吃' %name)
foo_list=[]
while True:
food=yield foo_list #food=yield='骨头'
print('狗哥[%s]吃了:%s' %(name,food))
foo_list.append(food)
print(foo_list)
dg=dog('alex')
next(dg)
#强调:针对表达式形式的yield,在使用生成器前必须下先send(None)或者next(dg),相当于初始化操作
dg.send('骨头')
dg.send('泔水')
#send有两个功能:
# 1、为当前yield位置赋值
# 2、与next的效果一样
执行结果:
【3】、面向过程编程
核心是过程二字,过程是指解决问题的步骤,即干什么再干什么后干什么
基于该思想编写程序就好比设计一条流水线,是一种机械化思维
优点:复杂问题流程化,进而简单化
缺点:牵一发而动全身,扩张性差
def communicate():
name=input('username>>:').strip()
pwd=input('password>>:').strip()
return (name,pwd)
def auth(name,pwd):
if name=='frank' and pwd=='123':
return True
else:
return False
def index(res):
if res:
print('welcome to index pages')
else:
print('请重新输入')
def main():
user,pwd=communicate()
res=auth(user,pwd)
index(res)
main()
【4】、包的使用
1、 什么是包
包本质就是一个包含有__init__.py文件的文件,文件夹是用来组织文件
强调,包以及包下所有的文件都是用来被导入使用,没有一个文件是用来被直接运行
因为包其实是模块的一种形式而已
2、Import p1
创建p1的名称空间
执行p1下的__init__.py文件的代码,将执行过程中产生的名字都丢到名称空间
在当前执行文件中拿到一个名字p1,p1指向__init__py的名称空间
3、包内模块:绝对导入与相对导入
绝对导入:每次导入都是以最顶级的包开始查找
相对导入:相当于当前所在的文件夹,.代码当前所在的文件夹,..代表上一级
强调:相对导入只能在被导入的模块中使用
在执行文件中不能用.或者..的导入方式
注意:
但凡在导入时带点的,点的左边必须要是一个包
【5】、logging模块
import logging
# logging.basicConfig(filename='access.log',
# format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
# datefmt='%Y-%m-%d %H:%M:%S %p',
# level=10,)
#
# logging.debug('log debug')
# logging.info('log info')
# logging.warning('log warning')
# logging.error('log error')
# logging.critical('log critical')
# 1、日志打印到文件
# 2、控制日志级别
# 3、控制日志格式
# logging模块包含四个对象:logger 、filter 、handler、 formatter
# 1、logger对象负责产生日志
loger1=logging.getLogger('交易日志')
# 2、filter过滤
# 3、handler对象需要与logger绑定,用来接受Logger对象传过来的日志,控制打印到不同的地方(不同文件,终端)
fh1=logging.FileHandler(filename='a.log',encoding='utf-8')
fh2=logging.FileHandler(filename='b.log',encoding='utf-8')
sh=logging.StreamHandler()
# 4、formatter对象需要与handler对象绑定,用于控制Handler对象日志格式
formatter1=logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s'
,datefmt='%Y-%m-%d %H:%M:%S %p')
formatter2=logging.Formatter(fmt='%(asctime)s - %(levelname)s: %(message)s'
,datefmt='%Y-%m-%d %H:%M:%S %p')
# 5、设置日志级别:logger与handle两层关卡都放行,日志才能最终放行
loger1.setLevel(10)
fh1.setLevel(10)
fh2.setLevel(10)
sh.setLevel(10)
#建立logger对象与handler对象的绑定关系
loger1.addHandler(fh1)
loger1.addHandler(fh2)
loger1.addHandler(sh)
#建立handler对象与formatter对象的绑定关系
fh1.setFormatter(formatter1)
fh2.setFormatter(formatter1)
sh.setFormatter(formatter2)
#使用logger1对象产生日志到不同的地方
loger1.debug('交易日志')
日志字典模板使用
Settings.py
"""
logging配置
"""
# 定义三种日志输出格式 开始
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
# log文件的全路径
fh1_logfile_path = 'b1.log'
fh2_logfile_path = 'b2.log'
# log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
},
'filters': {},
'handlers': {
#打印到终端的日志,使用的格式为 simple_format
'ch': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
#打印到文件b1.log的日志,使用的格式为 standard_format
'fh1': {
'level': 'DEBUG',
'class': 'logging.FileHandler', # 保存到文件
'formatter': 'standard',
'filename': fh1_logfile_path, # 日志文件
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
#打印到文件b2.log的日志,使用的格式为 standard_format
'fh2': {
'level': 'DEBUG',
'class': 'logging.FileHandler', # 保存到文件
'formatter': 'standard',
'filename': fh2_logfile_path, # 日志文件
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
# 'logger1': {
# 'handlers': ['ch', 'fh1','fh2'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
# 'level': 'DEBUG',
# 'propagate': False,
# },
# '交易日志': {
# 'handlers': ['ch', 'fh1','fh2'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
# 'level': 'DEBUG',
# 'propagate': False,
# },
# '用户权限': {
# 'handlers': ['ch', 'fh1','fh2'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
# 'level': 'DEBUG',
# 'propagate': False,
# },
'': {
'handlers': ['ch', 'fh1','fh2'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'DEBUG',
'propagate': False,
},
},
}
从字典中加载logging模块的配置
import settings
import logging.config
logging.config.dictConfig(settings.LOGGING_DIC)
# logger1=logging.getLogger('logger1')
# logger1=logging.getLogger('交易日志')
#
# logger1.debug('测试日志')
# logger2=logging.getLogger('用户权限')
# logger2.debug('测试日志')
logger1=logging.getLogger('交易日志')
logger2=logging.getLogger('用户权限')
logger1.debug('测试日志')
logger2.debug('测试日志')
# 完整的日志内容;
# 时间
# 级别
# 类型:跟什么业务有关
# 文件名/行号
# 具体的内容
【6】、Re模块
1、 什么是正则
正则就是用一些具有特殊的含义的符合组合到一起(称之为正则表达式)来描述字符或者字符串办法
2、 常用匹配模式(元字符)
import re
# print(re.findall('frank','asdffrank123 -_frank123*()'))
# print(re.findall('\w','frank123_-&()'))
# print(re.findall('\W','frank123_-&()'))
# print(re.findall('\s','h \t frank\nsunny'))
# print(re.findall('\S','h \t frank\nsunny'))
# print(re.findall('\d','frank123 456'))
# print(re.findall('\D','frank123 456'))
# print(re.findall('frank','frank is a good boy,frank'))
# print(re.findall('^frank','frank is a good boy,frank'))
# print(re.findall('sunny$','frank is a good sunny frank boy,sunny'))
# []: 代表匹配我们自己指定范围的任意一个字符,
# print(re.findall('a.c','a-c a*c a\n sdfa a c'))
# print(re.findall('a[0-9]c','a c a*c a1c'))
# print(re.findall('a[a-z]c','aac a*c a1c'))
# 重复匹配
# ? : 代表左边那一个字符出现0次或者1次
# print(re.findall('ab?','abb abbbb abbbb abasdfs'))
# * :代表左边那一个字符出现0次或者无穷次,如果没有可以凑合,但如果>1个,有多少就必须拿多少
# print(re.findall('ab*','abb abbbb abbbb abasdfs'))
# {n,m}:代表左边那一个字符出现n次到m次,至少要有n个,但如果有>n个,就拿<=m个
# print(re.findall('ab{1,3}','abbbbbabbb abbbba absdasba'))
# .* : 匹配0个或无穷个任意字符,默认是贪婪匹配
# print(re.findall('a.*c','a1c1111111c'))
# .*? : 匹配0个或无穷个任意字符,非贪婪匹配
# print(re.findall('a.*?c','a1c1111111c'))
# print(re.findall('compan(?:ies|y)','my company is a big company of companies'))
# print(re.findall(r'a\\c','a\c a1c aac'))
# 从左往右匹配,匹配成功一个就结束,返回一个对象,不成功最后返回None
# print(re.search('frank','frank is frank easdfas'))
# print(re.search('frank','frank is frank easdfas').group())
# obj=re.search('(href)="(.*?)"','<div class="div1"><a href="https://www.baidu.com">点我啊</a></div><div class="div1"><a href="https://www.python.org">点我啊</a></div>')
# print(obj.group())
# print(obj.group(1))
# print(obj.group(2))
# print(re.search('frank','frank is frank easdfas'))
# print(re.match('frank','frank is frank easdfas').group())
# msg='zabbix:x:503:503::/home/zabbix:/sbin/nologin'
# print(re.split('[:/]',msg))
# print(re.sub('frank','sunny','frank is a good boy,frank'))
# print(re.sub('^frank','sunny','frank is a good boy,frank'))
# print(re.sub('frank$','sunny','frank is a good boy,frank'))
# msg1='<div class="div1"><a href="https://www.baidu.com">点我啊</a></div><div class="div1"><a href="https://www.python.org">点我啊</a></div>'
# print(re.findall('href="(.*?)"',msg1))
#
# msg2='<div class="div1"><a href="https://www.sina.com.cn">点我啊</a></div><div class="div1"><a href="https://www.jd.com">点我啊</a></div>'
# print((re.search('href="(.*?)"',msg2)).group(1))
obj=re.compile('href="(.*?)"')
msg1='<div class="div1"><a href="https://www.baidu.com">点我啊</a></div><div class="div1"><a href="https://www.python.org">点我啊</a></div>'
print(obj.findall(msg1))
msg2='<div class="div1"><a href="https://www.sina.com.cn">点我啊</a></div><div class="div1"><a href="https://www.jd.com">点我啊</a></div>'
print(obj.search(msg2).group(1))