Python程序设计 实验8:Numpy 和标准库

简介: Python程序设计 实验8:Numpy 和标准库

实验过程及内容(实验思路,代码实现过程以及运行并测试结果):


1. Numpy 基础:


运行以下代码,理解每句代码的意思或输出结果(print 语句):


(a)
mysqrt = [math.sqrt(x) for x in range(0,5)]
mycrt = [x**(1/3) for x in range(0,5)]
npData = np.array(mysqrt)
print(“The shape:”, npData.shape)
print(“The dimensionality:”, npData.ndim)
print(“The type:”, npData.dtype)
twoDarray = np.array([mysqrt, mycrt])
print(“The shape:”, twoDarray.shape)
print(“The dimensionality:”, twoDarray.ndim)
print(“The type:”, twoDarray.dtype)

【代码解释】


npData.shape:shape函数的功能是查看矩阵或者数组的维数。


npData.ndim:ndim函数的功能是查看数组中每个元素的维数。


npData.dtype:dtype函数的功能是查看该数组中每个元素的数据类型。


      因此,对于npData = np.array(mysqrt)数组的维数是5,每个元素是单独的浮点型数,因此每个元素的维数是1.又因为每个元素是浮点型小数,因此数据类型是float64。


      同理,对于twoDarray = np.array([mysqrt,mycrt])数组的维数是2*5,每个元素是两个浮点型数组成的元组,因此每个元素的维数是2.又因为每个元素是浮点型小数,因此数据类型是float64。


【运行结果】


(b)

zeros = np.zeros(3)
zMat = np.zeros((4,3))
ones = np.ones(3)
oMat = np.ones((3,2))
diag = np.eye(4)
rng = np.arange(5)
dm = np.diag(rng)
print(dm.shape)
zMat_re = zMat.reshape(6,2)

【代码解释】

通过分析代码,可知最终起作用的代码只有如下三行的部分:


fb4e1228b9114fdf9af01752be0dc83e.png


numpy.arange(start, stop, step, dtype = None)在给定间隔内返回均匀间隔的值。值在半开区间 [开始,停止]内生成(换句话说,包括开始但不包括停止的区间),返回的是 ndarray 。


np.diag()以一维数组的形式返回方阵的对角线(或非对角线)元素,或将一维数组转换成方阵(非对角线元素为0)


因此首先生成了一个数组[0,1,2,3,4],然后以这个数组为对角线生成了一个5*5的矩阵,再调用函数打印矩阵的维数,因此将输出(5,5)


【运行结果】

6c3e3e0f83a84db788d5af1b0b87ba50.png

( c )


A = np.random.randint(0,10, size = (3,2))
B = np.random.randint(0,10, size = (3,3,3))
C = np.random.randint(0,10, size = (3,1))
print(A**2)
print(np.sqrt(A))
print(A + C)
print(B + C)
B[:, 0:2 , 0:2 ] -= 20
print(B)

【代码解释】


np.random.randint(a,b, size)表示生成范围在a~b内的,维度为size的矩阵。


A**2表示将A中的每个元素平方。


np.sqrt(A)表示将A中的每个元素开平方。


A + C、B + C:表示将两个矩阵相加,将两个矩阵对应相加,当遇到两矩阵大小不一样的情况,两个矩阵的shape必须满足若干个小矩阵可以组成与大矩阵同大小的矩阵。此时,将小矩阵中的元素对应地加到大矩阵上。


B[:, 0:2 , 0:2 ] -= 20:通过切片选择第一维的全部,第二维的前两行,第三维的前两列中的每个元素各减20。


【运行结果】


由于本题中使用了随机数生成数据,因此本题的数据具有偶然性。本次运行结果只对如下生成的A、B、C三个数据:


f335aef907424ce38cbf7986829352c5.png3e61d0c56b984b3a96710722847101a4.png01e9695fbdcb440787736b965ce12cfc.png


A**2

ae4d313bc995420ab35874bca7b63317.png

numpy.sqrt(A)

