异常、try 语句、raise 语句、bytes和bytearray、文件、with 语句、sys模块、os 模块、os.path 模块、os.walk() 函数、shutil 模块、生成器

  • 昨天回顾

    • id(x) 函数

    • is / is not 运算符

    • 函数式编程

      • 高阶函数

        map(函数, 可迭代对象)  # 返回生成器对象
        filter(函数, 可迭代对象)  # 返回生成器对象(生成器对象是可迭代对象)
        sorted(可迭代对象, key=None<函数>, reverse=False)  # 返回列表
        
    • 模块

      xxx.py # xxx 就是模块名

      • 导入模块

        # 以 random 模块为例
        # 1\. 
        import random
        random.randint(1, 100)
        random.choice([1, 2, 3, 4, 5])
        # 2\. 
        from random import randint
        randint(1, 100)
        # 3\. 
        from random import *
        randint(1, 100)
        choice([1, 2, 3, 4, 5])
        
    • 预置模块

      • random 模块
      • time 模块
      • datetime 模块

异常

  • 作用

    用作信号通知,通知上层调用者有错误产生需要处理

try 语句

  • 语法

try:
可能发生异常的语句块
except 错误类型1 [as 变量名1]:
异常处理语句块1
except 错误类型2 [as 变量名2]:
异常处理语句块2
...
except 错误类型n [as 变量名n]:
异常处理语句块n
except:
异常处理语句块other
else:
未发生异常的语句
finally:
最终的处理语句

  • 作用

    尝试捕获异常,得到异常通知,将程序由异常状态变为正常状态

  • 说明

    except 子句可以有 1个或多个

    except: 不给错误类型,可以匹配全部的错误类型

    else 子句里的语句会在 没有错误发生时执行,当处于异常时不执行

    finally 子句里的语句,无论何时都执行

  • 示例

    try:
        x = int(input("请输入一个整数:"))
        print('x=', x)
    except ValueError:
        print('您的输入不能转成整数')
    
    print("程序结束")
    

raise 语句

  • 问题

    # 写一个函数, get_score 函数,读取用户输入的整数成绩, 
    # 成绩的正常值是0~100 之间, 要求, 如果不在0~100 之间
    # 报 ValueError类型的错误
    def get_score():
        x = int(input('请输入成绩:'))
        if 0 <= x <= 100:
            return x
            raise ValueError('用户输入的成绩不在 0~100之间!')
    
  • 语法

    raise 异常类型

    raise 异常对象

  • 作用

    • 抛出一个错误,让程序进入异常状态
    • 发送错误通知给调用者
  • 说明

    • 一旦raise 语句被调用,则raise 之后的语句将不会执行。
  • 示例:

    # 写一个函数, get_score 函数,读取用户输入的整数成绩,
    # 成绩的正常值是0~100 之间, 要求, 如果不在0~100 之间
    # 报 ValueError类型的错误
    def get_score():
        x = int(input('请输入成绩:'))
        if 0 <= x <= 100:
            return x
        # raise ValueError
        raise ValueError('用户输入的成绩不在 0~100 之间')
    
    try:
        score = get_score()
        print(score)
    except ValueError as err:
        print("成绩输入有误 err=", err)
    
  • 异常类型的可选种类

    详见:

    >>> help(_builtins_)

字节串 bytes 和字节数组 bytearray

1 一个字节(byte)是8个二进制的位 (bit)

1个byte的取值范围是 0 ~ 255

bytes 不可变

bytearray 可变

字节串的字面值

>>> b''
>>> b""
>>> b''''''
>>> b''''''
>>> b'ABC'
>>> bytes([65, 66, 67, 68])
>>> bytes([65, 66, 67, 68, 200,255])
>>> bytes([65, 66, 67, 68, 200,255, 300])  # 300 超出了255 报错
>>> bytearray([65, 66, 67, 68, 200,255])   # 字节数组的创建必须使用bytearray函数
  • 字节串的运算

    字节串是序列,运算规则同元组一样

    +   +=    *    *= 
    >   >=   <  <=   ==  !=
    in / not in
    

索引和切片

  • 示例

    >>> b = bytes([65, 66, 67, 68, 200,255])
    >>> b
    b'ABCD\xc8\xff'
    >>> b[0]
    65
    >>> b[:2]
    b'AB'
    >>> b += b'123'
    >>> b
    b'ABCD\xc8\xff123'
    >>> len(b)
    9
    
  • bytes 和 str 的区别

    bytes 存储的字节 (0~255 之间的数)

    str 存储的是字符的编码

  • bytes 与 str 转换

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

    示例

    >>> s = 'hello 小张'
    >>> 
    >>> b = s.encode()  #  将字符串编码成为字节串
    >>> b
    b'hello \xe5\xb0\x8f\xe5\xbc\xa0'  # 在utf-8 编码中,1个汉字通常用3个字节进行编码
    >>> len(b)
    12
    >>> s2 = b.decode()  # 将字节串解码成为字符串
    >>> s2
    'hello 小张'
    

