学习python第十天

  这么算起来,学习 python 可不止用了十天,接下来还有 python 的高级部分,加油~


 1、异常(重点)

1.1  捕获异常

简单的捕获异常语法

try:
    # 提示用户输入一个数字
    num = int(input("请输入数字:"))
except:
    print("请输入正确的数字")
  • try尝试,下方编写要尝试代码,不确定是否能够正常执行的代码
  • except如果不是,下方编写尝试失败的代码

错误类型捕获

在程序执行时,可能会遇到 不同类型的异常,并且需要 针对不同类型的异常,做出不同的响应,这个时候,就需要捕获错误类型了

  • 当 Python 解释器 抛出异常 时,最后一行错误信息的第一个单词,就是错误类型
try:
    num = int(input("请输入整数:"))
    result = 8 / num
    print(result)
except ValueError:
    print("请输入正确的整数")
except ZeroDivisionError:
    print("除 0 错误")

捕获未知错误

  • 在开发时,要预判到所有可能出现的错误,还是有一定难度的
  • 如果希望程序 无论出现任何错误,都不会因为 Python 解释器 抛出异常而被终止,可以再增加一个 except
except Exception as result:
    print("未知错误 %s" % result)

异常捕获完整语法

  • else 只有在没有异常时才会执行的代码

  • finally 无论是否有异常,都会执行的代码

try:
    num = int(input("请输入整数:"))
    result = 8 / num
    print(result)
except ValueError:
    print("请输入正确的整数")
except ZeroDivisionError:
    print("除 0 错误")
except Exception as result:
    print("未知错误 %s" % result)
else:
    print("正常执行")
finally:
    print("执行完成,但是不保证正确")

1.2  异常的传递

  • 异常的传递 —— 当 函数/方法 执行 出现异常,会 将异常传递 给 函数/方法 的 调用一方
  • 如果 传递到主程序,仍然 没有异常处理,程序才会被终止

提示:(主函数调用其他函数,其他函数出现异常,只要在主函数中捕获异样就行)

  • 在开发中,可以在主函数中增加 异常捕获
  • 而在主函数中调用的其他函数,只要出现异常,都会传递到主函数的 异常捕获 中
  • 这样就不需要在代码中,增加大量的 异常捕获,能够保证代码的整洁
def demo1():
    return int(input("请输入一个整数:"))
def demo2(): return demo1() try: print(demo2()) except ValueError: print("请输入正确的整数") except Exception as result: print("未知错误 %s" % result)

1.3  抛出 raise 异常

应用场景

  • 在开发中,除了 代码执行出错 Python 解释器会 抛出 异常之外
  • 还可以根据 应用程序 特有的业务需求 主动抛出异常

示例

  • 提示用户 输入密码,如果 长度少于 8,抛出 异常

抛出异常

  • Python 中提供了一个 Exception 异常类
  • 在开发时,如果满足 特定业务需求时,希望 抛出异常,可以:
    1. 创建 一个 Exception 的 对象
    2. 使用 raise 关键字 抛出 异常对象
def input_password():
    pwd = input("请输入密码:")
    if len(pwd) >= 8:
        return pwd
    ex = Exception("密码长度不够")
    raise ex

try:
    user_pwd = input_password()
    print(user_pwd)
except Exception as result:
    print("发现错误:%s" % result)

2、模块

2.1  模块的概念

模块是 Python 程序架构的一个核心概念

  • 每一个以扩展名 py 结尾的 Python 源代码文件都是一个 模块
  • 模块名 同样也是一个 标识符,需要符合标识符的命名规则
  • 在模块中定义的 全局变量 、函数 都是提供给外界直接使用的 工具
  • 模块 就好比是 工具包,要想使用这个工具包中的工具,就需要先 导入 这个模块

2.2  模块的两种导入方式

1)import 导入

  • 在导入模块时,每个导入应该独占一行
  • 导入之后,通过 模块名. 使用 模块提供的工具 —— 全局变量函数
  • 如果模块的名字太长,可以使用 as 指定模块的名称,以方便在代码中的使用(别名符合大驼峰命名法)
import 模块名1 as 模块别名

2)from...import 导入

  • 如果希望 从某一个模块 中,导入 部分 工具,就可以使用 from ... import 的方式
  • import 模块名 是 一次性 把模块中 所有工具全部导入,并且通过 模块名/别名 访问
  • 导入之后,不需要 通过 模块名,可以直接使用 模块提供的工具 —— 全局变量函数
# 从 模块 导入 部分工具
form 模块名1 import 某个工具
# 从 模块 导入 所有工具使用*(这种方式不推荐使用,因为函数重名并没有任何的提示,出现问题不好排查)
from 模块名2 import *

3)特别注意!!

