第七章 文件和数据格式化

7.1 文件的使用

7.1.1 文件的类型
# 一个文本文件,其内容为“计算机等级考试”,采用文本方式打开
# 注意:文本文件与Python程序文件放在同一个目录下
file = open("1.txt", mode="rt", encoding="UTF-8")
read_content = file.readline()
print(read_content)
file.close()

# 运行结果
计算机等级考试

# 一个文本文件,其内容为“计算机等级考试”,采用二进制方式打开
file = open("1.txt", mode="rb")
read_content = file.readline()
print(read_content)
file.close()

# 运行结果
b'\xe8\xae\xa1\xe7\xae\x97\xe6\x9c\xba\xe7\xad\x89\xe7\xba\xa7\xe8\x80\x83\xe8\xaf\x95'
7.1.2 文件的打开和关闭

第七章 文件和数据格式化-LMLPHP

<变量名> = open(<文件路径及文件名>,<打开模式>)
# 以文本方式只读打开一个文件,读入后不能对文件进行修改
<变量名> = open(<文件名>, 'r')<变量名> = open(<文件名>)

# 以文本方式可读写的打开一个文件,可以读入并修改文件
<变量名> = open(<文件名>, 'r+')

# 以文本方式打开一个空文件,准备写入一批内容,并保存为新文件
<变量名> = open(<文件名>, 'w')

# 以文本方式打开一个空文件或已有的文件,追加形式写入一批内容,更新原文件
<变量名> = open(<文件名>, 'a+')

# 以二进制方式只读打开一个文件,读入后不能对文件进行修改
<变量名> = open(<文件名>, 'rb')
<变量名>.close()
7.1.3 文件的读写
file = open(<文件路径及名称>, "r")
for line in file:
	print(line)	# 处理一行数据 
f.close
f = open("c.txt", "w")
f.write('新年都未有芳华\n')
f.write('二月初惊见草芽\n')
f.write('白雪却嫌春色晚\n')
f.write('故穿庭树作飞花\n')
f.close()
ls = ['新年都未有芳华\n','二月初惊见草芽\n','白雪却嫌春色晚\n','故穿庭树作飞花\n']
f = open("c.txt", "w")
f.writelines(ls)
f.close()
新年都未有芳华
二月初惊见草芽
白雪却嫌春色晚
故穿庭树作飞花

7.2 数据组织的维度

7.2.1 一维数据
7.2.2 二维数据
7.2.3 高维数据

7.3 一维数据的处理

7.3.1 一维数据的表示
北京	上海	天津	重庆
北京,上海,天津,重庆
北京
上海
天津
重庆
北京;上海;天津;重庆
7.3.2 一维数据的存储
ls = ["北京", "上海", "天津", "重庆"]
file = open("city.csv", mode="w", encoding="UTF-8")
file.write(",".join(ls) + "\n")
file.close()

# 运行结果
北京,上海,天津,重庆
7.3.3 一维数据的处理
file = open("city.csv", mode="r", encoding="UTF-8")
ls = file.read().strip("\n").split(",")
file.close()
print(ls)

# 运行结果
['北京', '上海', '天津', '重庆']

7.4 二维数据的处理

7.4.1 二维数据的表示
7.4.2 二维数据的存储
ls = [
        ['指标', '2014年', '2015年', '2016年'],
        ['居民消费价格指数', '102', '101.4', '102'],
        ['食品', '103.1', '102.3', '104.6'],
        ['烟酒及用品', '994', '102.1', '101.5'],
        ['衣着', '102.4', '102.7', '101.4'],
        {'家庭设备用品', '101.2', '101', '100.5'},
        ['医疗保健和个人用品', '101.3', '102', '101.1'],
        ['交通和通信', '99.9', '98.3', '98.7'],
        ['娱乐教育文化', '101.9', '101.4', '101.6'],
        ['居住', '102', '100.7', '101.6'],
    ]
file = open("city.csv", mode="w", encoding="UTF-8")
for row in ls:
    file.write(",".join(row)+"\n")
file.close()

# 运行结果
指标,2014,2015,2016年
居民消费价格指数,102,101.4,102
食品,103.1,102.3,104.6
烟酒及用品,994,102.1,101.5
衣着,102.4,102.7,101.4
家庭设备用品,101.2,101,100.5
医疗保健和个人用品,101.3,102,101.1
交通和通信,99.9,98.3,98.7
娱乐教育文化,101.9,101.4,101.6
居住,102,100.7,101.6
7.4.3 二维数据的处理
ls = []
file = open("city.csv", mode="r", encoding="UTF-8")
for line in file:
    ls.append(line.strip("\n").split(","))
