Skip to content

基础项目练习

学完前面的变量、条件、循环、函数、列表、字典、文件以后,只停留在“看懂例子”是不够的。真正能不能把知识点用起来,要看你能不能独立完成一个小项目。

这一节不给你讲新语法,而是带你把前面学过的东西串起来,做一个真正能运行的小工具。你做完这个项目以后,应该能明显感受到:原来代码不是一行一行孤立存在的,而是可以组合成一个完整功能。

本节目标

  • 学会把多个基础知识点组合成一个完整程序
  • 学会先拆需求,再写代码
  • 学会用函数组织程序结构
  • 学会把结果保存到文件
  • 学会排查运行中的常见错误

先修知识

在开始之前,你至少应该已经掌握这些内容:

  • 变量、输入与输出
  • if 条件语句
  • forwhile 循环
  • 列表和字典
  • 函数
  • 文件读写

如果上面这些你还不熟,建议先回去把前面的章节复习一遍,再来看这一节。因为项目练习不是新的知识点堆积,而是旧知识点的综合应用。

为什么零基础一定要做项目

很多初学者有一个典型问题:单独一页一页看文档时,好像都懂;真到自己写代码时,脑子却是空的。

这不是因为你不聪明,而是因为你还没有建立“程序结构感”。

所谓结构感,就是你看到一个需求时,能立刻想到:

  1. 先准备什么数据
  2. 要做哪些判断
  3. 哪些操作要重复执行
  4. 哪些逻辑适合写成函数
  5. 最终结果要输出到屏幕,还是写入文件

项目练习的意义,就在于帮助你从“会看代码”走向“会自己组织代码”。

练习项目:图片链接整理器

我们先做一个适合零基础的项目:图片链接整理器。

这个项目的目标很简单:

  1. 准备一批图片链接
  2. 去掉空字符串和重复链接
  3. 给每个链接编号
  4. 判断链接是否是常见图片格式
  5. 把整理结果输出到屏幕
  6. 再保存到本地文本文件

你会发现,这个项目虽然小,但已经把很多基础知识点都串起来了。

第一步:先把需求翻译成代码任务

遇到需求时,不要立刻开始写代码。先把需求拆开。

这次的需求可以拆成下面几步:

  • 用列表保存一批原始链接
  • 遍历列表
  • 跳过空值
  • 判断是否重复
  • 判断扩展名是否像图片
  • 生成整理后的结果
  • 打印输出
  • 写入文件

只要你会拆,代码就不会乱。

第二步:准备原始数据

先写一批模拟数据。真实项目里这些数据可能来自网页、数据库、接口或者用户输入,但在练习阶段,我们先把它写死在代码里。

python
raw_urls = [
    "https://img.example.com/a.jpg",
    "https://img.example.com/b.png",
    "",
    "https://img.example.com/a.jpg",
    "https://img.example.com/c.gif",
    "https://img.example.com/readme.txt",
    "https://img.example.com/d.jpeg"
]

print(raw_urls)

输出结果:

text
['https://img.example.com/a.jpg', 'https://img.example.com/b.png', '', 'https://img.example.com/a.jpg', 'https://img.example.com/c.gif', 'https://img.example.com/readme.txt', 'https://img.example.com/d.jpeg']

这里我们故意放了几种情况:

  • 正常图片链接
  • 空字符串
  • 重复链接
  • 非图片文件链接

这样后面写逻辑时,效果会更明显。

第三步:先写一个判断函数

当你发现某个判断逻辑可能会重复使用时,就应该考虑写成函数。

例如这里我们要判断一个链接是否是图片链接,可以写成这样:

python
def is_image_url(url):
    image_suffixes = [".jpg", ".jpeg", ".png", ".gif", ".webp"]
    for suffix in image_suffixes:
        if url.endswith(suffix):
            return True
    return False


print(is_image_url("https://img.example.com/a.jpg"))
print(is_image_url("https://img.example.com/readme.txt"))

输出结果:

text
True
False

这里的核心点有两个:

  • endswith() 用来判断字符串是否以某个内容结尾
  • 只要匹配到一种图片后缀,就立刻 return True

如果循环结束都没有匹配成功,最后再 return False

第四步:去空、去重、过滤非图片链接

现在开始处理主逻辑。

python
raw_urls = [
    "https://img.example.com/a.jpg",
    "https://img.example.com/b.png",
    "",
    "https://img.example.com/a.jpg",
    "https://img.example.com/c.gif",
    "https://img.example.com/readme.txt",
    "https://img.example.com/d.jpeg"
]