9e0cee120f164d8298466485accc8da7.png

A + C

53648fc443244ae3a940845bd2db94a5.png

B + C

7420904bf9364138ade78f939e259ab1.png

B[:, 0:2 , 0:2 ] -= 20

92b1c0cd45554c9da63977b98d890731.png

(d)

from numpy import linalg
A = np.array([[2, 1, -2],[1,-1,-1], [1, 1 ,3]])
b = np.array([3, 0, 12])
x = linalg.solve(A,b)
print(x)


【代码解释】


首先创建了两个数组。


solve函数有两个参数a和b。a是一个N*N的二维数组,而b是一个长度为N的一维数组,solve函数找到一个长度为N的一维数组x,使得a和x的矩阵乘积正好等于b,数组x就是多元一次方程组的解。


【运行结果】


b91ea218ea9c479cbfdfd1e486531325.png

2. Numpy 应用 1:


      给定一个矩阵 2n×2n,将该矩阵分成四个象限(参见示例),然后返回一个新的 2×2 矩阵,包含每个象限的平均值。

例子:

原矩阵: 7dd2e48f1b234dbfa3d92497f7d4954f.png

新矩阵:


7a04d079273e4b37ac901df90f0b81c4.png


【解题思路】

      对于本题,由于前面第一题已经介绍了切片,获取矩阵维度以及获取矩阵部分的累加和的方法,本题中可以直接使用。可以首先获取矩阵的维度,从而获取结果矩阵中的4个数分别与原矩阵的四个象限的对应关系。再通过切片选定区域后,使用sum进行求和,最后再除以维度即可。


【编程实现】

import numpy  
# 获取初始矩阵  
matrix1 = numpy.array(  
    [[1, 2, 5, 7], [4, 1, 8, 0], [2, 0, 5, 1], [0, 2, 1, 1]])  
# 获得矩阵维度  
n = (int)(matrix1.shape[0]/2)  
# 进行切片分割  
res = numpy.array(  
    [[matrix1[:n, :n].sum()/(n**2), matrix1[:n, n:].sum()/(n**2)], [matrix1[n:, :n].sum()/(n**2), matrix1[n:, n:].sum()/(n**2)]])  
print(res)  


    首先利用shape函数获取矩阵的维度,并除以二获得四个象限的分界点。然后通过切片获取每个象限并求和。最后将每个象限的和除以象限中元素个数(n^2)即为平均值,然后再利用array函数将四个平均值转成数组的形式。


【运行测试】


8923cedeec994692ac0f3dcdbec6fcc9.png

3. Numpy 应用 2:


      仿照课件中利用 numpy 处理图片的方法,选择一张自己喜欢的图片进行处理,方法不限(如调整亮度、彩色变黑白、模糊化等等;鼓励自学图片处理方法,提出自己的方法)。


【解题思路】

      在本题中,我使用隔行取样对图片进行了压缩。当我们遇到图片需要压缩的情况,常常可以想到进行隔行取样的方法,完成对图片的压缩。


【编程实现】


# 引入所需的库  
import numpy as np  
import matplotlib.pyplot as plt  
from PIL import Image  
# 打开图片文件  
image = Image.open('test.jpg')  
# 将图片转成矩阵表示  
image_array = np.array(image)  
# 进行图片压缩  
image_array1 = image_array[::2, ::2, ]  
# 展示图片  
plt.imshow(image_array1)  
plt.show() 

 首先打开图片文件,转成矩阵之后,采用切片进行隔行取样,此处需注意,隔行的值不能太大,否则图像会严重失真。取样后直接输出结果即可。


【运行测试】

原图:

a432d3dfed77494f866c35d42888f839.png

压缩后的图:

ecceea760d5e43b98b8b5cc844fe4343.png

      可以看到,图片被压缩了。被压缩的图片比压缩前模糊了。


