[Python] Python学习笔记:高级特性与高级拓展模块

慕课北京大学陈斌老师python课 第9章:高级特性与高级拓展模块 学习笔记

  • 例外处理
    • 代码错误类型
    • 捕捉错误
      • try-except语句
      • try-finally语句
      • else语句块
  • 推导式
    • 什么是推导式
    • 推导式基本语言
    • 生成器推导式
  • 生成器函数
    • 什么是生成器
    • 生成器函数
  • 上机练习:生成器
    • 异常处理
    • 推导式
    • 斐波那契数列
  • 图像处理库
    • Pillow库
    • 图像处理步骤
    • PIL图像操作
    • 小程序:PIL生成验证码
  • 数据可视化
    • numpy矩阵处理库
    • matplotlib绘图库
    • 基本思路
    • 简单函数图像
    • 定制线型、标签图例
    • 散点图和直方图
  • 期末考试题
    • 两组数的差异
    • 回文字符串
    • 0的组合
    • 乘积的列表
    • 破译密码

例外处理

代码错误类型

语法错误:SyntaxError

除0错误:ZeroDivisionError

列表下标越界:IndexError

类型错误:TypeError

访问变量不存在:NameError

字典关键字不存在:KeyError

未知的变量属性:AttributeError

捕捉错误

try-except语句

try:
	<检测语句>
except <错误类型> [as e]:
	<处理异常>

try: # 为缩进的代码设置陷阱
except: # 处理错误的代码

try-finally语句

try:
	<检测语句>
except <错误类型> [as e]:
	<处理异常>
finally:
	<语句块>

finally: # 无论出错否,都执行的代码
如果try语句掳爱运行时没有出现错误,会跳过except语句块执行finally语句块的内容

else语句块

try:
	<检测语句>
except <错误类型> [as e]:
	<处理异常>
else:
	<语句块>

else: # 没有出错执行的代码

推导式

什么是推导式

推导式是从一个或者多个迭代器快速简洁的创建数据结构的一种方法;
将循环和条件判断结合,从而避免语法冗长的代码;
可以用来生成列表、字典和集合。

推导式基本语言

列表推导式:
[<表达式> for <变量> in <可迭代变量> if <逻辑条件>]

字典推导式:
{<键值表达式>:<元素表达式> for <变量> in <可迭代对象> if <逻辑条件>}

集合推导式:
{<元素表达式> for <变量> in <可迭代对象> if <逻辑条件>}

>>> [x*x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> {
     'K%d' % x: x**3 for x in range(10)}  # python3.6后,字典都是有序的
{
     'K0': 0, 'K1': 1, 'K2': 8, 'K3': 27, 'K4': 64, 'K5': 125, 'K6': 216, 'K7': 343, 'K8': 512, 'K9': 729}
>>> {
     x*x for x in range(10)}
{
     0, 1, 64, 4, 36, 9, 16, 49, 81, 25}
>>> {
     x+y for x in range(10) for y in range(x)} # 集合自动去重
{
     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}
>>> [x+y for x in range(10) for y in range(x)]
[1, 2, 3, 3, 4, 5, 4, 5, 6, 7, 5, 6, 7, 8, 9, 6, 7, 8, 9, 10, 11, 7, 8, 9, 10, 11, 12, 13, 8, 9, 10, 11, 12, 13, 14, 15, 9, 10, 11, 12, 13, 14, 15, 16, 17]
>>> [x*x for x in range(10) if x % 2 == 0]
[0, 4, 16, 36, 64]
>>> [x.upper() for x in [1, 'abc', 'xyz', True] if isinstance(x, str)]  # isinstance() 函数来判断一个对象是否是一个已知的类型
['ABC', 'XYZ']

生成器推导式

与推导式一样的语法:(要加括号
(<元素表达式> for <变量> in <可迭代对象> if <逻辑条件>)

返回一个生成器对象,也是可迭代对象
但生成器并不立即产生全部元素,仅在要用到元素时才生成。

>>> agen = (x*x for x in range(10))
>>> agen
<generator object <genexpr> at 0x000001F2431E3F48>
>>> for n in agen:
    	print(n)

0
1
4
9
...

生成器函数

什么是生成器

生成器是用来创建Python序列的一个对象
使用它可以迭代庞大的序列,且不需要在内存中创建和储存整个序列
通常生成器是为迭代器产生数据的

生成器函数

如果要创建一个比较大的序列,生成器推导式将会比较复杂,一行表达式无法容纳,这时可以定义生成器函数

生成器函数与普通函数相同,只是将return换成了yield

yield与return:

  • yield语句:
    立即返回一个值
    下一次迭代生成器函数时,从yield语句后的语句继续执行,直到再次yield返回,或终止
  • return语句:
    终止函数的执行,下次调用会重新执行函数

协同程序:可以运用的独立函数调用,函数可以暂停或者挂起,并在需要的时候从离开的地方继续或重新开始

函数even_number返回一个生成器对象:

def even_number(m):
    n = 0
    while n < m:
        yield n
        n += 2


for i in even_number(10):
    print(i)

结果:

0
2
4
6
8

上机练习:生成器

异常处理

编写程序,输入两个数,输出他们的商,采用例外处理来处理两种错误,给出用户有好的信息
1)除数为0
2)输入了非法值