file.close()
print(ls)

# 运行结果
[['指标', '2014年', '2015年', '2016年'], ['居民消费价格指数', '102', '101.4', '102'], ['食品', '103.1', '102.3', '104.6'], ['烟酒及用品', '994', '102.1', '101.5'], ['衣着', '102.4', '102.7', '101.4'], ['家庭设备用品', '101.2', '101', '100.5'], ['医疗保健和个人用品', '101.3', '102', '101.1'], ['交通和通信', '99.9', '98.3', '98.7'], ['娱乐教育文化', '101.9', '101.4', '101.6'], ['居住', '102', '100.7', '101.6']]
for row in ls:
	for item in row:
		<对第row行第item列元素进行处理>
# 此处省略去从CSV获取数据到二维列表ls
for row in ls:
    line = " "
    for item in row:
        line = line + "{:10.7}\t".format(item)
    print(line)
    
# 运行结果
 指标				201420152016年     	
 居民消费价格指   	 102          101.4       102       	
 食品				103.1		 102.3		 104.6     	
 烟酒及用品		  994          102.1       101.5     	
 衣着				102.4		 102.7       101.4     	
 家庭设备用品		 101.2		   101        100.5     	
 医疗保健和个人   	 101.3     	  102         101.1     	
 交通和通信     	  99.9         98.3        98.7      	
 娱乐教育文化    	 101.9     	  101.4       101.6     	
 居住        	   102       	100.7     	 101.6     	

7.5 实例解析——国家财政数据趋势演算

# FinancePredict.py
def parseCSV(filename):
    dataNames, data = [], []
    f = open(filename, 'r', encoding='utf-8')
    for line in f:
        splitedLine = line.strip().split(',')
        if '指标' in splitedLine[0]:
            years = [int(x[:-1]) for x in splitedLine[1:]]
        else:
            dataNames.append('{:10}'.format(splitedLine[0]))
            data.append([float(x) for x in splitedLine[1:]])
    f.close()
    return years, dataNames, data


def means(data):
    return sum(data) / len(data)


def linearRegression(xlist, ylist):
    xmeans, ymeans = means(xlist), means(ylist)
    bNumerator = - len(xlist) * xmeans * ymeans
    bDenominator = - len(xlist) * xmeans ** 2
    for x, y in zip(xlist, ylist):
        bNumerator += x * y
        bDenominator += x ** 2
    b = bNumerator / bDenominator
    a = ymeans - b * xmeans
    return a, b


def calNewData(newyears, a, b):
    return [(a + b * x) for x in newyears]


def showResults(years, dataNames, newDatas):
    print('{:^60}'.format('国家财政收支线性估计'))
    header = '指标       '
    for year in years:
        header += '{:10}'.format(year)
    print(header)
    for name, lineData in zip(dataNames, newDatas):
        line = name
        for data in lineData:
            line += '{:>10.1f}'.format(data)
        print(line)


def main():
    newyears = [x + 2010 for x in range(7)]
    newDatas = []
    years, dataNames, datas = parseCSV('finance.csv')
    for data in datas:
        a, b = linearRegression(years, data)
        newDatas.append(calNewData(newyears, a, b))
    showResults(newyears, dataNames, newDatas)


main()

# 运行结果
                         国家财政收支线性估计                         
指标             2010      2011      2012      2013      2014      2015      2016
全部收入        105359.6  114550.1  123740.6  132931.0  142121.5  151312.0  160502.4
中央收入         48169.1   52283.8   56398.5   60513.2   64627.9   68742.7   72857.4
地方收入         57190.6   62266.3   67342.1   72417.8   77493.6   82569.3   87645.1
全部支出        122936.9  133645.7  144354.5  155063.3  165772.1  176480.9  187189.8
中央支出         19037.5   20390.9   21744.3   23097.7   24451.1   25804.5   27157.9
地方支出        103899.4  113254.8  122610.2  131965.6  141321.0  150676.4  160031.9

习题7

