Python 极简入门教程(精炼但全面)
目的:用一份“最短路径但不失全面”的教程,把你从 0 带到能写出可维护、可发布的小项目。尽量以标准库为主,减少外部依赖;每节都有可复制即用的示例与练习。
目录
- 前言:学习路径与心法
- 第 1 章 环境与工具
- 第 2 章 语言基础(变量、类型、运算、输入输出)
- 第 3 章 容器与序列(str/bytes/list/tuple/set/dict)
- 第 4 章 流程控制与推导式
- 第 5 章 函数、参数、闭包与装饰器、类型注解
- 第 6 章 模块、包与项目结构
- 第 7 章 面向对象:数据模型与
dataclass
- 第 8 章 文件、Path 与常用数据格式(CSV/JSON)
- 第 9 章 错误处理、调试与日志
- 第 10 章 标准库速查(必会 20 选)
- 第 11 章 并发入门:
threading
/multiprocessing
/asyncio
- 第 12 章 网络与 Web 基础:
socket
、urllib
、http.server
- 第 13 章 命令行程序:
argparse
与可执行脚本
- 第 14 章 测试与质量:
unittest
、doctest
、typing
- 第 15 章 打包与发布:
pyproject.toml
、虚拟环境、版本管理
- 第 16 章 实战 1:待办 CLI(本地 JSON 存储)
- 第 17 章 实战 2:迷你日志分析器
- 第 18 章 实战 3:并发下载器(asyncio)
- 第 19 章 实战 4:静态网站小生成器(Markdown → HTML)
- 第 20 章 常见坑与最佳实践清单
- 附录 A 7 日速成 + 21 日进阶计划
- 附录 B 习题与参考答案
- 附录 C 内置函数与关键 PEP 速览
备注:本教程围绕 Python 3.10+ 编写,示例兼容 3.8+(除 match
模式匹配等特性)。
前言:学习路径与心法
- 先跑通,再优雅:先用最直白的方法跑通需求,再学习更“Pythonic”的写法(推导式、上下文管理、迭代器)。
- 标准库优先:Python 自带“电池”很全;只有当标准库不够用时再引入第三方。
- 读代码 + 改代码:复制示例,马上运行、改动、打印、断点——肌肉记忆 > 纸上谈兵。
最短学习闭环:
- 安装 →
- REPL 试手 →
- 写 50 行脚本 →
- 包装成 CLI →
- 写 5 个单测 →
- 打包发布到私用环境。
第 1 章 环境与工具
1.1 安装与版本
- 建议使用官方安装包或
pyenv
管理多版本。
- 检查版本:
1
2
|
python3 --version
python3 -c "import sys; print(sys.version)"
|
1.2 虚拟环境
1
2
3
|
python3 -m venv .venv
source ./.venv/bin/activate # Windows: .\.venv\Scripts\activate
python -m pip install --upgrade pip
|
1.3 编辑器与调试
- VS Code + Python 扩展;或 PyCharm 社区版。
- 断点调试:VS Code F5,或用内置
pdb
:
1
|
import pdb; pdb.set_trace()
|
第 2 章 语言基础
2.1 变量与基本类型
1
2
3
4
5
|
x = 42 # int
pi = 3.14159 # float
ok = True # bool
name = "Alice" # str
nothing = None # NoneType
|
- 动态类型、强类型:变量无类型、值有类型;不会隐式把 str 与 int 相加。
2.2 数值与运算符
1
2
3
4
5
|
5 // 2 # 2 整除
5 % 2 # 1 取模
2 ** 8 # 256 幂
abs(-3)
round(3.14159, 2) # 3.14
|
2.3 字符串基础
1
2
3
4
|
s = "hello" " " "world" # 相邻字面量合并
s = f"{name} has {x} apples"
len(s)
"py" in "python" # True
|
多行:
1
2
3
4
|
text = """
Line1
Line2
"""
|
2.4 输入与输出
1
2
3
|
name = input("Your name: ")
print("Hi,", name)
print("a", "b", sep=",", end="!\n")
|
第 3 章 容器与序列
3.1 list(动态数组)
1
2
3
4
5
|
nums = [1, 2, 3]
nums.append(4)
nums.extend([5, 6])
nums[0], nums[-1]
nums[1:4] # 切片
|
3.2 tuple(不可变序列)
1
2
|
pt = (10, 20)
x, y = pt # 解包
|
3.3 dict(映射)
1
2
3
4
5
|
user = {"name": "Alice", "age": 18}
user["age"] = 19
user.get("city", "NA")
for k, v in user.items():
print(k, v)
|
3.4 set(去重集合)
1
2
|
A = {1, 2, 3}; B = {3, 4}
A | B, A & B, A - B
|
3.5 序列通用操作
- 成员:
in
/ not in
- 长度:
len()
- 排序:
sorted(iterable, key=..., reverse=...)
第 4 章 流程控制与推导式
1
2
3
4
5
6
7
8
9
10
11
12
|
if score >= 90:
grade = "A"
elif score >= 60:
grade = "C"
else:
grade = "F"
for i in range(5):
print(i)
while n > 0:
n -= 1
|
推导式:
1
2
3
|
squares = [x*x for x in range(10) if x % 2 == 0]
keys = {k for k in ["a", "b", "a"]}
index = {i: v for i, v in enumerate(["a", "b"]) }
|
模式匹配(3.10+):
1
2
3
4
5
|
def http_status(code: int) -> str:
match code:
case 200 | 201: return "OK"
case 404: return "Not Found"
case _ : return "Unknown"
|
第 5 章 函数、闭包、装饰器、类型注解
5.1 函数与参数
1
2
3
4
|
def add(a, b=0, *args, scale=1, **kw):
return (a + b + sum(args)) * scale
add(1, 2, 3, 4, scale=10)
|
5.2 闭包与高阶函数
1
2
3
4
5
6
7
|
def make_adder(k):
def adder(x):
return x + k
return adder
add5 = make_adder(5)
add5(10)
|
5.3 装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import time
def timed(fn):
def wrapper(*a, **kw):
t0 = time.perf_counter()
try:
return fn(*a, **kw)
finally:
print(f"{fn.__name__} took {time.perf_counter()-t0:.3f}s")
return wrapper
@timed
def work():
time.sleep(0.1)
work()
|
5.4 类型注解(typing
)
1
2
3
4
|
from typing import Iterable, List
def top_n(xs: Iterable[int], n: int) -> List[int]:
return list(sorted(xs, reverse=True)[:n])
|
第 6 章 模块、包与项目结构
project/
├─ app/
│ ├─ __init__.py
│ ├─ main.py
│ └─ utils.py
├─ tests/
│ └─ test_utils.py
├─ pyproject.toml
└─ README.md
1
2
3
|
# app/main.py
if __name__ == "__main__":
print("Hello")
|
- 导入:
from app.utils import foo
第 7 章 面向对象:Python 数据模型
1
2
3
4
5
6
7
8
9
|
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
def __add__(self, other: "Point") -> "Point":
return Point(self.x + other.x, self.y + other.y)
|
- 常用 “dunder” 方法:
__repr__
、__len__
、__iter__
、__enter__/__exit__
。
上下文管理:
1
2
3
4
5
6
7
8
9
10
11
|
class Timer:
def __enter__(self):
import time
self.t0 = time.perf_counter()
return self
def __exit__(self, *exc):
import time
print(f"took {time.perf_counter()-self.t0:.3f}s")
with Timer():
sum(range(10_000))
|
第 8 章 文件、Path 与数据格式
1
2
3
4
|
from pathlib import Path
p = Path("data.txt")
p.write_text("hello\n", encoding="utf-8")
print(p.read_text(encoding="utf-8"))
|
CSV/JSON:
1
2
3
4
5
6
7
8
9
|
import csv, json, pathlib
rows = [{"id": 1, "name": "A"}, {"id": 2, "name": "B"}]
with open("users.csv", "w", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=rows[0].keys())
w.writeheader(); w.writerows(rows)
pathlib.Path("users.json").write_text(json.dumps(rows, ensure_ascii=False, indent=2))
|
第 9 章 错误处理、调试与日志
1
2
3
4
5
6
7
8
|
try:
risky()
except ValueError as e:
print("bad value:", e)
else:
print("no error")
finally:
clean()
|
日志:
1
2
3
4
|
import logging
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
log = logging.getLogger(__name__)
log.info("start")
|
第 10 章 标准库 20 选(速查)
pathlib
、dataclasses
、datetime
、time
itertools
、functools
、operator
collections
(Counter
/deque
/defaultdict
)
re
、json
、csv
、sqlite3
subprocess
、shutil
、tempfile
hashlib
、hmac
每个模块 1 分钟查阅文档 + 5 分钟写一个小片段。
第 11 章 并发入门
11.1 线程
1
2
3
4
5
6
7
8
|
from threading import Thread
def job(n):
print("work", n)
threads = [Thread(target=job, args=(i,)) for i in range(5)]
[t.start() for t in threads]
[t.join() for t in threads]
|
11.2 进程
1
2
3
|
from multiprocessing import Pool
with Pool() as pool:
print(pool.map(lambda x: x*x, range(8)))
|
11.3 asyncio
1
2
3
4
5
6
7
8
9
10
11
12
|
import asyncio, time
async def fetch(n):
await asyncio.sleep(0.1)
return n
async def main():
t0 = time.perf_counter()
res = await asyncio.gather(*(fetch(i) for i in range(10)))
print(res, time.perf_counter()-t0)
asyncio.run(main())
|
第 12 章 网络与 Web 基础
12.1 urllib
1
2
|
from urllib.request import urlopen
print(urlopen("https://example.com").read()[:60])
|
12.2 迷你 HTTP 服务器
1
2
|
from http.server import HTTPServer, SimpleHTTPRequestHandler
HTTPServer(("127.0.0.1", 8000), SimpleHTTPRequestHandler).serve_forever()
|
12.3 socket
1
2
3
4
|
import socket
with socket.create_connection(("example.com", 80)) as s:
s.sendall(b"GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
print(s.recv(1024))
|
第 13 章 命令行程序:argparse
1
2
3
4
5
6
7
8
9
|
# cli.py
import argparse, json
p = argparse.ArgumentParser(prog="echojson", description="Echo as JSON")
p.add_argument("message")
p.add_argument("--upper", action="store_true")
args = p.parse_args()
msg = args.message.upper() if args.upper else args.message
print(json.dumps({"message": msg}, ensure_ascii=False))
|
可执行:
第 14 章 测试与类型
14.1 unittest
1
2
3
4
5
6
7
8
9
10
|
# tests/test_mathx.py
import unittest
from app.utils import add
class T(unittest.TestCase):
def test_add(self):
self.assertEqual(add(1, 2), 3)
if __name__ == "__main__":
unittest.main()
|
14.2 doctest
1
2
3
4
5
6
7
8
9
10
|
def mean(xs: list[float]) -> float:
"""Return average.
>>> mean([1,2,3])
2.0
"""
return sum(xs)/len(xs)
if __name__ == "__main__":
import doctest
doctest.testmod()
|
第 15 章 打包与发布(现代最简)
pyproject.toml
:
1
2
3
4
5
6
7
8
9
10
|
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "minipkg"
version = "0.1.0"
description = "A tiny example"
authors = [{name="You"}]
requires-python = ">=3.9"
|
构建:
1
2
|
python -m pip install --upgrade build
python -m build
|
第 16 章 实战 1:待办 CLI(本地 JSON)
16.1 目标
todo add "task"
、todo ls
、todo done 3
。
16.2 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# todo.py
from __future__ import annotations
import argparse, json, sys
from pathlib import Path
PATH = Path.home()/".todo.json"
def load() -> list[dict]:
if PATH.exists():
return json.loads(PATH.read_text(encoding="utf-8"))
return []
def save(items: list[dict]) -> None:
PATH.write_text(json.dumps(items, ensure_ascii=False, indent=2), encoding="utf-8")
def cmd_add(text: str):
items = load(); items.append({"text": text, "done": False})
save(items); print("Added.")
def cmd_ls():
for i, it in enumerate(load(), 1):
flag = "✓" if it["done"] else "✗"
print(f"{i:>2}. [{flag}] {it['text']}")
def cmd_done(i: int):
items = load(); i -= 1
if 0 <= i < len(items):
items[i]["done"] = True; save(items); print("Done.")
else:
print("index out of range", file=sys.stderr)
if __name__ == "__main__":
p = argparse.ArgumentParser(prog="todo")
sub = p.add_subparsers(dest="cmd", required=True)
a = sub.add_parser("add"); a.add_argument("text")
sub.add_parser("ls")
d = sub.add_parser("done"); d.add_argument("index", type=int)
args = p.parse_args()
match args.cmd:
case "add": cmd_add(args.text)
case "ls": cmd_ls()
case "done": cmd_done(args.index)
|
第 17 章 实战 2:迷你日志分析器
- 输入:Nginx 访问日志
- 输出:PV/UV、Top IP、Top URL、状态码分布
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
# logsum.py
import re, sys, collections
pat = re.compile(r"^(?P<ip>\S+) \S+ \S+ \[(?P<ts>[^\]]+)\] \"(?P<method>\S+) (?P<path>\S+) \S+\" (?P<status>\d{3})")
Counter = collections.Counter
ips = Counter(); urls = Counter(); codes = Counter(); uv = set()
for line in sys.stdin:
m = pat.match(line)
if not m: continue
d = m.groupdict()
ips[d['ip']] += 1
urls[d['path']] += 1
codes[d['status']] += 1
uv.add(d['ip'])
print("PV:", sum(ips.values()))
print("UV:", len(uv))
print("TOP IP:", ips.most_common(5))
print("TOP URL:", urls.most_common(5))
print("CODES:", codes.most_common())
|
第 18 章 实战 3:并发下载器(asyncio)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# adl.py
import asyncio, aiohttp, pathlib
async def fetch(session, url):
name = url.split('/')[-1] or 'index.html'
data = await (await session.get(url)).read()
pathlib.Path(name).write_bytes(data)
return name, len(data)
async def main(urls):
async with aiohttp.ClientSession() as s:
for coro in asyncio.as_completed(fetch(s, u) for u in urls):
name, n = await coro
print(f"saved {name} bytes={n}")
if __name__ == "__main__":
import sys
asyncio.run(main(sys.argv[1:]))
|
说明:此处用到第三方 aiohttp
,可替换为标准库 urllib
+ 线程池以避免依赖。
第 19 章 实战 4:静态网站小生成器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# ssg.py (Markdown -> HTML 极简)
from pathlib import Path
import argparse, html
def md_to_html(md: str) -> str:
lines = md.splitlines()
out = []
for ln in lines:
if ln.startswith('# '):
out.append(f"<h1>{html.escape(ln[2:])}</h1>")
elif ln.startswith('## '):
out.append(f"<h2>{html.escape(ln[3:])}</h2>")
else:
out.append(f"<p>{html.escape(ln)}</p>")
return "\n".join(out)
if __name__ == "__main__":
p = argparse.ArgumentParser(); p.add_argument("src"); p.add_argument("dst")
args = p.parse_args()
Path(args.dst).write_text(md_to_html(Path(args.src).read_text(encoding="utf-8")), encoding="utf-8")
|
第 20 章 常见坑与最佳实践
- 可变默认参数:
def f(x, xs=[])
→ 用 None
+ 内部初始化。
- 路径:用
pathlib
代替 os.path
。
- 编码:读写文本总是显式
encoding="utf-8"
。
- 日志:
print
只用于交互,程序事件用 logging
。
- 异常:只捕获你能处理的异常,不要裸
except:
。
- 依赖:能用标准库就别装第三方;要装就固定版本。
- 性能:优先用内建函数与向量化思维(
sum
、any
、all
、map
、生成器表达式)。
附录 A 7 日速成 + 21 日进阶
7 日速成(每日 1–2 小时)
- 安装 / REPL / 变量与类型
- 容器(list/dict)/ 切片 / 推导式
- 函数与参数 / 模块导入
- 文件 IO / JSON / Path
- 流程控制 / 错误处理 / 日志
- 命令行脚本 / argparse
- 小项目:Todo CLI + 3 个单测
21 日进阶
- 并发(线程/异步)、网络、
sqlite3
、dataclass
、typing
、unittest
、打包发布、性能分析(timeit
/cProfile
)。
附录 B 习题与参考答案(节选)
B.1 写函数 flatten
:把嵌套 list 拉平成一维生成器。
1
2
3
4
5
6
|
def flatten(xs):
for x in xs:
if isinstance(x, list):
yield from flatten(x)
else:
yield x
|
B.2 用 Counter
统计一段文本里 Top 10 单词。
1
2
3
4
|
from collections import Counter
import re
words = re.findall(r"[a-zA-Z]+", open("book.txt", encoding="utf-8").read().lower())
print(Counter(words).most_common(10))
|
B.3 写一个上下文管理器,进入时切换到某目录,退出时切回。
1
2
3
4
5
6
7
8
9
10
11
|
import os
from contextlib import contextmanager
@contextmanager
def cd(path):
old = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(old)
|
附录 C 内置函数与关键 PEP 速览
结束语
把上面的示例都亲手敲一遍,再把四个实战项目串成一个“工具包”仓库(加 README、测试与版本号)。这比读十篇长文更快进入实战。祝编码愉快!