文件

  • 什么是文件

    文件通常用来存储以字节为单位的数据

  • 文件的操作流程

    1. 打开文件
    2. 读/写文件
    3. 关闭文件
  • 打开文件用open 函数

    open(file, mode='rt')
    # open 函数返回文件流对象
    # 打开失败回收到异常通知
    # mode 的缺省值的 'rt'
    
    • 示例

      myfile = open('/etc/passwd', 'rt')
      s = myfile.read()  # 用 myfile  绑定的文件流对象的read()  方法,得到 文件内部的数据
      print(s)
      myfile.close()  # 关闭文件
      
  • 两种操作文件的模式

    1. 直接用 字节串操作文件(内部可以存储文字,也可以存储图片等信息)

      打开模式 mode = 'b' # b是binary

    2. 用字符串操作文本文件(内部存储的都是文字)

      打开模式 mode='t' # t 是text 的首字母(默认为't')

  • 示例见

    1. 用字符串操作文件

      f = open('mynote.txt', 'rt')   # 'r 代表读
      
      s = f.read()  # 在't' 模式下 ,read 返回字符串
      print(s)
      
      f.close()   # 关闭
      
    2. 用字节串操作文件

      f = open('mynote.txt', 'rb')   # 'r' 代表读 'b' 代表以二进制方式操作
      
      b = f.read()  # 在't' 模式下 ,read 返回字节串
      print(b)
      
      s = b.decode()  # 将字节串转成了字符串
      print(s)
      f.close()   # 关闭
      
  • 文件的打开模式 mode

    模式 说明
    't' 以文本(字符串) 的模式操作文件(默认)
    'b' 以二进制(字节串) 的模式操作文件
  • 文件的打开方式 mode

    方式 说明
    'r' 读取文件(默认)
    'w' 写和覆盖写文件(如果文件不存在则创建文件 )
    'a' 写并且追加文件内容(如果文件不存在则创建文件)

    python 文件流对象的方法

    方法名 说明
    F.close() 关闭文件
    读取文件的方法
    F.read(size=-1) 读取文件(不给出size 参数过读取全部)
    F.readline() 读取文件中的一行,以'\n' 作为行分隔符
    F.readlines() 读取文件中的全部,以'\n' 作为行分隔符, 返回行的列表
    写文件的方法
    F.write(x) 写文件: 'b'模式 x 必须是字节串, 't'模式x必须是字符串, 如果文件不存在则新建文件
  • 练习

    1. 写一个程序,输入任意个正整数,当输入负数是结束输入,
    将输入的正整数写入文件data.txt 中
    如:
    请输入: 1
    请输入: 2
    请输入: 3
    请输入: 4
    请输入: -1
    文件中的内容是:
    1
    2
    3
    4

    2. 写一个程序,读入data.txt 中的数字,计算这些正整数的和并打印出来

mynote.txt 文件中的内容

我是老魏
我在 tarena

读数据

>>> f = open('mynote.txt', 'rb')
>>> f.read()  # 返回全部
b'\xe6\x88\x91\xe6\x98\xaf\xe9\xad\x8f\xe7\x9c\x80\xe6\x8b\xa9\n\xe6\x88\x91\xe5\x9c\xa8 tarena\n'
>>> f.read()  # 当到达文件尾部,返回空
b''
>>> f.close()
>>> f = open('mynote.txt', 'r')
>>> f.read()
'我是魏眀择\n我在 tarena\n'
>>> f.close()

>>> f = open('mynote.txt', 'r')
>>> f.readline()  # 返回一行
'我是魏眀择\n'
>>> f.readline()
'我在 tarena\n'
>>> f.readline()
''
>>> f.close()

>>> f = open('mynote.txt', 'r')
>>> f.readlines()  # 取出所有的行数据,返回列表
['我是魏眀择\n', '我在 tarena\n']
>>> f.close()

写数据

