资讯动态

Python作业实战:构建邻接矩阵与查询函数的完整指南

发布时间:2026/10/6 10:19:19 来源:尧图企业网站定制
第一次交 Python 作业的时候大家基本都还在print(hello world)、变量赋值的阶段打转到了第二次作业难度直接跳了一级开始要求你“用代码解决一个完整的小问题”。我带学员时发现绝大多数人在第二次作业卡住不是某个语法不会写而是根本没弄明白“这份作业到底想让我做什么”。这篇文章就拿一份非常典型的第二次作业来拆——构建邻接矩阵并实现查询函数。只要你的作业里出现了“邻接矩阵、自定义函数、DataFrame、类型转换、环境配置”这些关键词下面这套思路都能直接用。我不是在给标准答案而是想还原一个完整过程拿到题目后先怎么分析环境怎么准备核心代码怎么设计实测会遇到哪些坑最后怎么自检提交。你能照着做也能从里面挑出自己缺的那一块。1. 先搞清楚这次作业到底在考什么第二次作业和第一次最明显的差别是题目不再是“练习某个语法”而是“用几个语法组合起来解决一个实际问题”。比如这次要做的邻接矩阵表面上是图论的东西但落到 Python 里真正考的是这几件事能不能正确定义变量、看清楚数据类型会不会在字符串、整数、列表之间做类型转换能不能把一个逻辑完整地封装进函数而不是从头到尾写流水账能不能用二维列表或矩阵组织数据并结构化地输出出来。所以别被“邻接矩阵”四个字吓到。它只是一个容器目的是把你前面学过的零散知识点串起来。理解了这一点再看作业要求思路会清晰很多。1.1 作业要求里最容易被忽略的一句话作业题目里常常有一句特别不起眼的话“请使用自定义函数实现并返回二维列表。”大多数同学扫一眼题目就开始写循环最后矩阵倒是打印出来了但老师要求的那几个函数一个都没写分数直接扣掉一半。拿这份典型的第二次作业当例子通常的要求是给定一个无向图的顶点数n和边列表edges构建对应的邻接矩阵矩阵元素用 0 和 1 表示实现一个函数输入两个顶点编号返回它们之间是否存在边。这里的关键不是“写出来”而是“按要求写出来”。所以拿到题目的第一件事不是开电脑敲代码而是把题目里的要求动词全部圈出来挨个确认。我再强调一遍就这三件事圈出“自定义函数”“返回值”“不得修改原始数据”这类表述它们决定你的代码结构。确认顶点编号是从 0 开始还是从 1 开始这直接决定矩阵是多大的也决定赋值时要不要做减一处理。确认输出形式是打印矩阵、返回 DataFrame还是保存成文件。这几件事里第一件决定你拿不拿得到完成分第二件决定你拿不拿得到正确分第三件影响老师的批改体验。很多人第二次作业丢分不是代码能力问题是读题习惯问题。1.2 从初学者的搜索习惯里能看出什么我平时会留意初学者都在搜索引擎里敲什么词。出现频率最高的通常是“python安装”“python环境变量配置”“python定义函数”“python构建邻接矩阵”“python dataframe”“python类型转换”。把这些词组合在一起基本就是第二次作业的完整坐标系了。安装和环境变量是第一道坎是“能不能跑起来”的问题定义函数和类型转换是第二道坎是“能不能按题目要求组织代码”的问题构建邻接矩阵、操作 DataFrame 是第三道坎是“能不能把算法思想用代码落地”的问题。如果你也是这第二批做作业的人说明你不是个例大家都在这几个点上挣扎。接下来的内容我就按这三道坎的顺序来写中途穿插实际操作中的真实排错记录。2. 动笔之前先把 Python 环境收拾利索我知道很多人急着写代码觉得环境配置浪费时间。但实际上第二次作业没做完的人里有一半是环境问题没解决而不是题目做不出来。什么“ModuleNotFoundError”“python 不是内部或外部命令”全是环境配置的问题。先把环境弄顺后面会省很多事。2.1 装哪个版本、去哪下载第二次作业一般只会用到标准库加一两个第三方库比如numpy、pandas。给你两个主流选择想省心直接装Anaconda它自带numpy、pandas、scikit-learn这些常用库装了就不用再一个个折腾。想轻量去 Python 官网下官方安装包选Python 3.10 或 3.11就行不要追预览版和最新 RC 版第三方库的兼容性经常会慢半拍。有些同学会问“老师上课用的是 3.8我装 3.11 可以吗”只要老师没特别说明3.8 以上的版本都没问题。反而有些同学装了 3.13 的开发版回头装pandas找不到对应 wheel 包白白折腾一下午。选稳定版本是第一次做作业时最聪明的决定。2.2 PATH 环境变量配置很多人卡在第一步在 Windows 上安装 Python 的时候第一个界面就有一项“Add Python to PATH”默认是不勾选的如果你不勾后面在 cmd 里敲python就会提示“python 不是内部或外部命令”。这个东西打个比方你在 cmd 里输入python系统就要去一个“名单”里找python.exe的位置。这个名单就是 PATH。如果名单里没有这条记录系统当然找不到。解决办法有两种安装时直接勾选“Add Python to PATH”安装完手动加进入“系统属性” - “环境变量” - 在“系统变量”的 Path 里新增 Python 安装目录和它的 Scripts 子目录。装完之后打开 cmd 输入python --version能正常输出版本号就算成功。这个动作用不了三十秒但能救你无数次。2.3 为作业预装可能会用到的库如果你的老师明确说了这次作业可以用numpy或pandas那就提前把它们装好。在 cmd 里执行pip install numpy pandas如果你用的是 Anaconda也可以换成conda install numpy pandas这里提醒一个我在很多讨论区里看到的现象有些同学从网上复制安装命令比如“pip install -u --pre comfyui-m”这种看着像是来解决报错的方法实际上是把某个开源项目的安装命令当成通用命令在使用。看到这种带-u、--pre参数的命令要警惕它不是解决你作业问题的通用手段盲目复制容易装错包甚至把环境搞乱。装库就老老实实用pip install 库名这种直白写法。还有一个实用小技巧如果你在国内网络环境下安装第三方库特别慢可以在命令后面加一个国内镜像源pip install numpy pandas -i https://pypi.tuna.tsinghua.edu.cn/simple速度快得不止一点。3. 第二次作业的核心内容拆解环境折腾完终于可以进入正题了。这一节我按照作业常见的小题顺序来拆每种题型都给出核心思路和可直接改的示例代码。3.1 变量与类型转换所有后续操作的地基很多作业会在主任务前面放一两道“送分题”让你定义几个变量、输出它们的类型或者把字符串转成整数。看似简单但它其实是给后面铺垫的。比如你就可能从input()读进来的是字符串要参与矩阵运算之前必须转成int。n input(请输入顶点数) # n 此时是字符串不能直接用来建矩阵 n int(n)类型转换的常见场景就这几个int(123)字符串转整数float(3.14)字符串转浮点数str(123)数字转字符串list((1, 2, 3))元组转列表。想检查类型就用type()函数。作业里如果有一问是“写出下面变量的类型”你可以在代码里直接打印验证而不用靠猜。这个习惯很基础但我在实际批改过程中见过太多人栽在“n 是字符串”这个坑上导致后面range(n)直接报错。3.2 定义函数第二次作业的隐藏考点第二次作业开始你就得正式写函数了。别嫌麻烦老师让你写函数不是形式主义而是因为后面更复杂的任务都需要“逻辑封装”。先看一个合格的定义长什么样def check_edge(matrix, u, v): return matrix[u][v] 1第一行的def声明函数名后面括号里是参数函数体最后用return把结果交出去。写函数的关键是两个原则一个函数只负责一件事。build_adjacency_matrix就只负责建矩阵check_edge就只负责查边。不要一个函数既要读文件又要算结果又要打印拆开写以后调试会轻松很多。尽量用return返回结果而不是在函数里面直接print。因为后面的自检和测试要拿返回值来判断对错print出来的东西没法被程序继续使用。如果你怕自己的函数结构不对就先写一个“骨架函数”把参数和 return 先写好再往里面填充逻辑。第二次作业的重点不是炫技而是结构清楚。3.3 构建邻接矩阵三种写法从笨到巧邻接矩阵的定义其实很简单有n个顶点就建一个n行n列的矩阵。如果顶点i和顶点j之间有边就把第i行第j列记为 1否则记为 0。如果是无向图矩阵是对称的matrix[i][j] matrix[j][i]。第一种写法也是最容易出错的写法是直接用乘法生成二维列表matrix [[0] * n] * n这个写法乍一看没问题但你一赋值就会发现改一个位置整列都跟着变。原因是[[0] * n] * n里面的 n 个子列表其实都是同一个对象你改的是“同一块内存”自然全部一起变。这是典型的坑我后面还会再提。第二种写法是用列表推导式这也是我推荐的matrix [[0] * n for _ in range(n)]for _ in range(n)每次都重新生成一个新的内部列表所以互不影响。这种生成方式既简洁又完全避免了上面的坑。第三种写法是进阶版如果你已经安装了numpy可以直接这样写import numpy as np matrix np.zeros((n, n), dtypeint)np.zeros生成一个全是 0 的二维数组后面赋值照样是matrix[u][v] 1。用 numpy 的好处是数据类型统一、内存连续后续如果要做更复杂的矩阵运算直接就能上。完整的一个构建函数大概是这个样子def build_adjacency_matrix(n, edges): matrix [[0] * n for _ in range(n)] for u, v in edges: # 做一次越界检查防止编号从 1 开始导致索引错位 if 0 u n and 0 v n: matrix[u][v] 1 matrix[v][u] 1 # 无向图需要双向置 1 return matrix那个越界检查不是多此一举。如果题目给的顶点编号是从 1 到 n而你建的矩阵是从 0 到 n-1那不加检查就必然报IndexError。加上检查之后即使你忘了对编号做减一处理程序也不会直接崩只是会跳过无效位置你反而更容易发现问题。3.4 用 DataFrame 让输出更结构化有些老师要求在作业里把矩阵用结构化数据展示出来这时候就轮到pandas登场了。import pandas as pd def matrix_to_dataframe(matrix): df pd.DataFrame(matrix) return df如果你想让行列都有标签可以加上行列索引df pd.DataFrame(matrix, columnsrange(n), indexrange(n))DataFrame 相比普通二维列表的最大优势是“可读性”。矩阵以表格形式展示出来行和列都有明确编号老师看起来一目了然你自己检查的时候也更方便。这也解释了为什么第二次作业里会出现 DataFrame 的知识点它不只是让你换个容器存数据而是开始培养“结构化数据”的意识。4. 实操过程与核心环节实现光讲理论没意思。这一节我完整模拟一遍从 0 到提交的过程代码可以直接复制修改。4.1 一份可以直接跑通的完整代码骨架先把整个文件结构放上来命名为homework2.pyfrom typing import List, Tuple def build_adjacency_matrix(n: int, edges: List[Tuple[int, int]]) - List[List[int]]: 根据顶点数和边列表构建邻接矩阵 matrix [[0] * n for _ in range(n)] for u, v in edges: if 0 u n and 0 v n: matrix[u][v] 1 matrix[v][u] 1 return matrix def check_edge(matrix, u: int, v: int) - bool: 判断两个顶点之间是否存在边 return matrix[u][v] 1 def print_matrix(matrix): 格式化输出矩阵 for row in matrix: print( .join(str(x) for x in row)) if __name__ __main__: n 5 edges [(0, 1), (1, 2), (2, 3), (3, 0), (0, 4)] adj_matrix build_adjacency_matrix(n, edges) print(邻接矩阵) print_matrix(adj_matrix) print(顶点 1 和 2 之间有边吗, check_edge(adj_matrix, 1, 2)) print(顶点 0 和 3 之间有边吗, check_edge(adj_matrix, 0, 3))这里有三个细节值得说。第一是if __name__ __main__:。这个写法保证文件被直接运行时才执行下面的测试代码如果以后别人把你的函数 import 到别的程序里不会一进来就把测试结果打出来。第二次作业养成这个习惯后面越写越受益。第二是函数的类型注解比如edges: List[Tuple[int, int]]。这是给阅读代码的人看的标明参数类型。老师见到这种写法至少知道你有基本的代码规范意识。第三是print_matrix里用的join它比一行一行遍历打印更紧凑输出的矩阵形状也更好看。4.2 从文件读取边列表有些作业不会在代码里直接给边数据而是给你一个edges.txt或者 CSV 文件要求你自己读入。这种情况别怕也就几步的事def read_edges_from_file(file_path): edges [] with open(file_path, r, encodingutf-8) as f: for line in f: line line.strip() if not line: continue parts line.split() u, v int(parts[0]), int(parts[1]) edges.append((u, v)) return edgeswith open(...) as f负责打开文件并且在用完后自动关闭这是最稳妥的文件读取方式。strip()去掉行首行尾的空白split()按空格把一行拆成两个字符串最后用int()转成整数。流程就是“读、切、转、存”四步。如果你读的是 CSV 文件可以把分割方式改成line.split(,)或者直接用现成工具比如pandas.read_csv。但第二次作业阶段我更建议先用标准库写一遍因为这样你对数据解析的整个过程是有感知的后面用 pandas 才知道它替你省了哪些事。4.3 提交前的自检矩阵对不对一眼就能看出来写完不等于做完。我每次提交作业前都会先跑三个自检这比在纸上检查效率高得多。第一个是检查对称性。无向图的邻接矩阵必须是对称矩阵如果打印出来发现matrix[0][2]是 1但matrix[2][0]是 0那一定是在赋值的时候漏了matrix[v][u] 1这行。def is_symmetric(matrix): n len(matrix) for i in range(n): for j in range(n): if matrix[i][j] ! matrix[j][i]: return False return True第二个是检查对角线。正常情况下无自环的无向图对角线全是 0。如果你发现某个对角线上出现了 1要么是题目允许自环要么是你的边列表里混入了(u, u)这种数据。第三个是核对边数。无向图中每条边会在矩阵里产生两个对称的 1所以矩阵里 1 的总数除以 2应该等于边列表的长度。如果对不上说明肯定有漏边或者多填的。这三个检查都可以直接写进代码里但我更建议你在提交前手动跑一遍把它们当作最后的确认动作。程序能跑通是一回事跑对是另一回事。5. 常见问题与排查技巧实录这一节是我最想写的一部分。第二批做作业的同学遇到的问题高度集中把这些问题整理成一张速查表你完全可以把它挂在旁边遇到报错先自己对着表查一遍。现象最常见原因解决办法SyntaxError: invalid character中英文标点混用比如用了中文括号删除报错位置切换英文输入法重新输入IndexError: list index out of range顶点编号从 1 开始但矩阵索引从 0 开始建矩阵时多建一行/一列或对输入编号执行减一NameError: name np is not defined写代码用了 numpy但没导入在代码顶部检查是否重复出现两次import numpy as npModuleNotFoundError: No module named pandaspandas 没安装或安装到了另一个 Python 环境在 cmd 中运行pip install pandas确认 pip 和 python 属于同一环境修改矩阵一个位置整列都变用了[[0] * n] * n导致内部列表共享改成[[0] * n for _ in range(n)]ValueError: too many values to unpack边列表某个元素不是只有两个数打印 edges 检查可能是空行或多余逗号终端打印中文乱码编码问题文件保存时选择 UTF-8必要时在代码里加# -*- coding: utf-8 -*-cmd 里输入 python 没反应PATH 没有配置好重新安装时勾选 Add Python to PATH手动配置 PATH 后重启 cmd再看几个不是报错但更坑的现象。矩阵能打印出来但老师说你“没按要求实现”。这种情况十有八九是你没写函数或者函数没返回值。第二次作业的老师普遍盯着“函数封装”看你写一个几十行的脚本全部摊在main里就算结果对也拿不到函数分类的分。还有一种现象是代码在本机能跑但换了电脑就报错。多数原因是你的环境变量是针对本机配置的或者你用的库是全局环境里有但提交到线上平台后没有。这也解释了为什么用anaconda或者创建虚拟环境是一种好习惯——它的依赖是独立打包的不会出现“在我电脑上能跑”的尴尬。排查问题的顺序我总结成一句话“先看报错行再看变量内容最后看数据结构。”第二步很多人会跳过但这一步特别关键。比如IndexError如果你在赋值前先把u, v打印出来一眼就能看出是编号问题还是数据格式问题。6. 踩过几次坑之后我的一点体会第二次作业最典型的翻车点说到底还是“顶点编号从 0 开始还是从 1 开始”。我自己当年做这份作业时就是没看题目默认编号从 0 开始结果矩阵建出来比预期小了一圈一跑查询函数就报 IndexError。当时我以为是自己代码写错了调了快一个小时最后打印 edges 才发现是编号问题。这段经历给我的教训是遇到错误先怀疑输入数据再怀疑自己的代码逻辑。尤其是第二次作业这种带外部输入数据的题目十个报错里有八个是数据格式或编号规则的问题而不是语法问题。另外一个建议是提交前一定把函数注释写好。不是说多少行的问题而是你以后翻自己代码时能一眼看懂这个函数干什么。比如说“根据顶点数和边列表构建邻接矩阵”这么一句话下次复用这个函数就不用重新读一遍代码逻辑了。第二次作业是很多人的第一个“门槛”跨过去之后定义函数、二维数据、结构化输出这些技能就都长在你手上了。后面再做数据处理、或者学更复杂的图算法都是在这个基础上加东西。所以不用慌照着上面这些步骤把环境配好、把函数写好、把自检跑完你基本已经能把这次作业做得像模像样了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