python1.day15

day14回顾
   异常
     错误
     异常
     作用:
       用作信号通知
     语句:
       try-except语句
         捕获异常,将程序由异常流程转为正常流程
       try-finally语句
         保证(正常/异常)流程时,有些语句一定能执行
       raise 语句
         触发异常通知,让程序进入异常流程
       assert 语句
         根据条件触发AssertionError类型的错误
     异常类型:
        ValueError, ImportError, ZeroDivisionError,
        StopIteration, AssertionError, ....
        BaseExcetion(基类)

  迭代器
     什么是迭代器?
       函数:
         iter(可迭代对象)   获取并返回迭代器
         next(迭代器)    从迭代器中取数据,如果没有数据时会收到
                        StopIteration异常通知

    for in 语句的实质是while语句+迭代器+try语句的组合



day15笔记:
生成器 Genertor (python2.5及之后)
   什么是生成器
     生成器是能够动态提供数据的可迭代对象
     生成器是在程序运行时生成数据,与容器类不同,它通常不会在内
       存在中保存大量的数据,而是现用现生成

  生成器有两种:
     生成器函数
     生成器表达式

  
生成器函数的定义
   含有yield 的语句的函数是生成器函数。此函数被调用将返回一
   个生成器对象
   yield翻译为(产生或生成)

yield语句
   语法:
      yield 表达式
   说明:
     yield 用于def函数中,目的是将此函数作为生成器函数使用
     yield 用来生成数据,供迭代器的next(it) 函数使用
  示例见:
     yield.py

 

  1 # yield.py
  2 
  3 # 此示例示意生成器函数的定义和使用
  4 def myyield():
  5     print("即将生成2")
  6     yield 2  # 生成2
  7     print("即将生成3")
  8     yield 3  # 生成3
  9     print("即将生成5")
 10     yield 5
 11     print("即将生成7")
 12     yield 7
 13     print("myyield函数运行结束!")
 14 
 15 
 16 
 17 g = myyield()  # 生成器函数调用将返回生成器对象,g绑写一个生成器
 18 # print(g)
 19 it = iter(g)  # 让生成器提供迭代器
 20 print(next(it))  # 2
 21 
 22 print(next(it))  # 3
 23 
 24 print(next(it))  # 5
 25 
 26 print(next(it))  # 7
 27 
 28 print(next(it))  # StopIteration异常
 29 print("程序正常结束")
 30 
 31 
 32 
 33 
yield.py

  1 # yield.py
  2 
  3 # 此示例示意生成器函数的定义和使用
  4 def myyield():
  5     print("即将生成2")
  6     yield 2  # 生成2
  7     print("即将生成3")
  8     yield 3  # 生成3
  9     print("即将生成5")
 10     yield 5
 11     print("即将生成7")
 12     yield 7
 13     print("myyield函数运行结束!")
 14 
 15 for x in myyield():
 16     print(x)
 17 
 18 
 19 print("程序正常结束")
 20 
 21 
 22 
 23 
 24 
 25 
 26 
yield2.py

生成器函数说明:
   1. 生成器函数的调用将返回一个生成器对象,生成器对象是一个可迭
      代对象
   2. 在生成器函数调用return会触发一个StopIteration异常(即
      生成数据结束)
   生成器函数示例见:
     myinteger.py

  1 # myinteger.py
  2 
  3 # 此示例示意自己写一个生成器函数,可以生成从0开始的一系列
  4 # 整数,到n结束(不包含n)
  5 def myinteger(n):
  6     i = 0
  7     while i < n:
  8         yield i
  9         i += 1
 10 
 11 
 12 for x in myinteger(3):
 13     print(x)
 14 
 15 
 16 
myinteger.py