>>> f = open('python.log', 'w')  # 以字符串方式写文件, 如果文件文件不存在回新建一个文件
>>> f.write('该吃饭了')
4
>>> f.write('!')
1
>>> f.write('\n')  # 写一个换行
1
>>> f.write('下课')
2
>>> f.close()
  • 移动文件的读写指针seek 方法

    • 在读写二进制模式打开的文件,在不关闭文件的情况下, 可以使用seek 方法移动文件的读写指针

    F.seek(偏移量, whence=相对位置)
    偏移量(整数)
    大于0 向文件末尾方向
    小于0 向文件头方向
    相对位置:
    0 代表从文件头开始偏移
    1 代表从当前的读写位置开始偏移
    2 代表从文件末尾开始偏移

  • tell() 方法,返回文件的读写指针的位置

    F.tell()      # 返回整数
    
  • 示例

    mynote3.txt 的内容

    1234567890ABCDE
    

    示例程序

    myfile = open('mynote2.txt', 'rb')
    
    print('刚打开文件时,文件指针的位置是:', myfile.tell())  # 0
    b = myfile.read(2)
    print(b)  # b'12'
    print('读取两个字节后,文件指针的位置是:', myfile.tell())  # 2
    # 读取 67890 这个5个字节
    # myfile.seek(5, 0)   # 0 开始位置,向后移动5个字节
    # myfile.seek(3, 1)    # 1 当前位置,向后移动3个字节
    myfile.seek(-10, 2)    # 2 文件末尾位置,向前移动10个字节
    print('myfile.seek()后,文件指针的位置是:', myfile.tell())  # 5
    b = myfile.read(5)   # b'67890'
    print('myfile.read(5)后,文件指针的位置是:', myfile.tell())  # 10
    print(b)
    
    myfile.close()
    

with 语句

通过with 语句打开文件,with 语句结束,则文件会自动关闭

  • 语法

    with 表达式1 as 变量1[, 表达式2 as 变量2, ...]:
    语句块

  • 示例

    # file: mynote2.txt
    # 不用with 语句
    f = open('mynote2.txt')
    s = f.read()
    print(s)
    f.close()
    
    # 用with 语句
    with open('mynote2.txt') as f:
        s = f.read()
        print(s)
    

sys模块

  • Shell 的位置参数 $0 $1 $2

    • python 上获取命令行参数

      #! /usr/bin/python3
      
      # file 04_myprog.py
      import sys
      print(sys.argv)   # ['./04_myprog', '/root', 'hello']
      
      # 如下是shell 中运行的内容
      $ chmod +x myprog.py
      $ ./myprog /root hello   # $0='./04_myprog'  $1='/root'  $2='hello'
      

os 模块

  • 对操作系统的访问大多使用 python 中的os 模块

文档: https://docs.python.org/zh-cn/3/library/os.html

>>> import os
>>> os.getcwd()  # 返回当前的工作路径,pwd
'/root/桌面/py02/day03_code'
>>> os.mkdir('/tmp/nsd21xx')   # mkdir /tmp/nsd21xx
>>> os.makedirs('/tmp/nsd21xx/a/b/c')  # mkdir -p /tmp/nsd21xx/a/b/c
>>> os.listdir()  # ls
['mygames.py', '.idea', 'mynote.txt', 'python.log', 'mynote2.txt', '03_file_seek.py', '04_myprog.py', '05_cp.py', '01_read_text_file_by_string.py', '02_read_text_file_by_bytes.py']
>>> os.listdir('/tmp')  # ls /tmp  # 列出所有的文件夹
[ 'nsd21xx', 'dir1', 'dir2']
>>> os.chdir('/tmp/nsd21xx')  # cd  /tmp/nsd21xx
>>> os.getcwd()   # pwd
'/tmp/nsd21xx'
>>> os.symlink('/etc/passwd', '/tmp/abc')  # ln -s /etc/passwd /tmp/abc
>>> os.mknod('/tmp/myfile.txt')    # touch /tmp/myfile.txt
>>> os.chmod('/tmp/myfile.txt', 0o755)  # chmod 755 /tmp/myfile.txt
>>> os.rename('/tmp/myfile.txt', '/tmp/a.txt')  # mv /tmp/myfile.txt /tmp/a.txt
>>> os.rmdir('/tmp/dir2')   # rmdir /tmp/dir2
>>> os.remove('/tmp/a.txt')  # rm /tmp/a.txt
  • 字符串用于去掉空白字符串的方法

    空白字符是指 ' ', '\n' '\r' '\t'

    >>> s = '    \n  \t hello world      \n'
    >>> s.strip()      # 去掉左右两侧的空白字符
    'hello world'
    >>> s.lstrip()   # 去掉左侧的空白字符
    'hello world      \n'
    >>> s.rstrip()     # 去掉右侧的空白字符
    '    \n  \t hello world'
    

os.path 模块

用于路径的操作的模块