def is_image_url(url):
    image_suffixes = [".jpg", ".jpeg", ".png", ".gif", ".webp"]
    for suffix in image_suffixes:
        if url.endswith(suffix):
            return True
    return False


clean_urls = []

for url in raw_urls:
    if url == "":
        continue

    if url in clean_urls:
        continue

    if not is_image_url(url):
        continue

    clean_urls.append(url)

print(clean_urls)

输出结果:

text
['https://img.example.com/a.jpg', 'https://img.example.com/b.png', 'https://img.example.com/c.gif', 'https://img.example.com/d.jpeg']

这段代码非常适合初学者反复看,因为它把基础语法都用到了:

  • for 负责遍历
  • if 负责判断
  • continue 负责跳过不需要的数据
  • in 负责判断是否重复
  • append() 负责加入新元素

第五步:给结果编号

光有链接还不够,通常我们还希望给每条数据加一个序号,后面更容易查看。

python
clean_urls = [
    "https://img.example.com/a.jpg",
    "https://img.example.com/b.png",
    "https://img.example.com/c.gif"
]

for index, url in enumerate(clean_urls, start=1):
    print(f"{index}. {url}")

输出结果:

text
1. https://img.example.com/a.jpg
2. https://img.example.com/b.png
3. https://img.example.com/c.gif

enumerate() 是一个非常常用的工具,它可以在遍历列表时同时拿到:

  • 元素下标
  • 元素本身

这里的 start=1 表示编号从 1 开始,而不是默认的 0。

第六步:整理成更完整的结果结构

如果以后你还想保存更多信息,比如文件类型、是否有效、来源页面,那么最好不要只保存一个字符串,而是保存字典。

python
clean_urls = [
    "https://img.example.com/a.jpg",
    "https://img.example.com/b.png",
    "https://img.example.com/c.gif"
]

records = []

for index, url in enumerate(clean_urls, start=1):
    record = {
        "id": index,
        "url": url,
        "suffix": url.split(".")[-1]
    }
    records.append(record)

print(records)

输出结果:

text
[{'id': 1, 'url': 'https://img.example.com/a.jpg', 'suffix': 'jpg'}, {'id': 2, 'url': 'https://img.example.com/b.png', 'suffix': 'png'}, {'id': 3, 'url': 'https://img.example.com/c.gif', 'suffix': 'gif'}]

这样做的好处是,数据更有结构。后面你要打印、统计、写文件,都会方便很多。

第七步:把结果输出成更友好的格式

很多初学者写程序时,只知道 print(list)。这当然能看,但不适合实际查看。

我们可以把输出做得更清晰一点:

python
records = [
    {"id": 1, "url": "https://img.example.com/a.jpg", "suffix": "jpg"},
    {"id": 2, "url": "https://img.example.com/b.png", "suffix": "png"},
    {"id": 3, "url": "https://img.example.com/c.gif", "suffix": "gif"}
]

for item in records:
    print(f"编号:{item['id']}")
    print(f"链接:{item['url']}")
    print(f"格式:{item['suffix']}")
    print("-" * 30)

输出结果:

text
编号:1
链接:https://img.example.com/a.jpg
格式:jpg
------------------------------
编号:2
链接:https://img.example.com/b.png
格式:png
------------------------------
编号:3
链接:https://img.example.com/c.gif
格式:gif
------------------------------

第八步:保存到本地文件

做工具类项目时,最终结果通常要落地保存。

python
records = [
    {"id": 1, "url": "https://img.example.com/a.jpg", "suffix": "jpg"},
    {"id": 2, "url": "https://img.example.com/b.png", "suffix": "png"},
    {"id": 3, "url": "https://img.example.com/c.gif", "suffix": "gif"}
]

with open("image_urls.txt", "w", encoding="utf-8") as file:
    for item in records:
        line = f"{item['id']}\t{item['suffix']}\t{item['url']}\n"
        file.write(line)

print("文件写入完成")

输出结果:

text
文件写入完成

文件内容示例:

text
1	jpg	https://img.example.com/a.jpg
2	png	https://img.example.com/b.png
3	gif	https://img.example.com/c.gif

这里你可以注意两个点:

  • \t 表示制表符,可以让列之间看起来更整齐
  • \n 表示换行符,让每条记录独占一行

