Python 零基础入门教程
写给第一次接触编程的你。本教程假设你完全没有写过代码,也从零开始,一步一步来。
我们会在第 2 章帮你把电脑上的 Python 环境搭好,之后每一章都有可以直接复制运行的小例子,以及「动手试试」的小练习。阅读建议:不要跳着看,也不要只"看"不"打"。编程和做实验一样,看一百遍不如亲手敲一遍。每看到一个代码块,就照着敲到电脑里运行一下。
目录
- Python 是什么,能做什么,为什么你该学
- 安装与环境搭建
- 第一个程序
- 变量与基本数据类型
- 运算符
- 输入输出
- 控制流:if / elif / else
- 循环:for 与 while
- 字符串进阶
- 列表 list
- 元组、字典、集合
- 函数
- 模块与导入
- 文件读写
- 错误与异常
- 面向对象入门(可选)
- 综合小项目:处理一组实验数据
- 新手常见坑清单
- 下一步学什么 + 推荐资源
1. Python 是什么,能做什么,为什么你该学
1.1 它是什么?
Python 是一种"编程语言"。 编程语言,就是人类用来给电脑下指令的一套规则。就像你跟外国人说话要用英语,你要让电脑干活,就得用它能听懂的语言。Python 就是其中一种,而且以"好读、好写、好学"著称。
你写一段文字(叫代码,code),让电脑按顺序执行,电脑就会帮你做事情:算数、整理数据、批量改文件、画图、抓取网页……凡是重复、量大、需要精确的事情,都可以交给它。
1.2 它长什么样?
下面是一小段 Python 代码,就算你现在看不懂也没关系,先感受一下"原来长这样":
# 这是一行注释,电脑会忽略它,是写给人看的
elements = ["H", "O", "C", "N"] # 把几个元素符号装进一个"列表"
for e in elements: # 逐个拿出每个元素
print("这个元素是:" + e) # 打印出来
运行后,电脑会一行一行地打印出每个元素符号。
1.3 它能做什么
- 算数:把一堆实验数据加起来、求平均、找最大最小值。
- 处理文本:批量重命名文件、从几万行日志里找关键词。
- 处理数据:整理表格、清洗数据、画统计图。
- 自动化:定时下载文献、批量格式转换、自动发提醒。
- 科学计算:配合 NumPy、SciPy、Matplotlib 等工具做计算和绘图(本教程系列里有专门讲这些的)。
- 做网站、做游戏、做人工智能:Python 也是这些领域的主流语言之一。
1.4 为什么化学 / 科研的人需要学
做科研,尤其是计算化学相关领域,每天都会遇到这些场景:
- 一个数据文件里有几百上千个数值,要算平均值、标准差、找异常点——用 Excel 也能做,但 Python 可以一键、可重复、可留痕地完成,下次换一批数据直接再跑一遍。
- 要批量处理几十上百个分子文件、提取能量值、改输入文件——手动一个个点,既慢又容易错。
- 要用 VASP、ASE、RDKit、pymatgen 这些科研工具——它们几乎都用 Python 作为"操作语言"。学会 Python,你才能真正驾驭这些工具。
简单说:Python 是你科研路上的"计算器 + 秘书 + 助手",而且它免费、跨平台、资料最多。
1.5 你不需要什么
- 你不需要数学特别好,会加减乘除就行。
- 你不需要英语特别好,虽然代码里会出现英文单词,但就那么几十个常用的,见多了就熟了。
- 你不需要会装逼的电脑技能,会打开文件夹、会打字就行。
好,下面我们动手,把环境装好。
2. 安装与环境搭建
这一章以我的实际运行环境为例:Windows + Miniconda + Python 3.14 + VS Code。
先解释几个名词(都用人话):
- Miniconda:一个"装 Python 和管理环境"的工具。它最厉害的地方是能给你创建独立的虚拟环境,让不同项目的 Python 互不干扰。
- 虚拟环境(conda 环境):你可以理解成"一间独立的房间"。每个房间里装一套 Python 和一套工具,房间之间互不影响。这样你搞科研装 A 库,学基础装 B 库,不会打架。
- VS Code:一个写代码用的"编辑器"(就像写文档用 Word,写代码用 VS Code),免费、好用、有中文界面。
- 交互式 Python(REPL):一种"输入一句、立刻回一句"的对话式用法,后面会讲。
2.1 第一步:安装 Miniconda
- 打开浏览器,搜索 Miniconda,或直接访问官网下载页
https://docs.conda.io/en/latest/miniconda.html。 - 选择 Windows 版本(通常是一个
.exe安装包,选 64-bit)。 - 双击运行安装包,一路点"下一步"(Next)即可。注意一个选项:"Add Miniconda3 to my PATH environment variable"(加入环境变量)默认可能不勾选,建议勾选,这样后面在任何终端都能用
conda命令。如果装的时候没勾也没关系,可以用它自带的 "Anaconda Prompt" 来操作。 - 装完后,在 Windows 开始菜单搜索 "Anaconda Prompt"(或 "Miniconda Prompt")并打开——这是一个黑色窗口(叫终端 / 命令行),我们后面要在这里输入命令。
2.2 第二步:确认安装成功
在终端里输入下面这行,然后回车(输入命令后都按回车执行):
conda --version
如果显示类似 conda 24.x.x 这样的版本号,说明装好了。
2.3 第三步:创建一个虚拟环境(装 Python 3.14)
在终端里输入下面这条命令,创建一个名叫 py314 的环境,并指定 Python 版本为 3.14:
conda create -n py314 python=3.14 -y
解释一下:
conda create:让 conda 创建东西。-n py314:给新环境起名叫py314(名字随便取,好记就行)。python=3.14:指定这个环境里装 Python 3.14。-y:意思是"中途如果问你是否继续,自动回答 yes",省得手动确认。
它会联网下载并安装,等它跑完(可能几分钟)。
2.4 第四步:激活(进入)这个环境
conda activate py314
激活成功后,你会看到命令行的最前面出现了 (py314),像这样:
(py314) C:\Users\你的用户名>
这表示你现在已经"进入"了 py314 这个房间。以后每次写代码前,都要先执行 conda activate py314 进入环境。
验证一下 Python 版本:
python --version
应该显示 Python 3.14.x。恭喜,Python 装好了。
退出环境用
conda deactivate。查看你有哪些环境用conda env list。
2.5 第五步:安装 VS Code
- 搜索 VS Code,到官网
https://code.visualstudio.com/下载 Windows 版,双击安装(一路默认即可)。 - 装好后打开 VS Code。
2.6 第六步:给 VS Code 装上 Python 扩展
- 在 VS Code 左侧竖排图标栏,点最下面的扩展图标(四个小方块拼成的图标)。
- 在搜索框输入 Python,找到微软官方的 "Python" 扩展(作者是 Microsoft),点 Install(安装)。
- 装好后,VS Code 就能识别 Python 代码、自动补全、一键运行了。
2.7 第七步:让 VS Code 使用你的 py314 环境
- 在 VS Code 里按快捷键
Ctrl + Shift + P,会弹出命令面板。 - 输入并选择 Python: Select Interpreter(选择解释器)。
- 在列表里找到
py314(或者路径里带py314的那个),点它选中。
"解释器"(interpreter)就是"真正执行 Python 代码的程序"。选了 py314,VS Code 就会用你环境里的 Python 3.14 来运行代码。
2.8 第八步:运行你的第一个 .py 文件
- 在 VS Code 里按
Ctrl + N新建文件,按Ctrl + S保存,文件名写hello.py(后缀.py表示这是 Python 文件,很重要),保存到一个你找得到的文件夹,比如D:\code。 - 在文件里输入:
print("你好,Python!")
- 保存后,点右上角的三角形运行按钮(▶),或者按
Ctrl + F5。 - 看下方会弹出"终端"面板,里面显示运行结果:
你好,Python!
如果能看到这行字,说明你的环境完全搭好了,可以正式进入学习了!
2.9 补充:交互式 Python(快速试代码用)
有时候你只想快速试一句代码,不想建文件,可以用"对话模式"。在终端里(先 conda activate py314)输入:
python
会看到 >>> 这样的提示符,这就是交互式环境(英文叫 REPL)。你可以直接输入代码,回车立刻出结果:
>>> 1 + 2
3
>>> print("hi")
hi
想退出,输入 exit() 再回车即可。
本教程里的很多小例子,你都可以在文件里跑,也可以在
>>>里试。建议先建文件跑,养成好习惯。
3. 第一个程序
3.1 print:让电脑"说"出来
print 是 Python 里最常用的一个功能:把东西显示到屏幕上。print 就是"打印、显示"的意思。
print("你好,化学世界!")
print(42)
print(3.14)
运行结果:
你好,化学世界!
42
3.14
要点:
print后面跟一对圆括号(),括号里是要显示的内容。- 显示文字时,文字要用引号包起来(单引号
'...'或双引号"..."都可以,成对用就行)。 - 显示数字时,直接写数字,不用引号。
3.2 一次显示多个东西
用逗号隔开,print 会把它们依次显示出来,中间自动加一个空格:
print("氢", "氦", "锂", "铍") # 会显示:氢 氦 锂 铍
print("原子序数:", 1) # 会显示:原子序数: 1
3.3 注释:写给"人"看,电脑不管
代码里,以 # 开头的部分叫注释。注释是写给你自己(或同事)看的说明文字,电脑会直接跳过它。
# 这个程序会打印一个元素符号
print("H") # 这一行后面的 # 也是注释
写注释是好习惯,尤其过几天你自己回头看代码时,注释能帮你快速想起"我当时在干嘛"。
动手试试
- 用
print显示你的名字。 - 用
print显示一个元素符号和它的原子序数(比如 O 和 8)。 - 写一行注释,说明你的代码在做什么。
参考答案(思路):
print("XXX") # 练习1:显示你的名字
print("O", 8) # 练习2:显示元素符号和原子序数
# 这里写一句说明这个程序在干什么
4. 变量与基本数据类型
4.1 变量:给东西起个名字存起来
变量(variable) 就是"一个有名字的盒子",你可以往盒子里放东西,之后用名字就能把这个东西拿出来用。
element = "H" # 建一个叫 element 的变量,里面放了字符串 "H"
atomic_number = 1 # 建一个叫 atomic_number 的变量,里面放了数字 1
print(element) # 打印出 element 里存的东西 -> H
print(atomic_number) # -> 1
=在这里叫赋值,意思是"把右边的东西放到左边的盒子里"。读作"把 ... 赋给 ...",不是"等于"!这点新手特别容易混,后面第 18 章专门讲。- 变量的名字你可以自己起,但有个规则:只能由字母、数字、下划线
_组成,且不能以数字开头。比如mass1可以,1mass不行;原子量这种中文名其实也能用,但强烈建议用英文或拼音,兼容性更好。 - 变量名是区分大小写的:
Mass和mass是两个不同的变量。
mass = 1.008 # 氢的相对原子质量(粗略值)
print(mass) # 1.008
mass = 4.0 # 盒子里的东西可以换
print(mass) # 4.0
4.2 四种最基础的数据类型
数据类型 就是"东西的种类"。电脑对不同种类的东西,处理方式不一样。最开始你只需要认识这几种:
| 类型 | 英文 | 说明 | 例子 |
|---|---|---|---|
| 整数 | int | 不带小数点的数 | 1, -3, 100 |
| 浮点数 | float | 带小数点的数("浮点"就是"小数点会浮动"的意思,别被名字吓到) | 3.14, 1.008, -0.5 |
| 字符串 | str | 一串文字,用引号包起来 | "H2O", "hello" |
| 布尔值 | bool | 只有两个取值:真 / 假 | True, False |
n = 8 # int 整数
weight = 15.999 # float 浮点数(氧的相对原子质量)
formula = "H2O" # str 字符串
is_gas = True # bool 布尔值(水是气体吗?False 才对吧,这里只做演示)
print(n, weight, formula, is_gas)
注意 True 和 False 首字母必须大写,否则会报错。
4.3 用 type() 查看一个东西的类型
print(type(8)) # <class 'int'>
print(type(15.999)) # <class 'float'>
print(type("H2O")) # <class 'str'>
print(type(True)) # <class 'bool'>
<class '...'> 里的就是类型名。看不懂没关系,记住 type() 能帮你看"这到底是个啥"。
4.4 类型转换:把一种类型变成另一种
这是科研数据处理里极其常用的操作。比如从文件读出来的数字常常是字符串 "3.14",你要拿它做计算,就得先转成数字。
a = "42" # 这是一个字符串,不是数字
b = int(a) # int(...) 把它转成整数 42
print(b + 1) # 43(字符串没法直接 +1,转成数字才能算)
c = "3.14"
d = float(c) # 转成浮点数
print(d * 2) # 6.28
e = 100
f = str(e) # 数字转成字符串
print("数值是" + f) # "数值是100"(字符串和字符串才能用 + 拼起来)
反过来,如果转不了,会报错:
int("abc") # 报错!"abc" 没法变成整数
这个报错我们到第 15 章会知道怎么处理。
动手试试
- 建一个变量存你的年龄,用
type()看它的类型。 - 建一个变量存字符串
"100",把它转成整数后加 1,打印结果。 - 把整数
7转成字符串,再用+和字符串"号元素"拼起来打印。
参考答案:
# 1
age = 22
print(type(age)) # <class 'int'>
# 2
s = "100"
print(int(s) + 1) # 101
# 3
n = 7
print(str(n) + "号元素") # 7号元素
5. 运算符
运算符 就是"加、减、比大小、判断真假"这些符号。程序里靠它们做计算和判断。
5.1 算术运算符(加减乘除那些)
| 符号 | 含义 | 例子 | 结果 |
|---|---|---|---|
+ | 加 | 1 + 2 | 3 |
- | 减 | 5 - 2 | 3 |
* | 乘 | 3 * 4 | 12 |
/ | 除(结果永远是浮点数) | 10 / 4 | 2.5 |
// | 整除(只取整数部分,向下取) | 10 // 4 | 2 |
% | 取余数 | 10 % 4 | 2 |
** | 乘方 | 2 ** 3 | 8 |
注意:乘是 * 不是 ×,除是 / 不是 ÷,电脑键盘上没有 ×÷ 号。
print(10 / 4) # 2.5,普通除法,结果是小数
print(10 // 4) # 2,整除,丢掉小数部分
print(10 % 4) # 2,10 除以 4 余 2
print(2 ** 10) # 1024,2 的 10 次方
% 取余特别有用,比如判断一个数是不是偶数:x % 2 == 0(余 0 就是偶数)。
5.2 比较运算符(比大小,结果是 True / False)
| 符号 | 含义 | 例子 | 结果 |
|---|---|---|---|
== | 等于 | 3 == 3 | True |
!= | 不等于 | 3 != 3 | False |
> | 大于 | 5 > 3 | True |
< | 小于 | 5 < 3 | False |
>= | 大于等于 | 5 >= 5 | True |
<= | 小于等于 | 4 <= 3 | False |
print(3 == 3) # True
print(3 == 4) # False
print(3 != 4) # True
特别注意:判断"等于"要用两个等号 ==,单个 = 是赋值,不是比较。这是新手第一大坑,第 18 章再强调。
5.3 逻辑运算符(把多个判断组合起来)
and:两边都真,结果才真("并且")。or:两边只要有一个真,结果就真("或者")。not:取反(把真变假、假变真)。
print(3 > 2 and 5 > 4) # True,两个都对
print(3 > 2 and 5 > 10) # False,第二个不对
print(3 > 10 or 5 > 4) # True,第二个对就行
print(not (3 > 2)) # False,把"对"变成"错"
5.4 赋值运算符(简写)
前面见过 =。还有几种"边算边存"的简写:
x = 10
x = x + 5 # x 变成 15(先算右边的 x+5=15,再存回 x)
print(x) # 15
x += 5 # 和 x = x + 5 完全等价,简写
print(x) # 20
x -= 3 # x = x - 3
x *= 2 # x = x * 2
x /= 4 # x = x / 4
动手试试
- 计算 7 的 3 次方。
- 判断 2024 是不是偶数(提示:
2024 % 2 == 0)。 - 设
temp = 25,写一个逻辑表达式,判断温度是否在 0 到 100 之间(用and)。 - 用
//和%,把 100 秒换算成"分钟和剩余秒"。
参考答案:
# 1
print(7 ** 3) # 343
# 2
print(2024 % 2 == 0) # True
# 3
temp = 25
print(temp > 0 and temp < 100) # True
# 4
total = 100
minutes = total // 60 # 1
seconds = total % 60 # 40
print(minutes, "分", seconds, "秒")
6. 输入输出
6.1 input:让用户输入内容
input() 会让程序停下来,等你在键盘上打字并按回车,然后把你输入的内容作为字符串返回(还给你)。
name = input("请输入你的名字:")
print("你好,", name)
运行后,程序会显示 请输入你的名字: 等你输入,你打 小明 回车,它就会打印 你好, 小明。
关键点:input() 拿到的永远是字符串(str)。如果你想拿它当数字用,必须自己转换:
age = input("请输入你的年龄:") # 你输入 22,但 age 是字符串 "22"
age = int(age) # 转成整数
print("明年你就", age + 1, "岁了")
6.2 f-string:把变量"塞进"字符串里
很多时候你想打印一句带变量的完整句子,比如"氢的原子序数是 1"。如果硬用 + 拼,很麻烦(数字还得先转字符串)。f-string 让这件事变得超简单。
用法:在字符串开头加一个字母 f,然后在字符串里用花括号 {} 把变量名包起来:
element = "氢"
number = 1
print(f"{element}的原子序数是{number}") # 氢的原子序数是1
mass = 1.008
print(f"{element}的相对原子质量约为{mass}") # 氢的相对原子质量约为1.008
花括号里还可以直接放表达式(就是可以算的东西):
a = 3
b = 4
print(f"{a} 加 {b} 等于 {a + b}") # 3 加 4 等于 7
还可以控制小数位数(科研里特别常用,比如保留两位小数):
pi = 3.1415926
print(f"π 约等于 {pi:.2f}") # π 约等于 3.14,:.2f 表示保留2位小数
f-string 是 Python 3.6 之后的功能,Python 3.14 完全支持,放心用。
动手试试
- 写个程序,用
input让用户输入一个元素符号,然后用 f-string 打印"你输入的元素是 XXX"。 - 让用户输入一个数字(字符串),转成整数,打印它的平方。
- 设
r = 2.5,用 f-string 打印圆的半径是 2.50(保留两位小数)。
参考答案:
# 1
e = input("请输入一个元素符号:")
print(f"你输入的元素是 {e}")
# 2
n = input("请输入一个数字:")
n = int(n)
print(f"它的平方是 {n ** 2}")
# 3
r = 2.5
print(f"圆的半径是 {r:.2f}")
7. 控制流:if / elif / else
控制流 就是"让程序根据不同情况走不同的路"。比如"如果温度高于 100 度,就显示'沸腾',否则显示'未沸腾'"。
7.1 最简单的 if
temp = 120
if temp > 100:
print("水沸腾了")
运行结果:水沸腾了。
结构拆解:
if后面跟一个条件(一个能算出 True 或 False 的东西,比如temp > 100),条件后面要加冒号:。- 冒号下面的代码,要缩进(也就是在行首空几格)。缩进的这些代码,只有在条件为 True 时才会执行。
7.2 if / else:两种情况
temp = 60
if temp >= 100:
print("沸腾")
else:
print("没沸腾")
else 表示"否则",也就是条件不成立时执行的代码。else 后面也要冒号,它下面的代码同样要缩进。
7.3 if / elif / else:多种情况
elif 是 "else if"(否则如果)的缩写,用于"还有别的可能"的情况。比如给成绩分级:
score = 85
if score >= 90:
print("优秀")
elif score >= 80:
print("良好")
elif score >= 60:
print("及格")
else:
print("不及格")
程序从上往下依次检查,遇到第一个成立的条件就执行对应代码,然后跳过后面所有的。所以 85 会命中第二个 elif,打印"良好"。
7.4 缩进规则(新手最容易错的地方!)
Python 靠缩进来判断"哪些代码属于这个 if"。这是它和其他语言最大的不同,也是新手报错最多的原因。
规则:
- 同一个 if 下面的代码,缩进必须一致(一般用 4 个空格,或按一次 Tab 键)。
- 缩进必须严格对齐,多一个空格、少一个空格都可能报错。
x = 10
if x > 5:
print("大于5") # 缩进了,属于 if
print("这行也属于 if")
print("这行不属于 if,无论如何都会执行")
运行结果:
大于5
这行也属于 if
这行不属于 if,无论如何都会执行
VS Code 里,你在冒号后回车,它会自动帮你缩进;按 Shift + Tab 可以减少缩进(退回一层)。
7.5 多个条件的组合
用 and、or 组合条件:
temp = 30
if 0 <= temp <= 100: # 这种连续写法是 Python 特色,表示 temp 在 0 到 100 之间
print("温度正常")
也可以写成 temp >= 0 and temp <= 100,两种都对。
再举个化学味儿的例子:判断元素状态(简单例举,别较真):
element = "Br" # 溴
if element == "Br":
print("常温下是液态非金属")
elif element in ["O", "H", "N","F","Cl"]: # 这里用到了第10章才讲的列表和 in
print("常温下是气体")
else:
print("常温下通常是固体")
动手试试
- 写个程序,判断一个数
n是正数、负数还是零。 - 写个程序,让用户输入一个元素符号,如果输入
"Au"就打印"这是金",否则打印"这不是金"。 - 判断一个年份是不是闰年(能被 4 整除但不能被 100 整除,或者能被 400 整除)。
参考答案:
# 1
n = -5
if n > 0:
print("正数")
elif n < 0:
print("负数")
else:
print("零")
# 2
e = input("请输入元素符号:")
if e == "Au":
print("这是金")
else:
print("这不是金")
# 3
year = 2024
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
print("闰年")
else:
print("不是闰年")
8. 循环:for 与 while
循环 就是"把一段代码重复执行很多次"。这是电脑最擅长的事——你写一遍,它替你跑一千遍。
8.1 for 循环:挨个遍历
for 循环的经典用法是:从一个"队伍"里,一个一个地把东西取出来,对每个东西做同样的事。
elements = ["H", "He", "Li", "Be", "B"] # 一个元素符号的队伍(列表,第10章细讲)
for e in elements: # 依次把 elements 里的每个元素拿出来,存进变量 e
print(e)
运行结果:
H
He
Li
Be
B
读法:for e in elements 可以读作"对于 elements 里的每一个 e,做下面缩进里的事"。每取一个 e,就执行一遍缩进的代码。
对字符串也能遍历(字符串也是一个字符接一个字符):
for ch in "H2O":
print(ch)
# 依次打印 H 2 O
8.2 range:生成一串整数
range(n) 生成"从 0 到 n-1"的整数。它常和 for 搭配,用来"重复 n 次":
for i in range(5): # range(5) 是 0,1,2,3,4 这5个数
print(i)
# 打印 0 1 2 3 4(注意没有 5!)
range 有三种用法:
range(5) # 0 到 4
range(1, 6) # 1 到 5(左闭右开:包含1,不包含6)
range(1, 10, 2) # 1,3,5,7,9(第三个参数是"步长",每次加2)
记忆口诀:range 是"左闭右开",左边能取到,右边取不到。
for i in range(1, 6):
print(f"第{i}次") # 第1次 到 第5次
8.3 while 循环:条件满足就继续
while 是"只要条件还成立,就反复执行"。适合"不知道要循环几次,只知道什么时候该停"的情况。
n = 1
while n <= 5:
print(n)
n = n + 1 # 每次加1,不然会永远循环(死循环)
# 打印 1 2 3 4 5
一定要记得让条件最终变成 False(比如上面让 n 不断增加),否则程序会永远转下去,这叫死循环,只能按 Ctrl+C 强制停。
8.4 break 和 continue
break:立刻跳出整个循环,后面不管还有多少都不做了。continue:跳过本次循环的剩余部分,直接进入下一轮。
for i in range(1, 11):
if i == 5:
break # 到 5 就彻底停
print(i)
# 打印 1 2 3 4
for i in range(1, 6):
if i == 3:
continue # 跳过 3,但继续后面的
print(i)
# 打印 1 2 4 5
8.5 循环里累加:科研里最常见的套路
求一组数据的总和、平均值,本质就是"循环 + 累加":
data = [25.1, 24.8, 25.3, 24.9, 25.0] # 5次实验测得的温度
total = 0 # 先建一个"存总和"的盒子,初始为 0
for x in data:
total = total + x # 每次把当前值加进去
print(f"总和 = {total}")
print(f"平均值 = {total / len(data)}") # len(data) 是数据的个数
len(...) 是"数一数队伍里有几个"的意思,这里 len(data) 是 5。这个套路请一定亲手敲一遍,它是所有数据处理的基础。
动手试试
- 用 for + range 打印 1 到 100 里所有的偶数(提示:步长 2,从 2 开始)。
- 用 for 遍历
["Na", "K", "Ca"],打印"元素 XX"。 - 用 while 从 10 倒数到 1。
- 求 1 到 100 所有整数的和(用累加套路)。
参考答案:
# 1
for i in range(2, 101, 2):
print(i)
# 2
for e in ["Na", "K", "Ca"]:
print(f"元素 {e}")
# 3
n = 10
while n >= 1:
print(n)
n = n - 1
# 4
total = 0
for i in range(1, 101):
total = total + i
print(total) # 5050
9. 字符串进阶
字符串(str)是科研文本处理的绝对主力——分子式、元素符号、文件名、日志,全是字符串。这一章把常用操作一次讲清。
9.1 索引:取出某个位置的字符
字符串里的每个字符都有编号,这个编号叫索引(index)。编号从 0 开始,不是从 1 开始!这是新手常忘的点。
字符串: H 2 O
索引: 0 1 2
formula = "H2O"
print(formula[0]) # H
print(formula[1]) # 2
print(formula[2]) # O
print(formula[-1]) # O,-1 表示"倒数第一个"
print(formula[-3]) # H,-3 表示"倒数第三个"
负索引就是"从右边数",-1 是最后一个,-2 是倒数第二个。
9.2 切片:取出一段
切片(slice) 用 [开始:结束] 取出一段。规则和 range 一样:左闭右开,取得到开始,取不到结束。
s = "chemistry"
print(s[0:4]) # chem(索引0到3,不包含4)
print(s[4:7]) # ist
print(s[:4]) # chem(冒号前省略,表示从0开始)
print(s[4:]) # istry(冒号后省略,表示到最后)
print(s[-3:]) # try(最后3个)
还可以带步长:s[开始:结束:步长],比如 s[::2] 是"从头到尾每隔一个取一个"。
9.3 常用字符串方法
方法 就是"这个东西自带的、能用 . 点出来的功能"。字符串有很多方法,下面是最常用的:
| 方法 | 作用 | 例子 | 结果 |
|---|---|---|---|
upper() | 全变大写 | "h2o".upper() | "H2O" |
lower() | 全变小写 | "H2O".lower() | "h2o" |
strip() | 去掉两头的空格/换行 | " H2O ".strip() | "H2O" |
split() | 按某个字符切开,返回列表 | "H,O,C".split(",") | ["H", "O", "C"] |
replace(a,b) | 把 a 替换成 b | "H2O".replace("2","") | "HO" |
join(列表) | 用本字符串把列表拼起来 | ",".join(["H","O"]) | "H,O" |
startswith(x) | 是否以 x 开头 | "data.csv".startswith("data") | True |
endswith(x) | 是否以 x 结尾 | "data.csv".endswith(".csv") | True |
formula = " ch4 "
print(formula.strip()) # ch4(去掉空格)
print(formula.strip().upper()) # CH4
s = "Na,Cl,K"
parts = s.split(",") # 用逗号切开
print(parts) # ['Na', 'Cl', 'K']
text = "mol/kg"
print(text.replace("mol/kg", "mol/L")) # mol/L
split() 特别实用:从文本文件读一行 "25.1,24.8,25.3",split(",") 一下就拆成了三个数据。
9.4 in:判断一个字符串里有没有另一个字符串
print("H" in "H2O") # True
print("Au" in "H2O") # False
print("碳" in "二氧化碳") # True
in 是"在...里面吗"的意思,结果 True/False,常配合 if 使用。
动手试试
- 字符串
s = "C6H12O6"(葡萄糖),用索引取出第 3 个字符(索引 2)。 - 用切片取出
s的前两个字符。 - 把
"h2o"变成全大写。 - 字符串
"C,H,N,O",用 split 拆成列表,再用 join 把它们用-连起来。
参考答案:
# 1
s = "C6H12O6"
print(s[2]) # H
# 2
print(s[:2]) # C6
# 3
print("h2o".upper()) # H2O
# 4
parts = "C,H,N,O".split(",")
print(parts) # ['C', 'H', 'N', 'O']
print("-".join(parts)) # C-H-N-O
10. 列表 list
列表(list) 是"一个能装很多东西的有序盒子"。它用方括号 [] 包起来,里面的东西用逗号隔开。列表里的东西可以改、可以增删,非常灵活,是 Python 里最常用的数据结构。
10.1 创建列表
elements = ["H", "He", "Li", "Be"] # 字符串列表
nums = [1, 2, 3, 4, 5] # 数字列表
mixed = ["H", 1, 1.008, True] # 列表里可以混放不同类型(但不推荐乱混)
empty = [] # 空列表
print(elements)
10.2 索引与切片(和字符串一模一样)
elements = ["H", "He", "Li", "Be"]
print(elements[0]) # H
print(elements[-1]) # Be
print(elements[1:3]) # ['He', 'Li']
10.3 改元素
列表和字符串的一个大区别:列表可以直接改(字符串不行,叫"不可变",第 11 章再细说)。
elements = ["H", "He", "Li"]
elements[0] = "氢" # 把第0个改成"氢"
print(elements) # ['氢', 'He', 'Li']
10.4 增删改查
| 操作 | 说明 | 例子 |
|---|---|---|
列表.append(x) | 在末尾加一个 | elements.append("B") |
列表.insert(i, x) | 在指定位置 i 插入 | elements.insert(1, "Li") |
列表.remove(x) | 删除第一个等于 x 的 | elements.remove("He") |
列表.pop(i) | 删除位置 i 的元素并返回它 | x = elements.pop(0) |
len(列表) | 列表里有几个元素 | len(elements) |
x in 列表 | x 在不在列表里 | "H" in elements |
elements = ["H", "He"]
elements.append("Li") # ['H', 'He', 'Li']
elements.insert(1, "Be") # ['H', 'Be', 'He', 'Li']
elements.remove("He") # ['H', 'Be', 'Li']
last = elements.pop() # 删掉最后一个 'Li',并把 'Li' 存进 last
print(last) # Li
print(elements) # ['H', 'Be']
print(len(elements)) # 2
10.5 遍历列表
elements = ["C", "H", "O", "N"]
for e in elements:
print(f"元素 {e}")
如果想同时拿到"序号"和"内容",用 enumerate:
for i, e in enumerate(elements):
print(f"第{i}个是{e}")
# 第0个是C 第1个是H ...
10.6 排序:sort 和 sorted
列表.sort():原地排序,直接改变原列表,不返回新列表。sorted(列表):返回一个排好序的新列表,原列表不变。
nums = [3, 1, 4, 1, 5, 9, 2]
a = sorted(nums) # 返回新列表,nums 不变
print(a) # [1, 1, 2, 3, 4, 5, 9]
print(nums) # [3, 1, 4, 1, 5, 9, 2](原样)
nums.sort() # 原地排序,nums 自己被改了
print(nums) # [1, 1, 2, 3, 4, 5, 9]
倒序加参数 reverse=True:
nums.sort(reverse=True)
print(nums) # [9, 5, 4, 3, 2, 1, 1]
10.7 求最大最小值(不用自己写循环)
Python 内置了 max、min、sum:
data = [25.1, 24.8, 25.3, 24.9, 25.0]
print(max(data)) # 25.3
print(min(data)) # 24.8
print(sum(data)) # 125.1
有了这些,上一章"累加求平均"可以一行搞定:
print(sum(data) / len(data)) # 25.02
动手试试
- 建一个含 5 个元素符号的列表,打印第 2 个(索引 1)和最后一个。
- 往列表里 append 一个元素,再 insert 一个到开头(索引 0)。
- 对
[5, 2, 8, 1, 9]用 sorted 排个序,再验证原列表没变。 - 求
[10, 20, 30, 40]的和、最大值、元素个数。
参考答案:
# 1
el = ["H", "He", "Li", "Be", "B"]
print(el[1], el[-1]) # He B
# 2
el.append("C")
el.insert(0, "X")
print(el)
# 3
nums = [5, 2, 8, 1, 9]
print(sorted(nums)) # [1, 2, 5, 8, 9]
print(nums) # [5, 2, 8, 1, 9]
# 4
a = [10, 20, 30, 40]
print(sum(a), max(a), len(a)) # 100 40 4
11. 元组、字典、集合
除了列表,Python 还有三种常用的"容器"。这一章讲清楚它们各自的用途和区别。
11.1 元组 tuple:不能改的列表
元组(tuple) 用圆括号 () 表示,它和列表几乎一样,但一旦创建就不能修改(不能增删改元素)。这叫"不可变"。
point = (3, 4) # 一个坐标
colors = ("红", "绿", "蓝")
print(point[0]) # 3
print(len(colors)) # 3
为什么要有它?因为有些东西你不希望被不小心改掉,比如一个分子的固定参数、一个不可变的坐标。用元组可以"锁起来",让代码更安全。凡是你确定不会再改的固定数据,用元组更合适;需要随时增删改的,用列表。
# 下面这行会报错,因为元组不能改
# colors[0] = "黄" # 会报 TypeError
11.2 字典 dict:给每个东西配一个"标签"
字典(dict) 用花括号 {},里面是**"键: 值"** 成对出现。键(key)相当于"标签",值(value)是标签对应的内容。它适合表示"一一对应"的关系。
最经典的例子:元素符号 → 原子序数。
atomic = {"H": 1, "He": 2, "Li": 3, "O": 8}
print(atomic["H"]) # 1,用键查值
print(atomic["O"]) # 8
结构拆解:{"H": 1} 里,"H" 是键,1 是值,中间用冒号,多对之间用逗号。
增删查改
atomic = {"H": 1, "O": 8}
# 查
print(atomic["H"]) # 1
print(atomic.get("Au")) # None(用 get 查不存在的键不会报错,返回 None)
print(atomic.get("Au", "没找到")) # 没找到(get 可以指定"找不到时返回啥")
# 增(直接给新键赋值)
atomic["C"] = 6
# 改(给已有键赋新值)
atomic["O"] = 8
# 删
del atomic["H"] # 删掉 H 这一项
removed = atomic.pop("C") # 删掉 C 并返回它的值 6
print(atomic) # {'O': 8}
判断键在不在
print("Au" in atomic) # False
遍历字典
atomic = {"H": 1, "He": 2, "Li": 3}
for key in atomic: # 默认遍历的是"键"
print(key) # H He Li
for key in atomic:
print(f"{key} 的原子序数是 {atomic[key]}")
for key, value in atomic.items(): # items() 同时拿到键和值
print(key, value)
11.3 集合 set:不重复、无顺序的一堆东西
集合(set) 也用花括号 {},但里面只有值,没有"键:值",而且元素不重复、没有固定顺序。它最大的用处是"去重"和"找交集/并集"。
s = {1, 2, 3, 3, 3} # 重复的 3 会被自动去掉
print(s) # {1, 2, 3}
s.add(4) # 加一个
print(s) # {1, 2, 3, 4}
科研里典型用法:你有两组样品编号,想看它们共有的和全部不重复的:
group_a = {"A", "B", "C", "D"}
group_b = {"C", "D", "E", "F"}
print(group_a & group_b) # 交集(两边都有):{'C', 'D'}
print(group_a | group_b) # 并集(合起来,去重):{'A','B','C','D','E','F'}
print(group_a - group_b) # 差集(A有B没有):{'A', 'B'}
去重:把一个列表直接塞进 set():
samples = ["A", "B", "A", "C", "B"]
unique = set(samples) # {'A', 'B', 'C'}
print(unique)
11.4 三种容器对比
| 列表 list | 元组 tuple | 字典 dict | 集合 set | |
|---|---|---|---|---|
| 符号 | [ ] | ( ) | {键: 值} | { } |
| 能否修改 | 能 | 不能 | 能(值可改) | 能(增删元素) |
| 有无顺序 | 有 | 有 | 有(按插入序) | 无 |
| 是否可重复 | 可 | 可 | 键不可重复 | 不可重复 |
| 典型用途 | 一堆同类数据 | 固定不变的组合 | 标签→内容 的对应 | 去重、集合运算 |
动手试试
- 建一个元组存你的生日(年, 月, 日),打印月份(索引 1)。
- 建一个字典,存 3 个元素符号及其相对原子质量,查其中一个。
- 往上面的字典里加一个新元素,再删掉一个。
- 用集合对
[1,2,2,3,3,3,4]去重。
参考答案:
# 1
birth = (2000, 5, 20)
print(birth[1]) # 5
# 2
mass = {"H": 1.008, "O": 15.999, "C": 12.011}
print(mass["O"]) # 15.999
# 3
mass["N"] = 14.007
del mass["C"]
print(mass)
# 4
print(set([1,2,2,3,3,3,4])) # {1, 2, 3, 4}
12. 函数
函数(function) 是"一段起好名字、可以反复调用的代码块"。它是编程里最重要的思想之一,一定要弄懂。
12.1 为什么需要函数:把重复代码收起来
假设你要在程序里好多地方算"圆的面积"(面积 = π × r²)。每次都得写一遍公式,既啰嗦又容易错。函数就是把这个公式封装成一个小工具,起个名字,以后想用就"喊"它一声。
12.2 def:定义函数
def circle_area(r): # 定义一个函数,名字叫 circle_area,接收一个参数 r
area = 3.14159 * r * r # 函数体(缩进!)
return area # 把结果"返回"给调用者
# 调用函数
a = circle_area(2) # r=2,算出面积存进 a
print(a) # 12.56636
print(circle_area(3)) # 28.27431
逐个拆解:
def:定义函数的关键词(define 的缩写)。circle_area:函数名,你自己起的,规则和变量名一样。(r):括号里是参数,就是"调用时传进来的数据"。这里r是半径。return:把结果"交出去"。函数里 return 之后,函数就结束了。- 调用函数时写
circle_area(2),就是把2传给参数r,然后执行函数体,把return的结果拿回来。
12.3 多个参数
def rectangle_area(width, height):
return width * height
print(rectangle_area(3, 5)) # 15
12.4 参数默认值
给参数设一个默认值,调用时如果没传这个参数,就用默认值:
def greet(name, greeting="你好"):
return f"{greeting},{name}"
print(greet("旅行者")) # 你好,旅行者
print(greet("派蒙", "早上好")) # 早上好,派蒙
注意:有默认值的参数必须放在没有默认值的参数后面。
12.5 没有 return 的函数
有些函数只是"做点事",不需要返回结果,这时可以不用 return(它实际上返回 None,表示"空"):
def show_element(element):
print(f"这个元素是 {element}")
show_element("Fe") # 打印:这个元素是 Fe
12.6 函数的好处(总结)
- 避免重复:一处定义,处处使用。
- 便于修改:公式改了,只改函数里一处。
- 更清晰:给代码分块,一眼看懂结构。
- 可复用:可以把函数存起来,以后别的项目接着用。
动手试试
- 定义一个函数
square(n),返回 n 的平方。 - 定义一个函数
mean(a, b, c),返回三个数的平均值。 - 定义一个函数
describe_element(symbol, number),打印"元素 XXX 的原子序数是 N",然后调用它试试。 - 定义一个函数,参数是"摄氏温度",返回"华氏温度"(公式:F = C × 9/5 + 32)。
参考答案:
# 1
def square(n):
return n ** 2
print(square(7)) # 49
# 2
def mean(a, b, c):
return (a + b + c) / 3
print(mean(1, 2, 3)) # 2.0
# 3
def describe_element(symbol, number):
print(f"元素 {symbol} 的原子序数是 {number}")
describe_element("O", 8) # 元素 O 的原子序数是 8
# 4
def c_to_f(c):
return c * 9 / 5 + 32
print(c_to_f(100)) # 212.0
13. 模块与导入
13.1 模块是什么
模块(module) 就是"别人(或你自己)写好的、装了一堆现成函数和功能的文件"。你不需要什么都自己从头写,Python 自带了很多"标准库"模块,直接用就行。
导入 就是"把这个模块拿进来用"。
13.2 import:导入模块
import math # 导入数学模块
print(math.pi) # 3.141592653589793
print(math.sqrt(16)) # 4.0,开平方
print(math.floor(3.7)) # 3,向下取整
print(math.ceil(3.2)) # 4,向上取整
注意用法:导入了 math 后,要用 math.xxx 这种"模块名点功能"的方式调用。
random 模块(生成随机数)也很有用:
import random
print(random.random()) # 生成 [0,1) 之间的随机小数
print(random.randint(1, 6)) # 生成 1 到 6 之间的随机整数(含1和6),像掷骰子
print(random.choice(["H", "O", "C", "N"])) # 从列表里随机选一个
print(random.uniform(0, 10)) # 生成 0 到 10 之间的随机小数
13.3 from ... import ...:只导入某个功能
这样以后可以直接用名字,不用加"模块名."前缀:
from math import sqrt, pi
print(sqrt(25)) # 5.0
print(pi) # 3.14159...
13.4 自己写模块
其实你写的 .py 文件本身就是一个模块。比如你写了个 mytools.py,里面定义了几个函数,另一个文件就能导入它:
# 假设有个 mytools.py 文件,内容如下:
def double(x):
return x * 2
# 在同一个文件夹的另一个文件里:
import mytools
print(mytools.double(5)) # 10
13.5 pip:安装第三方库
标准库之外,还有海量的第三方库(别人写好上传到网上的),用 pip 来安装。pip 是 Python 自带的"安装器"。
在终端里(先 conda activate py314):
pip install numpy
意思就是"用 pip 装 numpy 这个库"。装完后就能 import numpy 用了。
常用命令:
pip install 包名 # 安装
pip uninstall 包名 # 卸载
pip list # 看装了什么
国内安装如果很慢,可以加清华镜像源加速:
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
动手试试
- 用 math 模块算 2 的平方根和 3 的 2 次方(
math.pow)。 - 用 random 生成 5 个 1 到 100 之间的随机整数(提示:用 for 循环)。
- 用
from math import factorial,算 5 的阶乘(factorial(5))。
参考答案:
# 1
import math
print(math.sqrt(2)) # 1.414...
print(math.pow(3, 2)) # 9.0
# 2
import random
for i in range(5):
print(random.randint(1, 100))
# 3
from math import factorial
print(factorial(5)) # 120
14. 文件读写
科研里,数据几乎都存在文件里。学会读写文件,你才能让程序真正"处理数据"。
14.1 打开、读、关闭
读一个文本文件,最经典的写法:
f = open("data.txt", "r", encoding="utf-8") # 打开文件,"r" 表示读(read)
content = f.read() # 把整个文件内容读成一个字符串
print(content)
f.close() # 用完要关掉
open(文件名, 模式, encoding=...):打开文件。- 模式
"r"表示读,"w"表示写(会覆盖原内容),"a"表示追加(往末尾加)。
- 模式
encoding="utf-8":一定要写,尤其是 Windows 下中文文件,不写可能乱码或报错。- 用完
close()关闭文件,释放资源。
14.2 with 语句:自动关闭(推荐)
手动 close() 容易忘(尤其中间报错时)。用 with 可以自动帮你关闭,这是标准推荐写法:
with open("data.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
# 出了 with 的缩进块,文件会自动关闭,不用写 close()
14.3 逐行读取
数据文件常常是"一行一个数据",用 readlines() 读成"每行是一个元素的列表",或直接 for 循环逐行读:
# 方法1:readlines()
with open("data.txt", "r", encoding="utf-8") as f:
lines = f.readlines() # 每一行(含末尾换行符)作为列表的一个元素
for line in lines:
print(line.strip()) # strip 去掉行尾的换行符和空格
# 方法2:直接 for 循环文件对象(推荐,更省内存)
with open("data.txt", "r", encoding="utf-8") as f:
for line in f:
print(line.strip())
14.4 写文件
with open("output.txt", "w", encoding="utf-8") as f:
f.write("第一行内容\n") # \n 是"换行符"
f.write("第二行内容\n")
注意:模式 "w" 会覆盖原文件(如果文件已存在,内容被清空重写)。想保留旧内容往末尾加,用 "a"(append)。
14.5 完整例子:读一行一个数值,转成数字算总和
假设 data.txt 内容是一行一个温度值:
25.1
24.8
25.3
24.9
25.0
values = [] # 建空列表存数字
with open("data.txt", "r", encoding="utf-8") as f:
for line in f:
line = line.strip() # 去掉换行符
if line: # 跳过空行
values.append(float(line)) # 转成浮点数,存进列表
print(values) # [25.1, 24.8, 25.3, 24.9, 25.0]
print(f"平均值 = {sum(values) / len(values)}")
这是科研数据处理的最基础骨架,请务必亲手跑一遍。第 17 章的综合项目就是它的升级版。
动手试试
- 写一个程序,创建一个文件
hello.txt,写入两行文字。 - 再读回这个文件,把内容打印出来。
- 写一个程序,把
[1.5, 2.5, 3.5]三个数,每个一行写入nums.txt,然后再读出来求平均值。
参考答案:
# 1
with open("hello.txt", "w", encoding="utf-8") as f:
f.write("你好\n")
f.write("Python\n")
# 2
with open("hello.txt", "r", encoding="utf-8") as f:
print(f.read())
# 3
with open("nums.txt", "w", encoding="utf-8") as f:
for n in [1.5, 2.5, 3.5]:
f.write(str(n) + "\n") # 数字要先转字符串才能写
with open("nums.txt", "r", encoding="utf-8") as f:
nums = []
for line in f:
nums.append(float(line.strip()))
print(sum(nums) / len(nums)) # 2.5
15. 错误与异常
写代码一定会遇到报错,这不代表你笨,而是编程的日常。关键是学会看懂报错、知道怎么改。
15.1 几种最常见的报错
NameError:用了没定义的名字
print(mass) # 如果从没定义过 mass,会报 NameError: name 'mass' is not defined
原因:变量没定义就用了,或者拼写错了(比如定义了 mass,却写成了 mss)。
TypeError:类型不对
print("数字" + 5) # TypeError: can only concatenate str (not "int") to str
原因:字符串和数字不能直接 +。要么把 5 转成字符串,要么别用 + 拼。
IndexError:索引越界
el = ["H", "He"]
print(el[5]) # IndexError: list index out of range(列表只有2个元素,索引0和1)
原因:访问的位置超出了范围。记住索引从 0 开始,最大是 长度-1。
ValueError:值不对
int("abc") # ValueError: invalid literal for int()
原因:"abc" 没法转成数字。
SyntaxError:语法错误(最常见,比如少冒号、少括号)
if True
print("x") # SyntaxError:if 后面少了冒号
原因:标点符号写错了。仔细看报错提示指向的那一行。
FileNotFoundError:文件找不到
open("不存在的文件.txt") # FileNotFoundError
原因:文件名写错,或程序运行的目录里没有这个文件。
15.2 怎么看懂报错信息
报错信息通常会告诉你三件事,看例子:
Traceback (most recent call last):
File "test.py", line 3, in <module>
print(mass)
NameError: name 'mass' is not defined
File "test.py", line 3:错误出在哪个文件的第 3 行——这是定位问题的关键。NameError:错误类型。name 'mass' is not defined:具体原因描述。
技巧:从报错信息的最后一行往上读,最后一行往往是问题的本质,前面告诉你发生在哪一行。
15.3 try / except:让程序别一报错就崩溃
有些错误是可以预见的(比如用户可能输入了没法转数字的内容)。用 try/except 可以"试着做,做不成就走备用方案":
raw = input("请输入一个数字:")
try:
num = float(raw) # 试着转成浮点数
print(f"它的平方是 {num ** 2}")
except ValueError: # 如果转失败(输入的不是数字),就走这里
print("你输入的不是数字!")
结构:
try:下面放"可能出错"的代码。except 错误类型:下面放"出错时怎么办"。- 程序不会因为 try 里的错误而崩溃,而是跳到 except 继续跑。
try/except 还能处理文件不存在的情况:
try:
with open("data.txt", "r", encoding="utf-8") as f:
print(f.read())
except FileNotFoundError:
print("没找到 data.txt 这个文件")
动手试试
- 故意写一个 NameError,运行看报错,然后改正它。
- 写一个程序,让用户输入一个整数,如果输入的不是整数(比如
abc),用 try/except 打印"请输入整数"。 - 访问列表
[1,2,3]的索引 10,看看报什么错,再用 try/except 把它接住。
参考答案:
# 2
raw = input("请输入一个整数:")
try:
n = int(raw)
print(f"你输入的是 {n}")
except ValueError:
print("请输入整数")
# 3
try:
print([1,2,3][10])
except IndexError:
print("索引越界了")
16. 面向对象入门(可选)
这一章是可选的,第一次读不懂可以先跳过,不影响你完成前面的所有内容。但了解个大概,对以后看别人的代码很有帮助。
16.1 类(class)和对象(object)是什么,用大白话讲
想象你要在程序里描述"分子"这个东西。每个分子都有一些属性(名字、分子式、相对分子质量)和一些行为(比如"显示自己的信息")。
- 类(class) 就是"图纸 / 模板"——它规定了"分子应该有什么属性、什么行为"。
- 对象(object) 就是"照着图纸造出来的具体实例"——一个具体的分子,比如 H2O。
类定义"长什么样",对象是"具体的那一个"。
16.2 定义一个类
class Molecule: # 定义一个叫 Molecule 的类
def __init__(self, name, formula): # 特殊方法:造对象时自动运行,设置初始属性
self.name = name # 把传入的 name 存到对象自己的 name 属性上
self.formula = formula
def show(self): # 普通方法:显示信息
print(f"分子 {self.name} 的化学式是 {self.formula}")
# 造两个对象(叫"实例化")
m1 = Molecule("水", "H2O")
m2 = Molecule("甲烷", "CH4")
m1.show() # 分子 水 的化学式是 H2O
m2.show() # 分子 甲烷 的化学式是 CH4
逐个拆解(先有个印象就行):
class Molecule:定义类。__init__是"构造方法",在创建对象时自动调用,用来给对象设置初始属性。self表示"对象自己"。self.name = name:把参数name存成对象自己的属性name。def show(self):对象的方法,用对象名.show()调用。
16.3 为什么用面向对象
当你有很多"同类型、各有属性、要做同样操作"的东西时,用类可以把"数据"和"操作数据的方法"打包在一起,代码更清晰、更不容易乱。对于科研新手,先用函数就够了,等遇到真正需要时再深入。
到这里,你已经覆盖了 Python 最核心的语法。下一章我们把前面学的串起来,做一个真正有用的脚本。
17. 综合小项目:处理一组实验数据
17.1 项目目标
写一个完整脚本,完成下面这件事:
- 读入一个数据文件(一行一个数值,比如一批实验测得的温度/能量值)。
- 算出数据个数、总和、平均值、最大值、最小值。
- 把结果写进一个新的结果文件
result.txt。
这个脚本你以后能直接改一改用来处理自己的真实数据。
17.2 先准备数据文件
先手动建一个 data.txt(用 VS Code 或记事本),内容是一行一个数值:
25.1
24.8
25.3
24.9
25.0
26.2
17.3 完整代码
# 文件名:analyze_data.py
# 功能:读入一组实验数据,计算统计量,写入结果文件
INPUT_FILE = "data.txt" # 输入文件名(大写表示这是"常量",约定俗成)
OUTPUT_FILE = "result.txt" # 输出文件名
def read_data(filename):
"""从文件读取数据,每行一个数值,返回浮点数列表。"""
values = []
with open(filename, "r", encoding="utf-8") as f:
for line in f:
line = line.strip() # 去掉换行符和空格
if line: # 跳过空行
values.append(float(line)) # 转成浮点数存起来
return values
def analyze(values):
"""计算一组数据的统计量,返回结果字典。"""
n = len(values) # 数据个数
total = sum(values) # 总和
mean = total / n # 平均值
return {
"个数": n,
"总和": total,
"平均值": mean,
"最大值": max(values),
"最小值": min(values),
}
def write_result(stats, filename):
"""把统计结果写入文件。"""
with open(filename, "w", encoding="utf-8") as f:
f.write("===== 数据分析结果 =====\n")
for key, value in stats.items(): # 遍历字典的键和值
f.write(f"{key}: {value:.3f}\n") # 保留3位小数
# ---- 主程序:按顺序调用上面的函数 ----
data = read_data(INPUT_FILE) # 1. 读数据
print(f"共读入 {len(data)} 个数据:{data}")
stats = analyze(data) # 2. 算统计量
print("统计结果:", stats)
write_result(stats, OUTPUT_FILE) # 3. 写结果
print(f"结果已写入 {OUTPUT_FILE}")
17.4 运行与检查
在 VS Code 里运行(或终端里 python analyze_data.py),屏幕会显示:
共读入 6 个数据:[25.1, 24.8, 25.3, 24.9, 25.0, 26.2]
统计结果: {'个数': 6, '总和': 151.3, '平均值': 25.216..., '最大值': 26.2, '最小值': 24.8}
结果已写入 result.txt
打开 result.txt,你会看到:
===== 数据分析结果 =====
个数: 6.000
总和: 151.300
平均值: 25.217
最大值: 26.200
最小值: 24.800
17.5 拆解:这个脚本用了哪些前面学的知识
- 函数(第 12 章):把"读数据、算统计、写结果"分成三个函数,各管一件事。
- 文件读写 + with(第 14 章):读 data.txt、写 result.txt。
- 列表 + 循环 + 累加(第 8、10 章):把每行转成数字存进列表。
- 字符串 strip / float 转换(第 4、9 章):清理换行、类型转换。
- 字典 + items() 遍历(第 11 章):存统计结果并遍历输出。
- f-string(第 6 章):格式化输出。
17.6 自己动手改一改(挑战)
- 让程序同时算标准差(公式:先求每个数与平均值的差的平方的平均,再开平方)。提示:用
math.sqrt,用循环或列表推导。 - 改成读入"逗号分隔"的数据(一行
25.1,24.8,25.3),用split(",")拆开。 - 加一个 try/except,如果文件不存在就友好提示。
参考答案(标准差 + 逗号分隔 + 容错):
import math
def read_data_comma(filename):
values = []
with open(filename, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if line:
for piece in line.split(","): # 按逗号拆
piece = piece.strip()
if piece:
values.append(float(piece))
return values
def std(values):
mean = sum(values) / len(values)
variance = sum((x - mean) ** 2 for x in values) / len(values) # 方差
return math.sqrt(variance) # 标准差
# 主程序
try:
data = read_data_comma("data.txt")
print(f"平均值 = {sum(data)/len(data):.3f}")
print(f"标准差 = {std(data):.3f}")
except FileNotFoundError:
print("找不到数据文件")
18. 新手常见坑清单
这一章把新手最容易栽跟头的地方集中列出来,强烈建议打印贴在显示器旁边。
坑 1:缩进不一致
if True:
print("A")
print("B") # 错!缩进比上面少了一个空格,会报 IndentationError
规则:同一层代码缩进必须完全一致(建议统一用 4 个空格)。VS Code 里按 Tab 会自动缩进 4 格。
坑 2:中文/全角符号
这是中国新手第一大坑!编程必须用**英文(半角)**的标点符号,尤其是:
| 错误(全角) | 正确(半角) |
|---|---|
( ) 中文括号 | ( ) |
“” ‘’ 中文引号 | " ' |
, 中文逗号 | , |
: 中文冒号 | : |
print(“hello”) # 错!全是中文标点,报 SyntaxError
print("hello") # 对
技巧:写代码时把输入法切到英文状态。引号、括号、逗号、冒号都要是英文的。注释里的中文没关系,但代码本身的标点必须是英文。
坑 3:= 和 == 混淆
=是赋值:把右边的值放进左边变量。==是比较:判断左右是否相等,结果是 True/False。
x = 5 # 赋值,x 现在是 5
if x == 5: # 比较,判断 x 是否等于 5
print("x 是 5")
if x = 5: 会直接报错,因为 = 不是判断。
坑 4:变量没定义 / 拼写错误
mass = 1.008
print(mas) # NameError,少写了个 s
仔细看报错里提示的变量名,对照你定义的名字。
坑 5:索引从 0 开始
el = ["H", "He", "Li"]
print(el[3]) # IndexError!只有 0、1、2 三个索引
第一个元素索引是 0,最后一个是 len(el) - 1(这里是 2)。想取最后一个,直接用 el[-1]。
坑 6:input() 返回的是字符串
n = input("请输入数字:") # 你输入 10,n 是字符串 "10"
print(n + 1) # TypeError!字符串不能和数字相加
要先 n = int(n) 转成数字。
坑 7:编码问题(Windows 特有)
Windows 下读中文文件如果不指定编码,可能乱码或报错。读写文件都加 encoding="utf-8":
with open("data.txt", "r", encoding="utf-8") as f:
...
坑 8:修改字符串时以为能直接改
字符串是"不可变"的,不能 s[0] = "x"。要改就用切片拼或 replace:
s = "H2O"
# s[0] = "X" # 错!字符串不能这样改
s = "X" + s[1:] # 对,重新拼一个
坑 9:忘了冒号 :
if、for、while、def、class 这些行的末尾都要加冒号:
for i in range(3): # 冒号不能少
print(i)
坑 10:整数除法取整想当然
Python 3 里 / 永远是小数结果(浮点),要整除用 //:
print(10 / 4) # 2.5
print(10 // 4) # 2
19. 下一步学什么 + 推荐资源
19.1 恭喜你
到这里,你已经掌握了 Python 最核心的语法:变量、类型、运算、输入输出、判断、循环、字符串、列表/字典/集合、函数、模块、文件读写、异常处理。这些是所有 Python 程序的地基,后面学的任何高级内容都建立在这上面。
19.2 下一步学什么(按对你科研的优先级)
-
数据科学三件套(强烈建议优先):
- NumPy:高效处理数值数组,是科学计算的基础。
- pandas:处理表格数据(像 Excel 但强得多)。
- Matplotlib:画图(折线、散点、直方图)。
- 这三者的教程在你本教程的同目录下都有:
NumPy教程.md、pandas教程.md、Matplotlib教程.md。
-
科研工具:等你需要做具体科研时再学:
- ASE(原子模拟环境)、pymatgen(材料学)、RDKit(化学信息学)、SciPy、scikit-learn(机器学习)——这些教程也在同目录下。
-
进阶语言特性(有基础后再回来):
- 列表推导式、lambda、生成器、装饰器、类型注解。
19.3 推荐资源
- 官方文档:
https://docs.python.org/zh-cn/3/(有中文版,权威但稍硬核,遇到问题查)。 - 菜鸟教程:
https://www.runoob.com/python3/(中文,适合查阅)。 - 廖雪峰 Python 教程:
https://www.liaoxuefeng.com/wiki/1016959663602400(经典中文教程)。 - 《Python编程:从入门到实践》(书):全球最畅销的入门书之一,有大量动手项目。
- B站:搜"Python 零基础",找播放量高的系统课程跟着做。
19.4 最后的话
学编程没有捷径,唯一的秘诀是:多写、多错、多改。今天学的每一个小知识点,都亲手敲一遍、改一改、故意弄错一次看看报错长什么样。坚持一个月,你会发现:以前那些要手动点半天的数据处理,现在写几行代码就搞定了。
祝你学习顺利,科研路上 Python 能成为你可靠的助手!
本教程完。如果你按顺序走完了 19 章,并亲手敲过每个例子,你就已经是一名"会写 Python"的人了。接下来去学 NumPy、pandas、Matplotlib,把它们用到你的真实数据上吧。
评论交流
欢迎留下你的想法