10 分钟学会 Python

这是我当初最希望有人递给我的速成教程:只讲你真会用到的东西、真会碰到的错误,也允许你暂时跳过其余内容。直接读,或者在任一章节点“播放”,泡咖啡时也能学。

🎙️ 发布并录制于: · 更新于 ·

01变量

左边写名字,右边放值,就这么简单。不用声明类型,也不用分号。类型提示现在也可以先跳过,等以后遇到时,自然就能看懂它为什么有用。

name = "Ada"          # 字符串
age = 36              # 整数
height = 1.7          # 浮点数
is_ready = True       # T 必须大写,写成 true 会报错
nothing = None        # Python 里的“null”,N 必须大写

print(name, age)      # Ada 36
你一定会遇到
NameError: name 'true' is not defined
Python 区分大小写,布尔值写作 TrueFalse,不是 truefalse。如果你从 JavaScript 转过来,这周大概会顺手写错三次。

02字符串

Python 有三种字符串格式化方式,其中两种先不用学。百分号格式化和 .format() 常见于旧教程、旧项目;你只需要会写 f-string:引号前加字母 f,变量放进花括号。

name = "Ada"
msgs = 5
print(f"Hi {name}, you have {msgs} messages")

# 这四个方法足以覆盖九成实际字符串处理:
s = "  Swift Grasp  "
s.strip()             # "Swift Grasp",去掉首尾空白
s.lower()             # 用于忽略大小写的比较
s.split()             # ['Swift', 'Grasp']
", ".join(["a", "b"])  # "a, b",没错,join 写在分隔符上
你一定会遇到
TypeError: can only concatenate str (not "int") to str
这是因为你写了 "age: " + 36。Python 不肯直接把文本和数字粘起来。别到处塞 str(),改用 f-string:f"age: {36}",问题以后就不会再来。

03If / Else 条件判断

这里没有花括号。冒号表示代码块开始,而缩进本身就是语法。这是新手第一天最常见的报错来源,所以现在就把它处理干净。

score = 87

if score >= 90:
    print("A")
elif score >= 80:
    print("B")               # 会执行这一行
else:
    print("keep going")

# and / or / not 是单词,不是 && || !
if 80 <= score < 90:          # 链式比较,很有 Python 风格
    print("solid B")

label = "pass" if score >= 60 else "fail"
你一定会遇到
IndentationError: unexpected indent,或者它的邪恶双胞胎:TabError: inconsistent use of tabs and spaces
十次里有九次,是你粘贴的代码混用了 Tab 和空格。一次解决,永不复发:在 VS Code 里打开命令面板,运行 "Convert Indentation to Spaces",再确认状态栏显示 Spaces: 4。以后不用再惦记。

04列表

这是每天都会用的容器:有顺序、能混装不同类型、需要时还能增长。先抓住两个重点:负数索引从末尾往前数,切片用来截取一段范围。

langs = ["python", "js", "rust"]

langs.append("go")       # 添加到末尾
langs[0]                 # "python"
langs[-1]                # "go",最后一项,不必绕去算 len()
langs[1:3]               # ['js', 'rust'],不包含结束索引
len(langs)               # 4
"rust" in langs          # True

nums = [3, 1, 2]
sorted(nums)             # 返回排序后的新副本:[1, 2, 3]
nums.sort()              # 原地排序,返回 None
你一定会遇到
IndexError: list index out of range
四项列表的索引是零到三,langs[4] 已经越界。想拿最后一项时,直接用 langs[-1],不要写 langs[len(langs)-1];后一种写法最容易滋生这类错误。

05字典

字典保存键值对,很像 JSON 对象。我估计实际写 Python 时,有一半时间都在传递字典。尽早养成一个习惯:某个键必须存在时用方括号;它可能不存在时用 .get()

user = {"name": "Ada", "age": 36}

user["name"]                   # "Ada"
user["role"] = "admin"         # 新增或覆盖

user.get("email")              # None,不会报错
user.get("email", "n/a")       # "n/a",提供默认值

for key, value in user.items():
    print(f"{key} = {value}")
你一定会遇到
KeyError: 'email'
用方括号访问不存在的键,程序会直接报错。数据损坏时,大声失败往往正是你想要的;但遇到 API 响应或配置中的可选字段,带默认值的 .get() 会稳妥得多。

06循环

Python 的 for 会直接遍历每一项。如果你正在写 for i in range(len(things)),先停一下,几乎总有更干净的写法。还需要索引?那就用 enumerate

for lang in ["python", "js", "rust"]:
    print(lang)

for i, lang in enumerate(["a", "b"]):
    print(i, lang)           # 先输出 0 a,再输出 1 b

for i in range(3):            # 只有数字:0, 1, 2
    print(i)

count = 3
while count > 0:
    count -= 1                # Python 没有 count--
没有报错的隐蔽问题
一边遍历列表,一边从中删除元素,会漏掉一些项。循环位置会在脚下移动,而 Python 不会提醒你。请遍历副本:for x in items[:];或者用下一节的推导式创建新列表。