a = input()
b = input()


try:
    print(int(a)/int(b))
except ZeroDivisionError:
    print("除数不能为0,请重新输入!")
except (ValueError, TypeError):
    print("请输入整数!")

推导式

编写一个推导式,生成包含100在内的所有勾股数(i,j,k)的列表

# 自己做的
>>> [(i, j, k) for i in range(1,101) for j in range(i, 101) for k in range(j, 101) if i**2+j**2==k**2]
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (7, 24, 25), (8, 15, 17), (9, 12, 15), (9, 40, 41), (10, 24, 26), (11, 60, 61), (12, 16, 20), (12, 35, 37), (13, 84, 85), (14, 48, 50), (15, 20, 25), (15, 36, 39), (16, 30, 34), (16, 63, 65), (18, 24, 30), (18, 80, 82), (20, 21, 29), (20, 48, 52), (21, 28, 35), (21, 72, 75), (24, 32, 40), (24, 45, 51), (24, 70, 74), (25, 60, 65), (27, 36, 45), (28, 45, 53), (28, 96, 100), (30, 40, 50), (30, 72, 78), (32, 60, 68), (33, 44, 55), (33, 56, 65), (35, 84, 91), (36, 48, 60), (36, 77, 85), (39, 52, 65), (39, 80, 89), (40, 42, 58), (40, 75, 85), (42, 56, 70), (45, 60, 75), (48, 55, 73), (48, 64, 80), (51, 68, 85), (54, 72, 90), (57, 76, 95), (60, 63, 87), (60, 80, 100), (65, 72, 97)]
# 老师的答案
a = {
     tuple(sorted([i,j,k])) for i in range(1, 101) for j in range(1, 101)for k in range(1, 101) if i**2+j**2==k**2}
print(a)

斐波那契数列

编写一个生成器函数,能够生成斐波那契数列

def fib():
    a, b = 1, 1
    while True:
        yield a
        a, b = b, a+b


for fn in fib():
    print(fn)
    if fn > 1000:
        break

图像处理库

Pillow库

Python里的图像处理库:PIL(Python Image Library)

首先安装Pillow库

功能强大,可以对图像做各种处理:缩放、裁剪、旋转、滤镜、文字、调色板等

图像处理步骤

打开图像image.open(<路径+图像名+文件格式>)
Pillow库能自动根据文件内容确定格式
若图片在程序目录下,则不需要附带路径,直接将图像名+文件格式作为参数

处理图像:大量方法

存取或显示图像
im.show()显示
im.save(<文件名>)保存,不指定文件名,则将原来的覆盖

PIL图像操作

缩略图
thumbnail函数:thumbnail(size, Image.ANTIALIAS)
参数size为一个元祖,指定生成缩略图的大小
Image.ANTIALIAS使图片更平滑,不会出现锯齿
直接对内存中的原图进行修改,但是修改完的图片需保存,处理后的图片不会被拉伸

模糊效果

from PIL import Image, ImageFilter
im = Image.open("timg.jpg")  # 打开当前路径下的一个jpg文件
im2 = im.filter(ImageFilter.BLUR)  # 应用模糊滤镜
im2.save('blur.jpg', 'jpeg')

原图片:
[Python] Python学习笔记:高级特性与高级拓展模块_第1张图片
处理后:
[Python] Python学习笔记:高级特性与高级拓展模块_第2张图片
添加文字

from PIL import Image, ImageDraw, ImageFont
img = Image.open("timg.jpg")
font = ImageFont.truetype('simsun.ttc', 100)  # 设置带添加文字大小为100,字体为宋体
draw = ImageDraw.Draw(img)  # 在img上创建可绘图对象Draw
draw.text((100, 10), '雪地', (255, 0, 0), font=font)  # 添加文字
img.save('snow.jpg', 'jpeg')

