Frank的学习之路

Day_6_总结_迭代器_生成器_包

今日内容:

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、  可以用于返回值

Yieldreturn的区别

相同点:都可以用于返回值,个数和类型没有限制

不同点: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文件的文件,文件夹是用来组织文件

强调,包以及包下所有的文件都是用来被导入使用,没有一个文件是用来被直接运行

因为包其实是模块的一种形式而已

2Import p1

创建p1的名称空间

执行p1下的__init__.py文件的代码,将执行过程中产生的名字都丢到名称空间

在当前执行文件中拿到一个名字p1p1指向__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

# 1logger对象负责产生日志

loger1=logging.getLogger('交易日志')

# 2filter过滤

# 3handler对象需要与logger绑定,用来接受Logger对象传过来的日志,控制打印到不同的地方(不同文件,终端)

fh1=logging.FileHandler(filename='a.log',encoding='utf-8')

fh2=logging.FileHandler(filename='b.log',encoding='utf-8')

sh=logging.StreamHandler()

# 4formatter对象需要与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、设置日志级别:loggerhandle两层关卡都放行,日志才能最终放行

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]' #其中namegetlogger指定的名字

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))

返回顶部