07函数

def 定义函数,用 return 交回结果。默认值让参数变成可选项;调用时写出参数名,比如 greet(excited=True),半年后回头看依然清楚。

def greet(name, excited=False):
    msg = f"Hello, {name}"
    return msg + "!" if excited else msg

greet("Ada")                   # Hello, Ada
greet("Ada", excited=True)     # Hello, Ada!

# 返回两个值,实际是一个元组,接收时解包
def min_max(nums):
    return min(nums), max(nums)

lo, hi = min_max([3, 1, 9])    # lo=1, hi=9
经典 Python 陷阱
绝不要写 def add(item, items=[])。这个默认列表只创建一次,之后所有调用共享它;第一次调用加入的内容,会出现在第二次调用里。每个 Python 开发者大概都会中招一次。请改用 items=None,再在函数内部写 if items is None: items = []

08推导式

一行创建新列表:左边做转换,中间写循环,右边加筛选。我只有一条实在的规矩:如果需要不止一个 if,或者还要嵌套循环,就老老实实写普通循环。卖弄聪明的一行代码,很容易让你白丢一个下午。

nums = [1, 2, 3, 4, 5]

squares = [n * n for n in nums]           # [1, 4, 9, 16, 25]
evens = [n for n in nums if n % 2 == 0]   # [2, 4]

# 字典版本
lengths = {w: len(w) for w in ["hi", "hello"]}
# {'hi': 2, 'hello': 5}

09文件

打开文件一律用 with。即使代码执行到一半报错,它也会替你关闭文件。还要始终传入 encoding="utf-8"。很多教程没写,是因为在作者的 Mac 上碰巧没问题;到了 Windows,默认编码不同,真实文件很快就会给你上一课。

with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("line one\n")

with open("notes.txt", encoding="utf-8") as f:
    for line in f:               # 逐行读取,文件多大都可以
        print(line.strip())

# 读写 JSON,每周都会用到
import json
with open("data.json", "w", encoding="utf-8") as f:
    json.dump({"name": "Ada"}, f)
你会在 Windows 上遇到
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d
这是因为在 Windows 上打开 UTF-8 文件时,没有写 encoding="utf-8"。解决办法就是养成上面的习惯。多敲这几个字符,比困惑一个小时便宜得多。

10错误处理

这里练两项本事。第一,看到 Traceback 时,先读最后一行,那里才是真正的错误;上面的内容只是调用路径。第二,只捕获明确的错误类型。一个光秃秃的 except: 会吞掉代码块里的所有问题,之后你可能要花几小时找它到底吃掉了什么。

try:
    age = int("not a number")
except ValueError:
    print("that wasn't a number")

try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"oops: {e}")

# 输入不合理时主动抛出错误
def set_age(age):
    if age < 0:
        raise ValueError("age can't be negative")
怎样阅读 Traceback
看到 Traceback (most recent call last):,请从下往上读。最后一行说明哪里出错;倒数第二行给出确切文件和行号;更上面则是程序如何走到这里。多数新手从上往下读,很快就会迷失在框架内部。

11

说句实话:就算几周不定义任何类,你照样能写出有用的 Python,所以别卡在这里。先学会读懂类就够了:__init__ 在创建对象时运行,self 就是对象在指代自己。然后继续往前走。等字典变得难以收拾,再回来学。

class Dog:
    def __init__(self, name):
        self.name = name
        self.tricks = []

    def learn(self, trick):
        self.tricks.append(trick)
        return f"{self.name} learned {trick}"

rex = Dog("Rex")
rex.learn("sit")
rex.tricks                     # ['sit']
你一定会遇到
TypeError: learn() takes 1 positional argument but 2 were given
你在方法定义里漏掉了 self。每个实例方法的第一个参数都是 self。Python 会自动把对象传进去,所以在真正理解这一点之前,参数数量总像是差了一位。

12速查表

下面这些写法,每个人都会搜索上百次。把这一节加入书签,它本来就是干这个的。

# 交换两个变量
a, b = b, a

# 反转列表或字符串
nums[::-1]

# 去重并保留顺序,list(set(x)) 会打乱顺序,不要用
list(dict.fromkeys(items))

# 最常见的元素
from collections import Counter
Counter(words).most_common(1)

# 合并两个字典,键冲突时右侧优先
merged = {**defaults, **overrides}

# 读取用户输入
name = input("Name: ")

# 在终端安装软件包或运行脚本
# pip install requests
# python script.py

这就是能真正拿来干活的语言核心。想让它留在脑子里,靠的不是继续读,而是挑一件生活中又小又烦的事,比如批量重命名文件,或者写个终端待办清单,然后把它做出来。你现在已经会得够多了。

Tell me what missed

A correction is more useful than a compliment. This goes straight to the person who writes SwiftGrasp.

Was this page useful?
0/1000

Please do not include passwords, private keys, or personal information.