练习:
   1. 写一个生成器函数myeven(begin, end), 用来生成从begin开始
      到end结束的所有偶数(不包含end)
     如:
         def myeven(begin, end):
             ... 此处自己实现

        for x in myeven(1, 10):
             print(x)  # 打印 2, 4, 6, 8
         L = [x**2 for x in myeven(4, 9)]
         print(L)  # [16, 36, 64]

  1 # 练习:
  2 #   1. 写一个生成器函数myeven(begin, end), 用来生成从begin开始
  3 #      到end结束的所有偶数(不包含end)
  4 #     如:
  5 #         def myeven(begin, end):
  6 #             ... 此处自己实现
  7 
  8 #         for x in myeven(1, 10):
  9 #             print(x)  # 打印 2, 4, 6, 8
 10 #         L = [x**2 for x in myeven(4, 9)]
 11 #         print(L)  # [16, 36, 64]
 12 
 13 
 14 def myeven(begin, end):
 15     i = begin
 16     while i < end:
 17         if i % 2 == 0:  # 是偶数
 18             yield i
 19         i += 1
 20 
 21 for x in myeven(1, 10):
 22     print(x)  # 打印 2, 4, 6, 8
 23 
 24 L = [x**2 for x in myeven(4, 9)]
 25 print(L)  # [16, 36, 64]
 26 
myeven.py

生成器表达式:
   语法:
     (表达式 for 变量 in 可迭代对象 [if 真值表达式])
   说明:
     if 子句可以省略
   作用:
     用推导式形式创建一个新的生成器
   示例:
     gen = (x**2 for x in range(1, 5))
     it = iter(gen)  # 拿到迭代器
     print(next(it))  # 1
     print(next(it))  # 4
     print(next(it))  # 9
     print(next(it))  # 16
     print(next(it))  # StopIteration

说明:
   生成器通常是一次性的,当数据获取完毕后将不能再提供数据

练习:
   已知有列表:
     L = [2, 3, 5, 7]
   1. 写一个生成器函数,让此函数能够动态提供数据,数据为原列
      表的数字的平方加1
   2. 写一个生成器表达式,让此表达式能够动态提供数据,数据为原
      列表的数字的平方加1
   3. 创建一个列表,此列表内的数据为原列表L的数字的平方加1

  1 # 练习:
  2 #   已知有列表:
  3 #     L = [2, 3, 5, 7]
  4 #   1. 写一个生成器函数,让此函数能够动态提供数据,数据为原列
  5 #      表的数字的平方加1
  6 #   2. 写一个生成器表达式,让此表达式能够动态提供数据,数据为原
  7 #      列表的数字的平方加1
  8 #   3. 创建一个列表,此列表内的数据为原列表L的数字的平方加1
  9 
 10 
 11 
 12 L = [2, 3, 5, 7]
 13 #   1. 写一个生成器函数,让此函数能够动态提供数据,数据为原列
 14 #      表的数字的平方加1
 15 def fun1(lst):
 16     for x in lst:
 17         yield x ** 2 + 1
 18 
 19 # for x in fun1(L):
 20 #     print(x)
 21 
 22 #   2. 写一个生成器表达式,让此表达式能够动态提供数据,数据为原
 23 #      列表的数字的平方加1
 24 
 25 for x in (a ** 2 + 1 for a in L):
 26     print(x)
 27 
 28 #   3. 创建一个列表,此列表内的数据为原列表L的数字的平方加1
 29 L = [a ** 2 + 1 for a in L]
 30 print(L)
 31 
 32 

练习:
   试写一个生成器函数 myfilter,要求此函数与系统内建的filter
   函数功能完全一致
     如:
         def myfilter(fn, iterable):
             ....
        
         for y in myfilter(lambda x: x%2==0, range(10)):
             print(y)

  1 # 练习:
  2 #   试写一个生成器函数 myfilter,要求此函数与系统内建的filter
  3 #   函数功能完全一致
  4 #     如:
  5 #         def myfilter(fn, iterable):
  6 #             ....
  7 
  8 #         for y in myfilter(lambda x: x%2==0, range(10)):
  9 #             print(y)
 10 
 11 
 12 
 13 
 14 def myfilter(fn, iterable):
 15     for x in iterable:
 16         if fn(x):
 17             yield x
 18 
 19 for y in myfilter(lambda x: x%2==0, range(10)):
 20     print(y)

   2. 看下列语句块的输出结果是什么?为什么?
     第一个程序:
         L = [2, 3, 5, 7]
         A = [x*10 for x in L]
         it = iter(A)
         print(next(it))  # 20
         L[1] = 33
         print(next(it))  # 30
     第二个程序:
         L = [2, 3, 5, 7]
         A = (x*10 for x in L)
         it = iter(A)
         print(next(it))  # 20
         L[1] = 33
         print(next(it))  # 330