>>> import os
>>> os.path.isabs('/root/abc.txt')   # 判断是否为绝对路径
True
>>> os.path.isdir('/tmp/nsd21xx')    # 判断是否是文件夹
True
>>> os.mknod('/tmp/b.txt')   # touch /tmp/b.txt
>>> os.path.isfile('/tmp/b.txt')     # 判断是否是文件
True
>>> os.path.islink('/tmp/abc')      # 判断是否是软连接?
True
>>> os.path.ismount('/home')       # 存在并且是挂载点
True
>>> os.path.exists('/root')       # 判断文件或文件夹是否存在
True
>>> os.path.basename('/tmp/nsd21xx/hello.py')  # 返回文件名
'hello.py'
>>> os.path.dirname('/tmp/nsd21xx/hello.py')  # 返回路径
'/tmp/nsd21xx'
>>> os.path.split('/tmp/nsd21xx/hello.py')  # 拆分 路径和文件名
('/tmp/nsd21xx', 'hello.py')
>>> os.path.join('/tmp/nsd21xx', 'world.py')  # 拼接路径
'/tmp/nsd21xx/world.py'

os.walk() 函数

遍历文件夹

[root@localhost tmp]# tree /tmp/nsd21xx/
/tmp/nsd21xx/
├── a
│ ├── aaa.txt
│ └── b
│ ├── bbb.txt
│ └── c
└── aa
└── bb
└── cc

示例

>>> for x in os.walk('/tmp/nsd21xx'):
...    print(x)
... 
#  (路径 , 路径内的所有文件夹列表 , 路径内的所有文件列表)
('/tmp/nsd21xx', ['a', 'aa'], [])
('/tmp/nsd21xx/a', ['b'], ['aaa.txt'])
('/tmp/nsd21xx/a/b', ['c'], ['bbb.txt'])
('/tmp/nsd21xx/a/b/c', [], [])
('/tmp/nsd21xx/aa', ['bb'], [])
('/tmp/nsd21xx/aa/bb', ['cc'], [])
('/tmp/nsd21xx/aa/bb/cc', [], [])

shutil 模块

文档: https://docs.python.org/zh-cn/3/library/shutil.html

>>> import shutil
>>> f1 = open('/etc/passwd', 'rb')
>>> f2 = open('/tmp/mypass.txt', 'wb')
>>> shutil.copyfileobj(f1, f2)
>>> f1.close()
>>> f2.close()
>>> 
>>> shutil.copy('/etc/passwd', '/tmp/mypass2.txt')    # cp /etc/passwd /tmp/mypass2.txt
'/tmp/mypass2.txt'
>>> shutil.copytree('/root/桌面/py02/day03_code', '/tmp/mycode')  # cp -r     /root/桌面/py02/day03_code /tmp/mycode
'/tmp/mycode'
>>> shutil.move('/tmp/mypass.txt', '/tmp/nsd21xx/a.txt')  # mv /tmp/mypass.txt /tmp/nsd21xx/a.txt
>>> shutil.rmtree('/tmp/mycode')  # rm -rf /tmp/mycode
>>> shutil.chown('/tmp/mypass.txt', user='xxx', group='yyy')  # 改属主属组
  • 课后练习:

    实现 cp 命令
    $ cp /etc/passwd /root/passwd

生成器

生成器是在程序运行时生成数据,与容器不同,它通常不会在内存中保留大量的数据,而是现用现生成。

生成器可以用算法动态的生成数据

生成器有两种

  1. 生成器函数
  2. 生成器表达式

生成器函数

含有yield 语句的函数 是生成器函数,此函数调用回返回一个生成器对象,生成器也是可迭代对象

yield 语句的语法

yield 表达式

生成器函数示例:

# 定义一个生成器函数, 有 yield 的函数调用后回返回生成器对象
def myrange(stop):
    i = 0
    while i < stop:
        yield i    # 为 遍历次生产器的for 语句提供数据
        i += 1

for x in myrange(5):
print('x=', x)

生成器表达式

  • 语法:

( 表达式 for 变量 in 可迭代对象 [if 真值表达式])

[] 内容代表可以省略

  • 作用

    用推导式的形式创建一个生成器

  • 示例

>>> [x ** 2 for x in range(1, 5)] # 列表解析(列表推导式)
[1, 4, 9, 16]
>>>
>>> (x ** 2 for x in range(1, 5)) # 生成器表达式
at 0x7f41dcd30a40>
>>> for y in (x ** 2 for x in range(1, 5)):
... print(y)
...
1
4
9
16

你可能感兴趣的:(异常、try 语句、raise 语句、bytes和bytearray、文件、with 语句、sys模块、os 模块、os.path 模块、os.walk() 函数、shutil 模块、生成器)