CS50P week6 file I/O

Lecture 6 - CS50’s Introduction to Programming with Python (harvard.edu)

Notes

list文件类型

  • 每行一个元素

open

# name = input("What's your name? ")

# file = open("names.txt", "w")
# file.write(name)
# file.close()

name = input("What's your name? ")

file = open("names.txt", "a")
file.write(f"{name}\n")
file.close()

注意:

  • 打开文件:file = open("names.txt", "w")"w"每次都是重写整个文件;file = open("names.txt", "a")"a"是append,在文件后面继续追加
  • 写入文件:file.write(f"{name}\n"),记得换行
  • 关闭文件:file.close()

with

with open("names.txt", "a") as file:
    file.write(f"{name}\n")

注意:

  • with 可以自动关掉文件,不用额外close
  • 记得换行

read

with open("names.txt", "r") as file:
    lines = file.readlines()

for line in lines:
    print("hello,", line.rstrip())

注意:

  • .rstrip() 可以去除额外的换行
  • file.readlines()能按行读取文件内容
  • 读文件也需要打开和关闭文件

将文件读取为list

names = []

with open("names.txt") as file:
    for line in file:
        names.append(line.rstrip())

for name in sorted(names):
    print(f"hello, {name}")

注意:

  • list增加是append() ,list排序是sorted
  • 读取文件为list

dic文件类型

  • 每行多个元素

读csv

students.csv
Hermoine,Gryffindor
Harry,Gryffindor
Ron,Gryffindor
Draco,Slytherin
students.py(list)
students = []

with open("students.csv") as file:
    for line in file:
        name, house = line.rstrip().split(",")
        students.append(f"{name} is in {house}")

for student in sorted(students):
    print(student)
students.py(dic)
students = []

with open("students.csv") as file:
    for line in file:
        name, house = line.rstrip().split(",")
        student = {"name": name, "house": house}
        students.append(student)

for student in students:
    print(f"{student['name']} is in {student['house']}")

注意:

  • name, house = line.rstrip().split(",")
  • student = {"name": name, "house": house}
dic 排序
students = []

with open("students.csv") as file:
    for line in file:
        name, house = line.rstrip().split(",")
        students.append({"name": name, "house": house})

for student in sorted(students, key=lambda student: student["name"]):
    print(f"{student['name']} is in {student['house']}")

注意:

  • lambda函数:key=lambda student: student["name"]即对于一个匿名函数,给定一个学生(对象),获取其name元素并返回为key(键)
csv库

引入csv库,可以更加方便的处理csv

import csv

students = []

with open("students.csv") as file:
    reader = csv.DictReader(file)
    for row in reader:
        students.append({"name": row["name"], "home": row["home"]})

for student in sorted(students, key=lambda student: student["name"]):
    print(f"{student['name']} is in {student['home']}")

注意:

  • csv库读取:csv.DictReader(file)读取有表头的csv(就直接知道每一列是什么意思了),csv.reader(file)读取没有表头的csv #csv库
  • csv读取结果是行(row)

写csv

import csv

name = input("What's your name? ")
home = input("Where's your home? ")

with open("students.csv", "a") as file:
    writer = csv.DictWriter(file, fieldnames=["name", "home"])
    writer.writerow({"name": name, "home": home})

PIL库

import sys

from PIL import Image

images = []

for arg in sys.argv[1:]:
    image = Image.open(arg)
    images.append(image)

images[0].save(
    "costumes.gif", save_all=True, append_images=[images[1]], duration=200, loop=0
)
  • pip install Pillow
  • python costumes.py costume1.gif costume2.gif

作业

lines

import sys
# 获取list长度
def getlen(my_list):
    total=len(my_list)
    for line in my_list:
        # 判断是不是注释或者空行
        if line.strip().startswith("#") or line.lstrip()=="":
            total-=1
    return total
# testlen=["1","2,3,4","","# nihao","222"]
# print(getlen(testlen))

inputlist=[]
try:
    if len(sys.argv)>2:
        raise ValueError
    elif len(sys.argv)==1:
        raise TypeError
    elif sys.argv[1].endswith(".py") ==0:
        raise NameError
    with open(sys.argv[1]) as file:
        for line in file:
            inputlist.append(line.rstrip())
        print(getlen(inputlist))
except ValueError:
    sys.exit("Too many command-line arguments")
except TypeError:
    sys.exit("Too few command-line arguments")
except FileNotFoundError:
    sys.exit("File does not exist")
except NameError:
    sys.exit("Not a Python file")

难点:

  • 封装了一个判断list长度的函数 #判断list长度
    • 判断空格:line.lstrip()=="" lstrip()
    • 判断注释:line.strip().startswith("#")
  • 不同异常退出提示不同

pizza

import sys
import csv
from tabulate import tabulate