迭代工具函数
   zip 函数
  enumerate 函数

zip函数
   zip(itere1[,iter2, ....])  返回一个zip生成器对象,此对象
              用于生成一个元组,此元组的数据分别来自于参数中的
              每个可迭代对象,生成元组的个数由最小的可迭代对象大
              小决定
   示例:
     numbers = [10086, 10000, 10010, 95588]
     names = ['中国移动', '中国电信', '中国联通']
     for t in zip(numbers, names):
         print("t=", t)
     for n, na in zip(numbers, names):
         print(na, '的客服电话是:', n)

    d = dict(zip(numbers, names))  # 创建字典

    for t in zip(numbers, names, range(1, 100000)):
         print(t)


zip 函数的实现原理示例见:
     myzip.py


enumerate 函数
   格式:
     enumerate(iterable, start=0)

   作用:
     生成一个枚举对象,此枚举对象生成的数据将原可迭代对象的数据与
     索引值形成元组(index, value) 形式返回
   示例:
     L = [3, 5, 8, 10]
     for i, v in enumerate(L):
         print('索引为', i, '的元素值为', v)

练习:
   试用自己的方法实现myenumerate, 功能与enumerate完全相同
     def myenumerate(iterable, start=0):
         ...  # 此处自己实现

    L = [3, 5, 8, 10]
     for i, v in myenumerate(L):
         print('索引为', i, '的元素值为', v)

  1 # 练习:
  2 #   试用自己的方法实现myenumerate, 功能与enumerate完全相同
  3 #     def myenumerate(iterable, start=0):
  4 #         ...  # 此处自己实现
  5 
  6 #     L = [3, 5, 8, 10]
  7 #     for i, v in myenumerate(L):
  8 #         print('索引为', i, '的元素值为', v)
  9 
 10 
 11 # 方法1 用while语句实现
 12 # def myenumerate(iterable, start=0):
 13 #     it = iter(iterable)  # 拿到迭代器
 14 #     while True:
 15 #         try:
 16 #             v = next(it)  # 拿到一个值
 17 #             yield (start, v)
 18 #             start += 1
 19 #         except StopIteration:
 20 #             return
 21 
 22 # 方法2 用for语句实现
 23 def myenumerate(iterable, start=0):
 24     for v in iterable:
 25         yield (start, v)
 26         start += 1
 27 
 28 L = [3, 5, 8, 10]
 29 for i, v in myenumerate(L):
 30     print('索引为', i, '的元素值为', v)
 31 
 32 
 33 
 34 
 35 
 36 
 37 

字节串和字节数组

字节串 bytes(也叫字节序列)
   作用:
     存储以字节为单位的数据
     字节串是不可变的字节序列
字节:
   字节是0~255之间的整数。用来表一个字节(8个位)的取值
   字节是数据存储的最小单位


创建空字节串的字面值:
    B = b''   # B绑定空字节串
    B = b""
    B = b''''''
    B = b""""""

创建非空字节串的字面值:
   B = b'ABCD'
   B = b"ABCD"
   B = b'\x41\x42\x43\x44'

字节串的构造函数 bytes
   bytes()   生成一个空的字节串,等同于b''
   bytes(整数可迭代对象)  用可迭代对象初始化一个字节串
   bytes(整数n)    生成n个值为0的字节串
   bytes(字符串,encoding='utf-8')   用字符串转换编码生成一个
         字节串