如果 两个模块,存在 同名的函数,那么 后导入模块的函数,会 覆盖掉先导入的函数

  • 开发时 import 代码应该统一写在 代码的顶部,更容易及时发现冲突
  • 一旦发现冲突,可以使用 as 关键字 给其中一个工具起一个别名

2.3  模块的搜索顺序 [扩展]

Python 的解释器在 导入模块 时,会:

  1. 搜索 当前目录 指定模块名的文件,如果有就直接导入
  2. 如果没有,再搜索 系统目录
  3. 在开发时,给文件起名,不要和 系统的模块文件 重名
  4. Python 中每一个模块都有一个内置属性 __file__ 可以 查看模块 的 完整路径
print(__file__)    

2.4  原则 —— 每一个文件都应该是可以被导入的

  • 一个 独立的 Python 文件 就是一个 模块
  • 在导入文件时,文件中 所有没有任何缩进的代码 都会被执行一遍!

实际开发场景

  • 在实际开发中,每一个模块都是独立开发的,大多都有专人负责
  • 开发人员 通常会在 模块下方增加一些测试代码
    • 仅在模块内使用,而被导入到其他文件中不需要执行

__name__ 属性

  • __name__ 属性可以做到,测试模块的代码 只在测试情况下被运行,而在 被导入时不会被执行
  • __name__ 是 Python 的一个内置属性,记录着一个 字符串
  • 如果 是被其他文件导入的__name__ 就是 模块名
  • 如果 是当前执行的程序 __name__ 是 __main__

在很多 Python 文件中都会看到以下格式的代码

# 在代码的最下方
def main():
    # ...
    pass

# 根据 __name__ 判断是否执行下方代码
if __name__ == "__main__":
    main()

3、包(Package)

3.1  概念

  •  是一个 包含多个模块 的 特殊目录
  • 目录下有一个 特殊的文件 __init__.py(即只有是源文件夹才能被导入)
  • 包名的 命名方式 和变量名一致,小写字母 + _

3.2  好处

  • 使用 import 包名 可以一次性导入  中 所有的模块
# 从 当前目录 导入 模块列表
from . import send_message
from . import receive_message

 4、文件

4.1  文件的基本操作

在 计算机 中要操作文件的套路非常固定,一共包含三个步骤

  1. 打开文件
  2. 读、写文件
    •  将文件内容读入内存
    •  将内存内容写入文件
  3. 关闭文件

1)操作文件的函数/方法

  • 在 Python 中要操作文件需要记住 1 个函数和 3 个方法
序号函数/方法说明
01 open 打开文件,并且返回文件操作对象
02 read 将文件内容读取到内存
03 write 将指定内容写入文件
04 close 关闭文件
  • open 函数负责打开文件,并且返回文件对象
  • read/write/close 三个方法都需要通过 文件对象 来调用

2)read 方法 —— 读取文件

  • open 函数的第一个参数是要打开的文件名(文件名区分大小写)
    • 如果文件 存在,返回 文件操作对象
    • 如果文件 不存在,会 抛出异常
  • read 方法可以一次性 读入 并 返回 文件的 所有内容
  • close 方法负责 关闭文件
    • 如果 忘记关闭文件会造成系统资源消耗,而且会影响到后续对文件的访问
  • 注意read 方法执行后,会把 文件指针 移动到 文件的末尾
# 1. 打开 - 文件名需要注意大小写
file = open("README")

# 2. 读取
text = file.read()
print(text)

# 3. 关闭
file.close()
  • 在开发中,通常会先编写 打开 和 关闭 的代码,再编写中间针对文件的 读/写 操作!

3)文件指针(知道)

  • 文件指针 标记 从哪个位置开始读取数据
  • 第一次打开 文件时,通常 文件指针会指向文件的开始位置
  • 当执行了 read 方法后,文件指针 会移动到 读取内容的末尾
    • 默认情况下会移动到 文件末尾
  • 如果执行了一次 read 方法,读取了所有内容,那么再次调用 read 方法,不能再读取内容了(文件指针指向了末尾)

4)打开文件的方式

  • open 函数默认以 只读方式 打开文件,并且返回文件对象
  • 频繁的移动文件指针,会影响文件的读写效率,开发中更多的时候会以 只读只写 的方式来操作文件
访问方式说明
r 只读方式打开文件。文件的指针将会放在文件的开头,这是默认模式。如果文件不存在,抛出异常
w 只写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件
a 追加方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入
r+ 读写方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,抛出异常
w+ 读写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件
a+ 读写方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入


#
打开文件 f = open("README", "w") f.write("hello python!\n") f.write("今天天气真好") # 关闭文件 f.close()

 5)按行读取文件内容

  • read 方法默认会把文件的 所有内容一次性读取到内存
  • 如果文件太大,对内存的占用会非常严重