4. Python 标准库 itertools:


      编写函数 sum0(lst),接受一个包含 8 个整数的列表lst。如果列表中的某些非空子集的总和返回 0,则返回 True。例如,lst=[-3, 11, 21, 5, 10, 11, 2, 1]返回 True,因为非空子集[-3, 2, 1]中数字加起来总和为 0;又如 lst=[2, 3, 4, 5, 6, 7, 8, 9]时,函数返回 False。


【解题思路】

      首先,本题中需要完成的是对所有组合情况的累加和检查,因此需要获得所有组合情况。我们不妨利用itertools中的combinations获取确定长度下的组合的迭代器并对部分和进行判断,再利用一层循环对组合长度进行遍历。


【编程实现】

import itertools  
# 定义判定是否存在组合为0函数 
def sum0(lst):  
    # 获取不同长度的组合  
    for num in range(1, 9):  
        # 获取相同长度下的不同组合迭代器  
        it = itertools.combinations(lst, num)  
        # 遍历判断是否和为0  
        for i in it:  
            if sum(i) == 0:  
                return True  
    return False  
lst = [1, 2, 3, 4, 5, 6, 7, -28]  
print(sum0(lst)) 


  首先利用外层循环遍历每次获得的组合的长度,然后对于每个确定的长度通过itertools.combinations获取全部组合的迭代器,然后再利用一层循环遍历整个迭代器判断部分和是否为零,如果为零直接返回True。如果遍历完所有长度的所有组合后都没有部分和为零则返回False。


【运行测试】

当存在部分和为0时:

6c9a42d1dda643bbab41fae6820f1703.png

当不存在部分和为0时:

e12e56fba12c411180a846505ed06cdf.png

5. Python 标准库 datetime:


      编写函数 calculate_age,计算自出生以来到目前为止,生活的总天数,总月数,总年数,返回元组(days,months,years);


【解题思路】

      可以通过datetime获取当前时间并与自己的生日做差,将时间差转换为天数,然后再一次转换为对应的总年月日数。


【编程实现】


import datetime  
# 定义计算年龄函数  
def calculate_age():  
    # 将生日转为datetime  
    birthday = datetime.datetime(2000, 9, 28)  
    # 获取datetime当前时间  
    cur = datetime.datetime.now()  
    # 获得日期差  
    during_days = (cur-birthday).days  
    # 获得对应年月日  
    return(during_days, (int)(during_days/30), (int)(during_days/365))  
print(calculate_age()) 

 首先获取当前时间并将自己的生日转为datetime类,并直接做差获得日期差,再利用日期差,获得对应的年月日的差并转为元组。


【运行测试】


37ffc17427e840e3bbae358559d7e19b.png


6. Python 标准库 collections, sys, os: 统计目前写过的 python 代码。


(1) 把实验、作业、小测的代码文件整理好,分开放在“作业”文件夹、“实验”文件夹、“小测”文件夹,三个文件夹放到同一个文件夹“代码”中。


【解题思路】

      按照要求整理对应文件即可:


【结果如下】

65873a13bc9e44a18d1c2fb35421e5c3.png

58841061c07a45788174b53555887dfd.png

a75a60913c9a40ffa76fe1c688c7781b.png