示例:
   B = bytes()                    # B=b''
   B = bytes(range(65, 69))       # B = b'ABCD'
   B = bytes(10)                  # B=b'\x00\x00....'
   B = bytes("hello", 'utf-8')    # B=b'hello'


bytes 的运算:
   +  +=  *  *=
   < <= > >= == !=
   in / not in
   索引和切片

示例:
   b = b'abc123ABC'
   b'A' in b  # True
   65 in b   # True
   print(b[0])  # 97

函数:
   len(x), max(x), min(x), sum(x), any(x), all(x)

bytes 与 str的区别:
   bytes 存储字节(0~255)
   str存储unicode字符  (0~0x10FFFF)

bytes与str转换
         编码(encode)
   str   -----------> bytes
       b = s.encode(encoding='utf-8')

     解码(decode)
   bytes  -----------> str     
       s = b.decode(encoding='utf-8')

  示例:
     s = "ABC中文"
     b = s.encode('utf-8')  # b = b'ABC\xe4\xb8\xad\xe6\x96\x87'

    s2 = b.decode('utf-8')  # s2 = 'ABC中文'


字节数组 bytearray
   可变的字节序列

字节数组的构造函数 bytearray
    (同字节串)
   bytearray()   生成一个空的字节数组,等同于bytearray(b'')
   bytearray(整数可迭代对象)  用可迭代对象初始化一个字节数组
   bytearray(整数n)    生成n个值为0的字节数组
   bytearray(字符串,encoding='utf-8')   用字符串转换编码生成一个
         字节数组


运算:
   +  +=  *  *=
   < <= > >= == !=
   in / not in
   索引Index / 切片 slice
   (注: 字节数组的索引和切片可以赋值操作,规则同列表的索引和切片
   赋值规则相同)

bytearray 的方法:
   参见文档:
     python_base_docs_html/bytearray.html


文件 File
   什么是文件
     文件是用于数据存储的单位
     文件通常用来长期存储数据
     文件中的数据是以字节为单位进行顺序存储的
 
   文件操作的流程
     1. 打开文件
     2. 读写文件
     3. 关闭文件


  文件的打开和关闭:
     文件需要在使用时先打开文件才能读写
     在不需要读写文件时,应及时关闭文件以释放系统资源
     任何操作系统,一个应用程序同时打开文件的数量有最大数限制

  文件的打开函数:
     open(file, mode='rt')  用于打开一个文件,返回此文件对象
                      如果打开失败,则会触发OSError类型的错误
        
  文件的关闭方法:
    F.close()  关闭文件,释放系统资源
   文本文件的读取数据方法:
     F.read([n])
     F.readline()
     F.readlines()
     (文档参见: python_base_docs_html/文件.html)

  1 mode 模式字符的含义
  2 字符	含义
  3 'r'	以只读方式打开(默认)
  4 'w'	以只写方式打开,删除原有文件内容(如果文件不存在,则创建该文件并以只写方式打开)
  5 'x'	创建一个新文件, 并以写模式打开这个文件,如果文件存在则会产生"FileExistsError"错误
  6 'a'	以只写文件打开一个文件,如果有原文件则追加到文件末尾
  7 'b'	用二进制模式打开
  8 't'	文本文件模式打开 (默认)
  9 '+'	为更新内容打开一个磁盘文件 (可读可写)
 10 缺省模式是 'rt'
 11 'w+b' 可以实现二进制随机读写,当打开文件时,文件内容将被清零
 12 'r+b' 以二进制读和更新模式打开文件,打开文件时不会清空文件内容
 13 'r+' 以文本模式读和更新模式打开文件,打开文件时不会清空文件内容
 14 python 文件常用方法:
 15 方法	说明
 16 F.close()	关闭文件(关闭后文件不能再读写会发生ValueError错误)
 17 F.readline()	读取一行数据, 如果到达文件尾则返回空行
 18 F.readlines(max_chars=-1)	返回每行字符串的列表,max_chars为最大字符(或字节)数
 19 F.writelines(lines)	每行字符串的列表
 20 F.flush()	把写入文件对象的缓存内容写入到磁盘
 21 F.read(size = -1)	从一个文件流中最多读取size个字符
 22 F.write(text)	写一个字符串到文件流中,返回写入的字符数
 23 二进制文件操作方法
 24 F.tell()	返回当前文件流的绝对位置
 25 F.seek(offset, whence=0)	改变数据流的位置,返回新的绝对位置
 26 F.readable()	判断这个文件是否可读,可读返回True,否则返回False
 27 F.writable()	判断这个文件是否可写,可写返回True,否则返回False
 28 F.seekable()	返回这个文件对象是否支持随机定位
 29 F.truncate(pos = None)	剪掉 自pos位置之后的数据,返回新的文件长度(字节为单位)


   示例见:
     file_open.py

  1 # file_open.py
  2 
  3 # 此示例示意打开一个文件, 同时对文件的内容进行读取操作
  4 
  5 # 1. 打开文件
  6 # f = open("myzip.py")
  7 f = open("myfile.txt")
  8 print("文件打开成功")
  9 
 10 # 2.读取文件
 11 
 12 # 3. 关闭文件
 13 f.close()
 14 print("文件关闭成功")
 15 
 16 