第九步:写成一个完整程序

前面我们是一小段一小段练习。现在把它们真正拼起来。

python
def is_image_url(url):
    image_suffixes = [".jpg", ".jpeg", ".png", ".gif", ".webp"]
    for suffix in image_suffixes:
        if url.endswith(suffix):
            return True
    return False


def clean_image_urls(raw_urls):
    clean_urls = []

    for url in raw_urls:
        if url == "":
            continue

        if url in clean_urls:
            continue

        if not is_image_url(url):
            continue

        clean_urls.append(url)

    return clean_urls


def build_records(clean_urls):
    records = []

    for index, url in enumerate(clean_urls, start=1):
        record = {
            "id": index,
            "url": url,
            "suffix": url.split(".")[-1]
        }
        records.append(record)

    return records


def show_records(records):
    print("整理结果如下:")
    for item in records:
        print(f"编号:{item['id']}")
        print(f"链接:{item['url']}")
        print(f"格式:{item['suffix']}")
        print("-" * 30)


def save_records(records, filename):
    with open(filename, "w", encoding="utf-8") as file:
        for item in records:
            line = f"{item['id']}\t{item['suffix']}\t{item['url']}\n"
            file.write(line)


raw_urls = [
    "https://img.example.com/a.jpg",
    "https://img.example.com/b.png",
    "",
    "https://img.example.com/a.jpg",
    "https://img.example.com/c.gif",
    "https://img.example.com/readme.txt",
    "https://img.example.com/d.jpeg"
]

clean_urls = clean_image_urls(raw_urls)
records = build_records(clean_urls)
show_records(records)
save_records(records, "image_urls.txt")

print("项目执行完成")

输出结果:

text
整理结果如下:
编号:1
链接:https://img.example.com/a.jpg
格式:jpg
------------------------------
编号:2
链接:https://img.example.com/b.png
格式:png
------------------------------
编号:3
链接:https://img.example.com/c.gif
格式:gif
------------------------------
编号:4
链接:https://img.example.com/d.jpeg
格式:jpeg
------------------------------
项目执行完成

这就是一个完整的小项目了。它虽然不大,但已经具备“需求拆解 -> 编写函数 -> 处理数据 -> 输出结果 -> 保存文件”的完整流程。

这个项目用到了哪些知识点

你可以回头对照一下,看看前面的知识是怎么串起来的:

  • 变量:保存链接、文件名、中间结果
  • 列表:保存多条链接
  • 字典:保存结构化数据
  • 条件语句:判断空值、重复值、文件类型
  • 循环:遍历原始数据和整理结果
  • 函数:拆分不同功能
  • 字符串方法:判断后缀、格式化输出
  • 文件操作:保存最终结果

这就是项目练习最重要的意义:把“散着学”的知识点连起来。

常见错误

1. 把 = 写成 ==

下面这种写法是错误的:

python
if url = "":
    print("空字符串")

这里应该用 == 比较,而不是 = 赋值。

2. 没有给文件指定编码

如果你写文件时没有加 encoding="utf-8",某些系统环境下可能会出现乱码。

3. 忘记处理重复数据

如果你直接遍历原始列表然后写入文件,最后保存出来的内容可能会重复很多次。

4. 只会把代码全部堆在一起

很多初学者会把所有逻辑写在一个大 for 循环里。程序虽然也许能跑,但后面很难改、很难排错。你要慢慢养成用函数拆逻辑的习惯。

练习题

练习 1

把程序改成只保留 .jpg.png 两种图片格式。

练习 2

在结果中新增一个字段 length,表示链接字符串的长度。

练习 3

统计一共有多少个 jpg、多少个 png、多少个 gif

练习 4

让用户自己输入文件名,例如:

python
filename = input("请输入保存文件名:")

然后把结果保存到用户指定的文件里。

练习 5

把这个工具改成“用户名整理器”“邮箱整理器”或者“网页标题整理器”,自己重新设计一套数据结构。

本节小结

这一节你没有学到新语法,但你学会了比“新语法”更重要的东西:怎样把基础语法组织成一个完整程序。

如果你能独立写完这个项目,并且完成上面的练习题,那说明你已经不只是“会看 Python”,而是开始进入“会用 Python”的阶段了。

接下来你再学函数、文件、数据库、爬虫时,就会更容易理解这些知识点为什么存在,以及它们在真实项目里到底怎么配合工作。

Built with VitePress.