(2) 编写函数,统计“代码”文件夹中 python 文件的个数(file_num),写过的代码行数( code_line ),代码中空行的行数 ( space_lines ),注释的行数 (comments_lines,只统计以#开头的),返回元组记录上述信息。


【解题思路】

      通过最外层循环遍历代码文件夹下的三个文件夹,对于每个文件夹,再使用一层循环遍历文件夹中的每个文件,对于每个文件,首先判断拓展名是不是‘.py’如果不是则继续下一个文件的判断。如果是,则按行读入文件,每读入一行,行计数器加一。对于每一行,分别进行空行与注释的判断,满足则对应计数器加一。当所有文件都判断完毕后,直接返回结果元组即可。


【编程实现】

import collections  
import sys  
import os  
def getInfo(path):  
    # path = './code'  
    # 定义各个计数器  
    file_num = 0  
    code_line = 0  
    space_lines = 0  
    comments_lines = 0  
    # 对文件路径非法情况进行特判  
    if not os.path.exists(path):  
        print('Invalid Path!')  
        return  
    # 首先遍历“作业”文件夹、“实验”文件夹、“小测”文件夹  
    for i in os.listdir(path):  
        # 遍历各个文件夹中的每个文件  
        for j in os.listdir(path+'/'+i):  
            # 如果是Python文件,则对应计数器加一  
            if j.endswith('.py'):  
                file_num += 1  
                # 按行读入Python文件  
                for line in open(path+'/'+i+'/'+j, encoding='utf-8'):  
                    # 对于每行 对应计数器加一  
                    code_line += 1  
                    # 如果为空行 则空行计数器加一  
                    if line == "\n":  
                        space_lines += 1  
                    # 如果为注释 则注释计数器加一  
                    if line.startswith('#'):  
                        comments_lines += 1  
    # 返回结果元组  
    return(file_num, code_line, space_lines, comments_lines)  
print(getInfo('./code')) 


首先判断路径的合法性,当出现非法路径,则直接给出错误信息并返回。对于合法的路径,通过外层循环遍历三个文件夹,再通过一层循环遍历各个文件。对于每个文件,首先判断文件的拓展名是否为‘.py’,如果不是则判断下一个,如果是,则按行将文件读入,再对每行进行空行和注释的判断。当处理完所有文件后,将结果以元组的形式返回。


【运行测试】

5d1f84f6b48d46c2a6b6a9d3326d63c8.png

(3) 在(2)基础上,允许用户输入指定的文件或文件夹,统计输入文件或文件夹的信息。例如,假设 python 文件名为 code_stat.py,运行方法如下:


78e267b8d0c346689c85689a177bc2f0.png

【解题思路】

      与(2)思路大致相同,只需加入对路径或文件的判断即可,在此处,我使用os.path.isdir(path)和os.path.isfile(path)完成对路径或文件的判断。


【编程实现】


import collections  
import sys  
import os  
def getInfo(path):  
    # path = './code'  
    file_num = 0  
    code_line = 0  
    space_lines = 0  
    comments_lines = 0  
    if not os.path.exists(path):  
        print('Invalid Path!')  
        return  
    # 如果是路径  
    if os.path.isdir(path):  
        for j in os.listdir(path):  
            if j.endswith('.py'):  
                file_num += 1  
                for line in open(path+'/'+j, encoding='utf-8'):  
                    code_line += 1  
                    if line == "\n":  
                        space_lines += 1  
                    if line.startswith('#'):  
                        comments_lines += 1  
    # 如果是Python文件  
    elif os.path.isfile(path) and path.endswith('.py'):  
        file_num += 1  
        for line in open(path, encoding='utf-8'):  
            code_line += 1  
            if line == "\n":  
                space_lines += 1  
            if line.startswith('#'):  
                comments_lines += 1  
    return(file_num, code_line, space_lines, comments_lines)  
print(getInfo('./code/Homework')) 

大致思路与(2)相同,区别只是对传入的路径进行了判断,如果是路径,则依次遍历路径中的文件进行统计;如果是文件,则直接读取文件进行统计。


【运行测试】

      对路径的测试:

13626215d93648ff9825cbe3ddd1b64e.png

      对文件的测试:

712498d17ea741f3aa5bdcd570b62a01.png

实验结论:


      在本次实验中,我学习并学会了Numpy库的一些函数的使用方法,与之前学过的C++相比,Python多元化的库为Python处理更多数据提供了良好的技术支持。Numpy库中涵盖广泛,可以处理矩阵,线性代数等,也可以处理图片。这些都方便了我使用Python完成对数据的进一步处理。

      我也学会了使用Python的标准库itertools,datetime,collections, sys,和os这些都很大程度上方便了编程。

      此外,在本次实验过程中,我也遇到了一些问题:


在完成对图片的处理时调用了image.shape结果抛出异常。在查阅资料后发现这是读取的图片格式和PIL中Image 读取的图片格式差异问题导致的,解决方法就是在save操作之前,将图片的格式转化一下即可解决问题。


在完成第6题读入Python代码文件时,抛出如下异常:

b14964bdc52846d09ef26518f91d6f88.png

      通过查阅资料发现,发生该异常的原因是编码格式不是Python可以读取的格式,只需在读入的地方加上“encoding=utf-8”即可。


      此外,在本次实验中我发现,代码的容错性也是编程过程中需要注意的点。在进行实验六的过程中,多次由于路径不对造成异常的发生,因此需要在程序执行前加入判断语句,对路径有效性进行检验。

相关文章
|
10天前
|
存储 缓存 JavaScript
python实战篇:利用request库打造自己的翻译接口
python实战篇:利用request库打造自己的翻译接口
26 1
python实战篇:利用request库打造自己的翻译接口
|
20天前
|
Web App开发 Python
在ModelScope中,你可以使用Python的浏览器自动化库
在ModelScope中,你可以使用Python的浏览器自动化库
15 2
|
25天前
|
数据格式 Python
如何使用Python的Pandas库进行数据透视图(melt/cast)操作?
Pandas的`melt()`和`pivot()`函数用于数据透视。基本步骤:导入pandas,创建DataFrame,然后使用这两个函数转换数据格式。示例代码展示了如何通过`melt()`转为长格式,再用`pivot()`恢复为宽格式。输入数据是包含'Name'和'Age'列的DataFrame,最终结果经过转换后呈现出不同的布局。
38 6
|
25天前
|
数据挖掘 数据处理 索引
如何使用Python的Pandas库进行数据筛选和过滤?
Pandas是Python数据分析的核心库,其DataFrame数据结构便于数据操作。筛选与过滤数据主要包括:导入pandas,创建DataFrame,通过布尔索引、`query()`或`loc[]`、`iloc[]`方法筛选。
|
26天前
|
数据处理 Python
如何使用Python的Pandas库进行数据排序和排名?
Pandas在Python中提供数据排序和排名功能。使用`sort_values()`进行排序,如`df.sort_values(by='A', ascending=False)`进行降序排序;用`rank()`进行排名,如`df['A'].rank(ascending=False)`进行降序排名。多列操作可传入列名列表,如`df.sort_values(by=['A', 'B'], ascending=[True, False])`。
22 6
|
25天前
|
机器学习/深度学习 算法 数据挖掘
请解释Python中的决策树算法以及如何使用Sklearn库实现它。
决策树是监督学习算法,常用于分类和回归问题。Python的Sklearn库提供了决策树实现。以下是一步步创建决策树模型的简要步骤:导入所需库,加载数据集(如鸢尾花数据集),划分数据集为训练集和测试集,创建`DecisionTreeClassifier`,训练模型,预测测试集结果,最后通过`accuracy_score`评估模型性能。示例代码展示了这一过程。
|
26天前
|
JSON C语言 C++
【Python 基础教程 26】Python3标准库全面入门教程:一步步带你深入理解与应用
【Python 基础教程 26】Python3标准库全面入门教程:一步步带你深入理解与应用
60 1
|
12天前
|
数据采集 网络协议 API
python中其他网络相关的模块和库简介
【4月更文挑战第4天】Python网络编程有多个流行模块和库,如requests提供简洁的HTTP客户端API,支持多种HTTP方法和自动处理复杂功能;Scrapy是高效的网络爬虫框架,适用于数据挖掘和自动化测试;aiohttp基于asyncio的异步HTTP库,用于构建高性能Web应用;Twisted是事件驱动的网络引擎,支持多种协议和异步编程;Flask和Django分别是轻量级和全栈Web框架,方便构建不同规模的Web应用。这些工具使网络编程更简单和高效。
|
22天前
|
机器学习/深度学习 数据挖掘 Python
NumPy的基本操作(Python)
NumPy的基本操作(Python)
30 4
|
26天前
|
Python
深入探究 Python 标准库中的 sys 模块
【2月更文挑战第8天】
41 0