menu=[]
try:
    if len(sys.argv)>2:
        raise ValueError
    elif len(sys.argv)==1:
        raise TypeError
    elif sys.argv[1].endswith(".csv") ==0:
        raise NameError
    with open(sys.argv[1]) as file:
        reader = csv.DictReader(file,fieldnames=["pizza1","Small","Large"])
        for row in reader:
            menu.append({"pizza": row["pizza1"], "Small": row["Small"],"Large":row["Large"]})
    print(tabulate(menu,headers="firstrow",tablefmt="grid"))
    # 注意区别:headers="firstrow",那么表头就是csv里的第一行
    # headers="keys",表头是键名("pizza","small","large")
except ValueError:
    sys.exit("Too many command-line arguments")
except TypeError:
    sys.exit("Too few command-line arguments")
except FileNotFoundError:
    sys.exit("File does not exist")
except NameError:
    sys.exit("Not a csv file")

难点:

  • 导入有表头的csv
    • reader = csv.DictReader(file,fieldnames=["pizza1","Small","Large"]) fieldnames相当于给表头起别名
  • tabulate来输出美化后的表格
    • 注意区别:headers="firstrow",那么表头就是csv里的第一行
    • headers="keys",表头是键名("pizza","small","large"

scourgify

# 把一个2列的表拆分为3列的表
import sys
import csv

hp=[]
try:
    if len(sys.argv)>3:
        sys.exit("Too many command-line arguments")
    elif len(sys.argv)<3:
        sys.exit("Too few command-line arguments")
    elif sys.argv[1].endswith(".csv") ==0 or sys.argv[2].endswith(".csv") ==0:
        sys.exit("Not a csv file")
    # 读文件,将文件放入hp字典中
    with open(sys.argv[1]) as file:
        reader = csv.DictReader(file)
        for row in reader:
            last,first=row["name"].strip().split(", ")
            hp.append({"first": first, "last":last,"house": row["house"]})
    # 写文件,把hp文件写入另一csv
    with open(sys.argv[2],"w",newline="") as file:
        writer = csv.DictWriter(file, fieldnames=["first","last","house"])
        writer.writeheader()
        for row in hp:
            writer.writerow({"first":row["first"],"last":row["last"],"house":row["house"]})
        
except FileNotFoundError:
    sys.exit("File does not exist")

难点:

  • 其实可以读写在一起(或者嵌套打开),不必分开,因为之后也没有其他地方要用到读的文件,所以没必要用字典hp[]来中转:
with open(sys.argv[1]) as input, open(sys.argv[2], "w", newline="") as output:
    reader = csv.DictReader(input)
    writer = csv.DictWriter(output, fieldnames=["first", "last", "house"])
    writer.writeheader()
    for row in reader:
        last_name, first_name = row["name"].strip().split(", ")
        writer.writerow(
            {"first": first_name, "last": last_name, "house": row["house"]}
        )
  • 将字典按行写入csv中:
    • with open(sys.argv[2],"w",newline="") as f:,记得"w"授予写入权限,newline="" 可以正常解析换行符,否则会多空行
    • writer.writerow({"first":row["first"],"last":row["last"],"house":row["house"]}) 涉及到嵌套字典怎么取用元素
    • 有表头的csv要先writer=csv.DictWriter(),再writer.writeheader(),再逐行写入

shirt

import os.path
import sys
from PIL import Image,ImageOps

images = []
try:
    if len(sys.argv)>3:
        sys.exit("Too many command-line arguments")
    elif len(sys.argv)<3:
        sys.exit("Too few command-line arguments")
    for im in sys.argv[1:]: 
        if im.endswith(".jpg") ==0 and im.endswith(".png") ==0 and im.endswith(".jpeg") ==0:
            sys.exit("Invalid input")
    # 判断后缀名是否一样
    if os.path.splitext(sys.argv[1])[1] != os.path.splitext(sys.argv[2])[1]:
        sys.exit("Input and output have different extensions")
    shirt=Image.open("shirt.png")

    im= Image.open(sys.argv[1]) 
    # 将before.jpg缩减成shirt的大小
    im = ImageOps.fit(im, shirt.size)
    # 把shirt粘贴在before.jpg上,im.paste(shirt, mask=shirt)?神奇的用法,可以去掉shirt以外的东西
    im.paste(shirt, shirt)
    im.save(sys.argv[2])

except FileNotFoundError:
    sys.exit("File does not exist")

难点:

  • 判断后缀名是否一致:splitext()函数
    • 导入库:os.path
    • 取后面部分
  • 图片粘贴:
    • 导入图片相关函数:from PIL import Image,ImageOps
    • paste():把shirt粘贴在before.jpg上,im.paste(shirt, mask=shirt)?神奇的用法,可以去掉shirt以外的东西
  • 13
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值