跳转至

第 1 章 · 语法快速对照

本章把最基础的语法过一遍,让你快速建立"Python 长什么样"的直觉。如果你已经能看懂下面这段代码的大意,就可以跳到下一章:

def greet(name: str, times: int = 1) -> list[str]:
    """Return a list of greetings."""
    return [f"Hello, {name}!" for _ in range(times)]

1.1 没有 {};:缩进就是语法

这是你最先要适应的。Java 用大括号划分块,Python 用缩进(约定 4 个空格);语句末尾不需要分号。

  • Java

    if (x > 0) {
        System.out.println("positive");
        doSomething();
    }
    
  • Python

    if x > 0:
        print("positive")
        do_something()
    

⚠️ Java 程序员的陷阱

缩进不一致会直接 IndentationError。不要 Tab 和空格混用——编辑器里统一设成"4 空格",且让 Tab 自动转成空格。

命名风格也从 camelCase 换成 snake_case:函数和变量 do_somethinguser_name;类名仍用 PascalCase(如 HttpClient);常量 UPPER_SNAKE(约定,语言不强制)。


1.2 变量与类型:动态类型,无需声明

Java 是静态强类型:声明变量必须写类型,编译期检查。Python 是动态强类型:变量不绑定类型,值才有类型;同一个名字可先后指向不同类型的对象。

  • Java

    String name = "Alice";   // 类型钉死
    int age = 30;
    // name = 30;            // 编译错误
    
  • Python

    name = "Alice"           # 类型由值决定
    age = 30
    name = 30                # 合法!name 现在指向 int
    

强类型 ≠ 弱类型

Python 是强类型"a" + 1 会抛 TypeError(不会像 JavaScript 那样悄悄变 "a1")。它只是把类型检查推迟到运行时。要静态检查?第 8 章的类型提示 + mypy 把它"补"回来。

可选的类型注解(annotation)只是给人和工具看的提示,运行时不强制

age: int = 30          # 注解可写可不写,不改变运行行为

1.3 数字:int 无限精度,没有 ++

两个反直觉点:

  • Java

    int a = 2147483647;
    a = a + 1;           // 溢出为 -2147483648
    long big = 10L;
    double d = 3.14;
    i++;                 // 自增
    
  • Python

    a = 2147483647
    a = a + 1            # 2147483648,永不溢出
    big = 10 ** 100      # 任意大整数都没问题
    d = 3.14             # float 即 Java 的 double
    # i++                # 语法错误!只能 i += 1
    
  • int任意精度的,没有 Integer/Long/BigInteger 之分。
  • 没有 ++ / --:用 i += 1
  • 浮点 float 等价于 Java 的 double;除法 / 永远返回 float(7 / 2 == 3.5),整除用 //7 // 2 == 3),取余用 %,幂用 **

1.4 字符串:不可变 + f-string

字符串不可变(和 Java 一样),但字符串拼接别再用 + 一串连起来——用 f-string(格式化字符串字面量):

  • Java

    String name = "Alice";
    int age = 30;
    String s = String.format(
        "%s is %d years old", name, age);
    // 或 "Alice" + " is " + 30 + "..."
    
  • Python

    name = "Alice"
    age = 30
    s = f"{name} is {age} years old"
    # 还能内嵌表达式:
    s2 = f"next year: {age + 1}"
    

常用操作对照:

操作 Java Python
长度 s.length() len(s)
取字符 s.charAt(0) s[0]
子串 s.substring(1, 4) s[1:4](切片)
大写 s.toUpperCase() s.upper()
分割 s.split(",") s.split(",")
包含 s.contains("ab") "ab" in s
去空白 s.trim() s.strip()

Pythonic 写法