一、选择题
  1. 关于Python变量使用,下列说法中错误的是:_____

    A 变量使用不必先声明
    B 变量使用无需先创建和赋值
    C 变量使用无需指定数据类型
    D 可以使用del释放变量的内存资源

    正确答案:B

  2. 关于文件,下列说法中错误的是:_____

    A 对已经关闭的文件进行读写操作会默认再次打开文件

    B 对文件操作完成后即使不关闭程序也不会报错,所以可以不关闭文件

    C 对于非空文本文件,read()返回字符串,readlines()返回列表

    D file = open(filename, “rb”)表示以只读、二进制方式打开名为filename的文件

    正确答案:A

  3. 给出以下代码:

    fname = input("请输入要写入的文件:")
    fo = open(fname, "w+")
    ls = ["唐诗", "宋词", "元曲"]
    fo.writelines(ls)
    fo.seek(0)
    for line in fo:
        print(line)
    fo.close()
    

    上述代码正确的是:_____

    A 唐诗 B “唐诗” C 唐诗宋词元曲 D “唐诗宋词元曲”

    宋词 “宋词”

    元曲 “元曲”

    正确答案:C

  4. 下列选项中不是Python对文件读操作方法的是:_____

    A read() B readline() C readall() D readlines()

    正确答案:C

  5. 将一个文件与程序的对象关联起来的过程,称为:_____

    A 文件读取 B 文件写入 C 文件打开 D 文件关闭

    正确答案:C

  6. 在读写文件之前,需要创建文件对象,采用的方法是:_____

    A create B folder C open D File

    正确答案:C

  7. 有一非空文本文件textfile.txt,执行下述代码:

    file = open("textfile.txt", "r")
    for line in file.readline():
        line += '[prefix]'
    file.close()
    for line in file.readline():
        print(line)
    

    程序输出的结果是:_____

    A 逐行输出文件内容 B 逐行输出文件内容,但每行以[prefix]开头

    C 报错 D 文件被清空,所以没有输出

    正确答案:C

  8. 关于CSV文件处理,下述描述中错误的是:_____

    A 因为CSV文件以半角逗号分隔每列数据,所以即使列数据为空也要保留逗号

    B 对于包含英文半角逗号的数据,以CSV文件保存时需进行转码处理

    C 因为CSV文件可以有Excel打开,所以是二进制文件

    D 通常,CSV文件每行表示一个一维数据,多行表示二维数据

  9. 下列文件/语法格式通常不用作高维数据存储的一项是:_____

    A HTML B XML C JSON D CSV

    正确答案:D

  10. 采用Python语言对CSV文件写入,最可能采用的字符串方法是:_____

    A strip() B split() C join() D format()

    正确答案:C