file_open.py

练习:
   1. 写一个生成器函数myxrange(start, stop, step) 来生成一
     系列整数,
       要求:
         myxrange的功能与range功能完全相同
         不允许调用range函数和列表
        用自己写的myxrange结合生成器表达式求 1~10内的奇数的平方和
       print(sum((x for x in myxrange(1, 10) if x%2)))
    
   2. 自己写一个文件(si.txt)内容如下:
      写入内容如下:
        xiaozhang,20,100
        ziaoli,18,98
        ziaowang,19,80
     为学生信息管理系统添加一个功能
       | 9) 从文件中读取学生数据(si.txt) |
     读取学生信息并加载到内存中

  1 # file : main.py
  2 
  3 from menu import show_menu
  4 from student_info import *
  5 
  6 def main():
  7     infos = []  # 此列表用于保存学生数据
  8     while True:
  9         show_menu()
 10         s = input("请选择: ")
 11         if s == '1':
 12             infos += input_student()
 13         elif s == '2':
 14             output_student(infos)
 15         elif s == '3':
 16             delete_student(infos)
 17         elif s == '4':
 18             modify_student_score(infos)
 19         elif s == '5':
 20             output_by_score_desc(infos)
 21         elif s == '6':
 22             output_by_score_asc(infos)
 23         elif s == '7':
 24             output_by_age_desc(infos)
 25         elif s == '8':
 26             output_by_age_asc(infos)
 27         elif s == '9':
 28             infos = read_from_file()
 29         elif s == '10':
 30             save_to_file(infos)  # 保存
 31         elif s == 'q':
 32             break
 33 
 34 main()
 35 
main
  1 # file : menu.py
  2 
  3 
  4 def show_menu():
  5     '''显示菜单'''
  6     print("+---------------------------------+")
  7     print("| 1) 添加学生信息                 |")
  8     print("| 2) 显示学生信息                 |")
  9     print("| 3) 删除学生信息                 |")
 10     print("| 4) 修改学生成绩                 |")
 11     print("| 5) 按学生成绩高-低显示学生信息  |")
 12     print("| 6) 按学生成绩低-高显示学生信息  |")
 13     print("| 7) 按学生年龄高-低显示学生信息  |")
 14     print("| 8) 按学生年龄低-高显示学生信息  |")
 15     print("| 9) 从文件中读取学生数据(si.txt) |")
 16     print("| 10) 保存信息到文件(si.txt)      |")
 17     print("| q) 退出                         |")
 18     print("+---------------------------------+")
 19 
 20 