Python 字符串可以用 "',多行用三引号 """..."""切片(slice) 是 Python 的核心语法,第 7 章会深入。


1.5 布尔、None 与 truthiness

  • Java

    boolean ok = true;
    String name = null;          // null 引用
    if (list != null && !list.isEmpty()) { }
    
  • Python

    ok = True                   # 首字母大写!
    name = None                 # None 是单例对象,不是 null
    if lst:                     # 直接判断"非空"
        ...
    

两个要点:

  1. True / False / None 首字母大写。写小写会报 NameError
  2. truthiness(真值测试):Python 的 if 能直接吃任何对象——空容器、0None"" 都是"假",其余"真"。所以 if lst: 等价于 Java 的 if (lst != null && !lst.isEmpty())

⚠️ Java 程序员的陷阱

别写 if lst == True:if lst is not None and len(lst) > 0:。前者会把 1 == True 这种隐式比较带进来,后者啰嗦。直接 if lst:

判断 Noneis(身份比较),不用 ==

if name is None: ...      # ✅ 判 None 用 is
if name is not None: ...  # ✅

1.6 控制流

if / elif / else

  • Java

    if (score >= 90) {
        grade = "A";
    } else if (score >= 60) {
        grade = "B";
    } else {
        grade = "C";
    }
    
  • Python

    if score >= 90:
        grade = "A"
    elif score >= 60:        # 不是 "else if"
        grade = "B"
    else:
        grade = "C"
    

三元表达式

# Java:  String s = ok ? "yes" : "no";
# Python:
s = "yes" if ok else "no"

for:永远遍历,不数索引

  • Java

    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
    for (String s : list) { ... }
    
  • Python

    for item in list:           # 直接遍历
        print(item)
    for i, item in enumerate(list):   # 要索引时
        print(i, item)
    

需要一个数字序列?用 range(不是 for(i=0;i<n;i++)):

for i in range(5):       # 0,1,2,3,4
    ...
for i in range(2, 10, 2): # 2,4,6,8(起、止、步长)
    ...

match-case(Python 3.10+ 的"switch")

Python 没有 switch,但 3.10 起有结构化模式匹配 match,比 switch 强大得多:

def describe(point):
    match point:
        case (0, 0):
            return "origin"
        case (0, y):
            return f"on y-axis, y={y}"
        case (x, 0):
            return f"on x-axis, x={x}"
        case (x, y):
            return f"point ({x}, {y})"

简单的值匹配,它就当 switch 用;它真正强大在能解构数据结构(第 7 章会再提)。注意:若无任何 case 匹配,函数返回 None——像 switch 的 default 一样,用 case _: 兜底更稳妥(见下面练习 1.2)。


1.7 集合一览

Python 内置四件套,对应 Java 的常见容器:

Python Java 对应 特点
list ArrayList 有序、可变、[1, 2, 3]
tuple (无直接对应) 有序、不可变(1, 2, 3)
dict HashMap / LinkedHashMap 键值对、{"a": 1}
set HashSet 无序、去重、{1, 2, 3}
  • Java

    List<Integer> nums = new ArrayList<>();
    nums.add(1); nums.add(2);
    nums.get(0);                 // 取元素
    Map<String, Integer> m = new HashMap<>();
    m.put("a", 1);
    m.get("a");
    
  • Python

    nums = [1, 2]
    nums.append(3)
    nums[0]                      # 取元素,不是 nums.get(0)
    m = {"a": 1}
    m["b"] = 2                   # 赋值即"put"
    m["a"]                       # 取值,不是 m.get("a")(也有 .get)
    

Pythonic 写法

遍历 dict 不要 .keySet(),直接 for key, value in m.items():

集合的细节(可变性、引用语义、推导式)在第 3 章数据模型和第 7 章惯用法深入。现在记住:方括号 [] 是 list、花括号 {} 是 dict 或 set、圆括号 () 是 tuple


本章练习

练习 1.1

把下面这段 Java 翻译成 Pythonic 的 Python(注意:是 Pythonic,不是逐行翻译):

StringBuilder sb = new StringBuilder();
for (int i = 0; i < names.size(); i++) {
    if (names.get(i) != null) {
        sb.append(names.get(i).toUpperCase());
        if (i < names.size() - 1) sb.append(", ");
    }
}
return sb.toString();

参考答案

return ", ".join(name.upper() for name in names if name)
要点:用 str.join 拼接、生成器表达式过滤 None/空串、if name 借助 truthiness。参考答案见 solutions/01_syntax.py

练习 1.2

match 写一个函数 http_status(code: int) -> str:200 返回 "OK",404 返回 "Not Found",500 返回 "Server Error",其余返回 "Unknown"

参考答案
def http_status(code: int) -> str:
    match code:
        case 200: return "OK"
        case 404: return "Not Found"
        case 500: return "Server Error"
        case _:   return "Unknown"   # _ 是通配
练习 1.3

解释为什么 if x == True:x = 1 时为真,而 if x: 才是推荐写法。

参考答案

Python 里 boolint 的子类,True == 1,所以 1 == True 成立——这会把"恰好等于 1 的整数"误判为真。if x: 用的是 truthiness,语义是"x 非零/非空",更准确地表达意图,也避免了隐式数值比较。


← 回首页 | 下一章:第 2 章 · 函数