二、编程题
  1. 统计次数。输入一个文件和一个字符串,统计该字符在文件中出现的次数。

    # 定义一个函数,用于统计指定字符在指定文件中出现的次数
    def countstr(filename, str1):
        # 将文件名赋值给一个变量
        filenames = filename
        # 打开文件
        f = open(filenames, 'r')
        # 初始化计数器
        count = 0
        # 逐行读取文件内容
        for line in f:
            # 遍历每个字符
            for i in line:
                # 如果字符与指定字符相同,则计数器加一
                if i == str1:
                    count += 1
        # 输出结果
        print(f'{str1}字符在{filename}文件中出现{count}次')
    
    # 定义一个主函数,用于输入文件名和指定字符,并调用 countstr 函数进行统计
    def main():
        filename = input("请输入文件名称:")
        str1 = input("请输入需要统计的字符:")
        countstr(filename, str1)
    
    # 调用主函数
    main()
    
    # 运行结果
    请输入文件名称:1.txt
    请输入需要统计的字符:a
    a字符在1.txt文件中出现9
  2. 替换大小写。假设有一个英文文本文件,编写一个程序读取其内容并将里面的大写字母变成小写字母,小写字母变成大写字母。

    # 打开文件并读取内容
    with open('1.txt', 'r') as f:
        text = f.read()
    # 将大小写字母互换
    text = text.swapcase()
    # 打印结果
    print(text)
    
    # 运行结果
    AAAAAAAAA
    aaaaaaaaa
    BBBBBBBBBB
    bbbbbbbbbb
    CCCCCCCCCC
    cccccccccc
    DDDDDDDDDD
    dddddddddd
    
  3. 编写矩阵。编写一个程序,生成一个10x10的随机矩阵并保存为文件(空格分隔行向量,换行分隔列向量),再写程序将刚才保存的矩阵另存为CSV格式,用Excel或文本编辑器打开查看结果。

    import random
    
    # 生成 10x10 的随机矩阵
    matrix = [[random.randint(1, 100) for j in range(10)] for i in range(10)]
    
    # 将矩阵保存为文件(空格分隔行向量,换行分隔列向量)
    with open('matrix.txt', 'w') as f:
        # 遍历每一行
        for row in matrix:
            # 将行向量转换为字符串,使用空格分隔
            row_str = ' '.join([str(x) for x in row])
            # 将该行字符串写入文件并换行
            f.write(row_str + '\n')
    
    # 将矩阵另存为 CSV 格式
    with open('matrix.csv', 'w') as f:
        # 遍历每一行
        for row in matrix:
            # 将行向量转换为字符串,使用逗号分隔
            row_str = ','.join([str(x) for x in row])
            # 将该行字符串写入文件并换行
            f.write(row_str + '\n')
    
    # 运行结果
    # 保存为文件
    75 74 4 2 2 13 42 17 56 54
    21 36 71 33 96 1 51 64 37 44
    33 15 4 28 91 80 58 6 33 78
    1 84 88 63 22 65 1 49 11 43
    5 77 100 28 51 54 58 72 83 76
    79 53 80 60 31 19 59 92 60 68
    2 97 63 53 52 70 69 84 19 69
    77 57 59 51 9 66 48 20 98 24
    89 69 38 68 12 27 36 96 82 55
    26 92 16 6 38 65 87 36 4 60
    
    #另存为 CSV 格式
    75	74	4	2	2	13	42	17	56	54
    21	36	71	33	96	1	51	64	37	44
    33	15	4	28	91	80	58	6	33	78
    1	84	88	63	22	65	1	49	11	43
    5	77	100	28	51	54	58	72	83	76
    79	53	80	60	31	19	59	92	60	68
    2	97	63	53	52	70	69	84	19	69
    77	57	59	51	9	66	48	20	98	24
    89	69	38	68	12	27	36	96	82	55
    26	92	16	6	38	65	87	36	4	60
    
  4. 替换源代码文件的大小写。编写一个程序,读取一个Python源代码文件,将文件中所有除保留字外的小写字母换成大写字母,生成后的文件要能够被Python解释器正确执行。

    import keyword
    
    
    def convert_code(filename):
        with open(filename, mode='r', encoding="UTF-8") as f:
            source_code = f.read()
    
        # 获取Python的所有保留字
        reserved_words = keyword.kwlist
    
        # 将小写字母转换成大写字母,但是不将保留字转换成大写字母
        new_code = []
        for line in source_code.split('\n'):
            new_line = []
            for word in line.split():
                if word.lower() in reserved_words:
                    new_line.append(word)
                else:
                    new_line.append(word.upper())
            new_code.append(' '.join(new_line))
    
        # 生成新的文件
        new_filename = filename.split('.')[0] + '_new.py'
        with open(new_filename, mode='w', encoding="UTF-8") as f:
            f.write('\n'.join(new_code))
        return new_filename
    
    
    convert_code("统计次数.py")
    
  5. 列表转换为CSV。编写一个程序,要去能够将元素为任意Python支持的类型(包括含有半角逗号的字符串)的列表转储为CSV,并能够重新正确解析为列表。

    import csv
    import io
    
    
    def list_to_csv(data):
        # 创建一个字符串缓冲区
        csv_data = io.StringIO()
        # 创建一个 CSV writer 对象
        writer = csv.writer(csv_data)
        # 遍历列表中的每一行数据
        for row in data:
            # 将每一行数据写入 CSV 文件中
            writer.writerow(row)
        # 返回 CSV 格式的字符串
        return csv_data.getvalue()
    
    
    def csv_to_list(csv_string):
        # 创建一个空列表,用于存储解析后的数据
        data = []
        # 创建一个字符串缓冲区,用于读取 CSV 格式的字符串
        csv_data = io.StringIO(csv_string)
        # 创建一个 CSV reader 对象
        reader = csv.reader(csv_data)
        # 遍历 CSV 文件中的每一行数据
        for row in reader:
            # 将每一行数据添加到列表中
            data.append(row)
        # 返回解析后的列表
        return data
    
    
    # 测试代码
    data = [[1, 'a', True], [2, 'b', False], [3, 'c,d', True]]
    csv_string = list_to_csv(data)
    print(csv_string)
    parsed_data = csv_to_list(csv_string)
    print(parsed_data)
    
    # 运行结果
    1,a,True
    2,b,False
    3,"c,d",True
    
    [['1', 'a', 'True'], ['2', 'b', 'False'], ['3', 'c,d', 'True']]
    
06-01 21:59