menu.py


  1 # file: student.py
  2 
  3 def input_student():
  4     L = []  # 创建一个列表,准备存放学生数据的字典
  5     while True:
  6         n = input("请输入姓名: ")
  7         if not n:  # 如果用户输入空字符串就结束输入
  8             break
  9         try:
 10             a = int(input("请输入年龄: "))
 11             s = int(input("请输入成绩: "))
 12         except ValueError:
 13             print("您的输入有错,请重新输入!!!")
 14             continue
 15         d = {}  # 一定要每次都创建一个新的字典
 16         d['name'] = n
 17         d['age'] = a
 18         d['score'] = s
 19         L.append(d)   # 把d加入列表中L
 20     return L
 21 
 22 def output_student(L):
 23     print("+---------------+----------+----------+")
 24     print("|     姓名      |   年龄   |   成绩   |")
 25     print("+---------------+----------+----------+")
 26     for d in L:
 27         name = d['name']
 28         age = str(d['age'])  # 转为字符串
 29         score = str(d['score'])  # 转为字符串
 30         print("|%s|%s|%s|" % (name.center(15),
 31                             age.center(10),
 32                             score.center(10)))
 33     print("+---------------+----------+----------+")
 34 
 35 def delete_student(L):
 36     name = input("请输入要删除学生的姓名: ")
 37     i = 0  # i 代表列表的索引
 38     while i < len(L):
 39         d = L[i]  # d绑定字典
 40         if d['name'] == name:
 41             del L[i]
 42             print("删除", name, "成功!")
 43             break
 44         i += 1
 45     else:
 46         print("删除失败!")
 47 
 48 def modify_student_score(L):
 49     pass
 50 
 51 
 52 def output_by_score_desc(L):
 53     def get_score(d):
 54         return d['score']
 55     L2 = sorted(L, key=get_score, reverse=True)
 56     output_student(L2)
 57 
 58 def output_by_score_asc(L):
 59     L2 = sorted(L, key=lambda d:d['score'])
 60     output_student(L2)
 61 
 62 def output_by_age_desc(L):
 63     L2 = sorted(L, key=lambda d:d['age'], reverse=True)
 64     output_student(L2)
 65 
 66 def output_by_age_asc(L):
 67     L2 = sorted(L, key=lambda d:d['age'])
 68     output_student(L2)
 69 
 70 
 71 def read_from_file():
 72     L = []  # 创建一个准备存放字典的列表
 73     try:
 74         # 1. 打开文件
 75         # f = open("./si.txt")
 76         # f = open("si.txt")
 77         f = open("/home/tarena/aid1812/pbase/day16/student_project/si.txt")
 78         # 2. 读取信息
 79         try:
 80             while True:
 81                 line = f.readline()  # line='xiaozhang,20,100\n'
 82                 if not line:  # 到达文件尾
 83                     break
 84                 s = line.strip()  # 去掉左右两端的空白字符'xiaozhang,20,100'
 85                 lst = s.split(',')  # ['xiaozhang', '20', '100']
 86                 n = lst[0]
 87                 a = int(lst[1])
 88                 scr = int(lst[2])
 89                 d = dict(name=n, age=a, score=scr)
 90                 L.append(d)
 91         finally:
 92             # 3. 关闭文件
 93             f.close()
 94             print("读取数据成功")
 95     except OSError:
 96         print("读取数据失败")
 97     except ValueError:
 98         print("数据类型错误!")
 99     return L
100 
101 def save_to_file(L):
102     try:
103         f = open("si.txt", 'w')
104         # 循环写入每个学生的信息
105         for d in L:
106             # 每次写入一个学生的信息
107             f.write(d['name'])  # 姓名
108             f.write(',')
109             f.write(str(d['age']))  # 年龄
110             f.write(',')
111             f.write(str(d['score']))  # 成绩
112             f.write('\n')  # 换行
113         f.close()
114         print("保存成功")
115     except OSError:
116         print("保存失败!")
117 
student.py

猜你喜欢

转载自www.cnblogs.com/shengjia/p/10323267.html