[Python] Python学习笔记:高级特性与高级拓展模块_第3张图片

小程序:PIL生成验证码

from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random


def rndChar():  # 随机字母
    return chr(random.randint(60, 90))


def rndColor():  # 随机颜色1  文字颜色
    return random.randint(64, 255), random.randint(64, 255), random.randint(64, 255)


def rndColor2():  # 随机颜色2  背景颜色
    return random.randint(32, 127), random.randint(32, 127), random.randint(32, 127)


width = 60 * 4
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))  # 底色生成白色
font = ImageFont.truetype('arial.ttf', 36)
draw = ImageDraw.Draw(image)
for x in range(width):  # 填充每个像素
    for y in range(height):
        draw.point((x, y), fill=rndColor())
for t in range(4):  # 输出文字
    draw.text((60*t+10, 10), rndChar(), font=font, fill=rndColor2())
image = image.filter(ImageFilter.BLUR)  # 模糊
image.save('code.jpg', 'jpeg')

在这里插入图片描述

数据可视化

numpy矩阵处理库

numpy是Python用于处理大型矩阵的一个速度极快的库
可以做向量和矩阵的运算,包括各种创建矩阵的方法,以及一般的矩阵运算、求逆、求转置。

底层函数使用C写的,运行速度较快

numpy方法

  • 矩阵计算
    创建矩阵 a = np.matrix([])
    矩阵求逆 a.I
    矩阵转置 a.T
    矩阵乘法 a*bnp.dot(a,b)

  • 对象属性
    np.shape 数组形状,矩阵则为n行m列
    np.size 对象元素的个数
    np.dtype 制定当前numpy对象的整体数据

>>> import numpy as np
>>> a = np.matrix([[1,2],[3,4]])
>>> a.I
matrix([[-2. ,  1. ],
        [ 1.5, -0.5]])
>>> a.T
matrix([[1, 3],
        [2, 4]])
>>> a.I * a
matrix([[1.00000000e+00, 0.00000000e+00],
        [1.11022302e-16, 1.00000000e+00]])
>>> b = np.matrix([[7,6],[5,4]])
>>> a*b
matrix([[17, 14],
        [41, 34]])
>>> a.shape
(2, 2)
>>> a.size
4
>>> a.dtype
dtype('int32')

注意
矩阵中元素的类型必须同为整数型,或者同为浮点数型
老师课件中显示的类型为int64,我查了查
[Python] Python学习笔记:高级特性与高级拓展模块_第4张图片
数据类型转换可参考numpy数据类型dtype转换.

matplotlib绘图库

matliotlib是python的一个绘图库。
可绘制简单的散点图、折线图、甚至三维图形、动画等。

基本思路

通过将图像上的一些点的坐标连接起来,即可绘制函数的近似图像,当点越多时,所绘图像越接近函数图像。

  • numpy库的linspace()函数生成数组:
    nmpy.linspace(,,)
    生成一个存放等差数列的数组,数组元素为浮点型,三个参数为:数列起始值、终止值(默认包含自身)、数列元素个数

  • matplotlib库的plot()函数用来画图
    可以设定图形颜色、线条线型、做标记等

简单函数图像

简单图形:

import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 50)
plt.plot(x, np.sin(x))  # 若没有第一个参数x,图形的x坐标默认为数组的索引
plt.show()  # 显示图形

[Python] Python学习笔记:高级特性与高级拓展模块_第5张图片
多个简单图形:

import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 50)
plt.plot(x, np.sin(x), x, np.sin(2*x))
plt.show()

[Python] Python学习笔记:高级特性与高级拓展模块_第6张图片

定制线型、标签图例

plot()函数的绘制样式参数表示
[Python] Python学习笔记:高级特性与高级拓展模块_第7张图片
定制线型

import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 50)
plt.plot(x, np.sin(x), 'r-o', x, np.sin(2*x), 'g--')
plt.show()

[Python] Python学习笔记:高级特性与高级拓展模块_第8张图片
标签图例

  • 坐标轴标签
    plt.xlabel(), plt.ylabel()

  • 图形标题
    plt.title()

散点图和直方图

散点图
函数scatter(x,y) (x,y)是点的坐标

import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2*np.pi, 50)
y = np.sin(x)
plt.scatter(x, y)
plt.show()