读取大文件的正确姿势

# 打开文件
file = open("README")

while True:
    # 一次读取一行内容
    text = file.readline()

    # 判断是否读到内容
    if not text:
        break

    # 每读取一行的末尾已经有了一个 `\n`
    print(text, end="")

# 关闭文件
file.close()

6)文件读写案例 —— 复制文件

# 一次性全部读取(适合复制小文件)
def test01():
    # 1. 打开文件
    file_read = open("README")
    file_write = open("README[复件]", "w")
    # 2. 读取并写入文件
    text = file_read.read()
    file_write.write(text)
    # 3. 关闭文件
    file_read.close()
    file_write.close()

# 一行一行读取(适合复制大文件) def test02(): # 1. 打开文件 file_read = open("README") file_write = open("README[复件]", "w") # 2. 读取并写入文件 while True: # 每次读取一行 text = file_read.readline() # 判断是否读取到内容 if not text: break file_write.write(text) # 3. 关闭文件 file_read.close() file_write.close()

4.2  文件/目录的常用管理操作

  • 在 终端 / 文件浏览器、 中可以执行常规的 文件 / 目录 管理操作,例如:
    • 创建、重命名、删除、改变路径、查看目录内容、……
  • 在 Python 中,如果希望通过程序实现上述功能,需要导入 os 模块

文件操作

序号方法名说明示例
01 rename 重命名文件 os.rename(源文件名, 目标文件名)
02 remove 删除文件 os.remove(文件名)

目录操作

 

序号方法名说明示例
01 listdir 目录列表 os.listdir(目录名)
02 mkdir 创建目录 os.mkdir(目录名)
03 rmdir 删除目录 os.rmdir(目录名)
04 getcwd 获取当前目录 os.getcwd()
05 chdir 修改工作目录 os.chdir(目标目录)
06 path.isdir 判断是否是文件 os.path.isdir(文件路径)

4.3  文本文件的编码格式(科普)

ASCII 编码

  • 计算机中只有 256 个 ASCII 字符
  • 一个 ASCII 在内存中占用 1 个字节 的空间
    • 8 个 0/1 的排列组合方式一共有 256 种,也就是 2 ** 8

 

UTF-8 编码格式

  • 计算机中使用 1~6 个字节 来表示一个 UTF-8 字符,涵盖了 地球上几乎所有地区的文字
  • 大多数汉字会使用 3 个字节 表示
  • UTF-8 是 UNICODE 编码的一种编码格式

 Ptyhon 2.x 中如何使用中文

  • Python 2.x 默认使用 ASCII 编码格式
  • Python 3.x 默认使用 UTF-8 编码格式
  • 在 Python 2.x 文件的 第一行 增加以下代码,解释器会以 utf-8 编码来处理 python 文件
# 官方推荐的格式
# *-* coding:utf8 *-*

# 我们也可以使用
# coding=utf8

unicode 字符串(注意注意!!!)

  • 在 Python 2.x 中,即使指定了文件使用 UTF-8 的编码格式,但是在遍历字符串时,仍然会 以字节为单位遍历 字符串
  • 要能够 正确的遍历字符串,在定义字符串时,需要 在字符串的引号前,增加一个小写字母 u,告诉解释器这是一个 unicode 字符串(使用 UTF-8 编码格式的字符串)
# *-* coding:utf8 *-*

# 在字符串前,增加一个 `u` 表示这个字符串是一个 utf8 字符串
hello_str = u"你好世界"

print(hello_str)

for c in hello_str:
    print(c)

5、eval 函数

eval() 函数十分强大 —— 将字符串 当成 有效的表达式 来求值 并 返回计算结果

# 基本的数学计算
In [1]: eval("1 + 1")
Out[1]: 2

# 字符串重复
In [2]: eval("'*' * 10")
Out[2]: '**********'

# 将字符串转换成列表
In [3]: type(eval("[1, 2, 3, 4, 5]"))
Out[3]: list

# 将字符串转换成字典
In [4]: type(eval("{'name': 'xiaoming', 'age': 18}"))
Out[4]: dict

5.1  案例 - 计算器

input_str = input("请输入一个算术题:")

print(eval(input_str))

5.2  不要滥用 eval

在开发时千万不要使用 eval 直接转换 input 的结果

__import__('os').system('ls')
  • 等价代码
import os
os.system("终端命令")
  • 执行成功,返回 0
  • 执行失败,返回错误信息

如果滥用eval(),输入__import__('os').system('ls'),会显示当前系统文件,那么如果我是删除系统文件呢,不安全咯!

input_str = input("请输入str:")
print(eval(input_str))

 

posted @ 2018-10-30 20:40  人工智能之路上的菜鸡  阅读(213)  评论(0编辑  收藏  举报