[Python] Python学习笔记:高级特性与高级拓展模块_第9张图片
直方图
函数hist(x,n) x是横坐标,n是条状图的数量

import matplotlib.pyplot as plt
import numpy as np
x = np.random.randn(1000)
plt.hist(x, 50)
plt.show()

[Python] Python学习笔记:高级特性与高级拓展模块_第10张图片

期末考试题

  1. s.remove(x)移除s中元素x
  2. int()只取小数的整数部分,即向下取整

两组数的差异

给出两组相同数量的整数,求这两组整数的差异估算,即:对应数差值平方之和。
第一组为a1, a2…an
第二组为b1, b2…bn
(a1-b1)^2+(a2-b2)^2+....+(an-bn)^2

输入:两行,每行是一组整数,用空格隔开
输出:一个整数

def diff(a, b):
    s = 0
    for i in range(len(a)):
        s += (a[i] - b[i])**2
    return s


a_list = list(map(int, input().split()))
b_list = list(map(int, input().split()))
print(diff(a_list, b_list))

回文字符串

给定一个字符串,判断它是否是回文字符串(即类似于peep, 12321这样的对称字符串),如果是输出True,不是则输出False。
判断过程中假定只考虑字母和数字字符,而且忽略字母的大小写和其它符号(如空格、标点符号等)。

输入:共一行,为一个字符串 love e vol;
输出:共一行,为True或False

def is_hui(a):
    a_list = list(a)
    s = []  # 或者说直接 s= ''
    for i in a_list:
        i.lower()
        if ord('a') <= ord(i) < ord('z'):
            s.append(i)  # s = s + i  这样就不用列表转字符串了,更简单
    a_str = ''.join(s)  # 列表转换为字符串
    return a_str == a_str[::-1]


st = input()
print(is_hui(st))

将列表转换为字符串''.join(s)

0的组合

给定一个包含若干个整数(可能存在重复整数)的列表,判断其中是否存在三个元素a,b,c,使得a+b+c=0?找出所有满足条件且不重复的这样的三个数的组合。

输入:共一行,列表中元素以空格隔开
-1 0 1 2 -1

输出:共一行,为不重复组合的个数,不存在这样的组合就输出0.
2(注:两个组合是-1,-1,2和-1,0,1)

def sum_0(lst):
    lst.sort()
    n = len(lst)
    st = set()
    for i in range(n):
        for j in range(i+1, n):
            for k in range(j+1, n):
                if lst[i] + lst[j] + lst[k] == 0:
                    st.add((lst[i], lst[j], lst[k]))
    return len(st)


a_list = list(map(int, input().split()))
print(sum_0(a_list))

注意:我本来想刚开始不排序,在st.add()处排序,但是排序后元组就变成了列表了,无法加入到集合当中,会报错。

乘积的列表

给定一个包含若干个整数的列表alist,要求返回输出列表blist,blist中的元素为除与alist对应位置上的元素之外其余各元素的乘积。

输入:共一行,列表中的元素以空格隔开
1 2 3

输出:共一行,为一个列表。
[6, 3, 2]
(注:原列表的1,对应输出6=23,原列表的2,对应输出3=13,原列表的3,对应输出2=1*2)

a_list = list(map(int, input().split()))
s = []
for i in a_list:
    p = 1
    for j in a_list:
        if i != j:
            p *= j
    s.append(p)
print(s)

破译密码

A国情报局抓获敌国间谍一名,从间谍身上搜出了若干密电,在严刑逼供之下,间谍说出了密电加密方法:将明文电报(仅由大写字母构成)中的所有字母均替换为字母表中向后看的第n个字母,如果超过Z,则从A继续数,这样就得到了密文,比如ATTACK,向后看第2个字母,就加密为CVVCFM。

可还没等到间谍说出加密用的密钥(数字n),就被卧底开枪打死,间谍临死前在地板上画了BYE三个字母。

情报局长看着一条条密电发了愁,但机智的你已经发现,原来间谍在告诉我们,所有密电的明文都以BYE结尾!

请编写程序破译这些密电吧!

输入:共一行字符串,全部由大写字母构成的密文
JNTQZCZF

输出:共一行字符串,破译后的明文
IMSPYBYE

a = input().upper()
l = [chr(i) for i in range(ord("A"), ord("Z")+1)]
n = l.index('E')-l.index(a[-1])
b = ""
for i in a[:-3]:
    b += l[(l.index(i) + n) % 26]
b += "BYE"
print(b)

你可能感兴趣的:(Python,python)