Kotlin vs Python 知识点对照表

Kotlin vs Python 知识点对照表

面向精通Kotlin的开发者,快速掌握Python核心知识

目录

  1. 语法核心对照
    • 1.1 变量与类型声明
    • 1.2 函数定义
    • 1.3 类与对象
    • 1.4 泛型系统
    • 1.5 类型系统进阶
    • 1.6 空安全处理
    • 1.7 集合操作
    • 1.8 扩展函数与运算符重载
  2. 并发模型对照
    • 2.1 协程 vs asyncio
    • 2.2 线程模型
    • 2.3 异常处理
  3. 标准库/生态对照
    • 3.1 包管理
    • 3.2 测试框架
    • 3.3 常用库对照
  4. 运行时特性对照
    • 4.1 编译 vs 解释
    • 4.2 内存模型
    • 4.3 垃圾回收
  5. [Python 易错代码大全](#Python 易错代码大全 "#5-python-%E6%98%93%E9%94%99%E4%BB%A3%E7%A0%81%E5%A4%A7%E5%85%A8")
    • 5.1 可变默认参数陷阱
    • 5.2 闭包变量绑定延迟
    • 5.3 or 运算符的假值陷阱
    • 5.4 == vs is 的身份 vs 相等
    • 5.5 整数缓存与身份比较
    • 5.6 列表推导式中的变量泄漏
    • 5.7 self 忘记写
    • 5.8 __init__ 返回值陷阱
    • 5.9 字符串拼接性能陷阱
    • 5.10 try/except 吞掉 KeyboardInterrupt
    • 5.11 *args 捕获生成器耗尽
    • 5.12 @dataclass__hash__ 陷阱
    • 5.13 isinstance 与类型的微妙关系
    • 5.14 dict 修改时遍历崩溃
    • 5.15 浅拷贝 vs 深拷贝
    • 5.16 boolint 的子类
    • 5.17 None 的比较陷阱
    • 5.18 lambda 在循环中的闭包陷阱
    • 5.19 multiprocessing 的 lambda 序列化失败
    • 5.20 asyncio 中调用同步阻塞函数
  6. 快速参考表

1. 语法核心对照

1.1 变量与类型声明

Kotlin
kotlin 复制代码
// 不可变变量 (val)
val name: String = "Kotlin"
val inferred = "类型推断"  // String

// 可变变量 (var)
var count: Int = 0
count = 1  // OK

// 延迟初始化
lateinit var lateString: String
val lazyValue: String by lazy {
    "延迟计算"
}

// 常量
const val MAX_SIZE = 100
Python
python 复制代码
# Python 没有val/var区分,靠约定
# 不可变约定:全大写或文档说明
MAX_SIZE = 100  # 约定为常量

# 变量声明(无需类型注解)
name: str = "Python"  # 类型注解可选
inferred = "类型推断"  # 运行时确定类型

# 可变变量(默认都可变)
count: int = 0
count = 1  # OK

# 延迟初始化
class Example:
    def __init__(self):
        self._lazy_value = None

    @property
    def lazy_value(self):
        if self._lazy_value is None:
            self._lazy_value = "延迟计算"
        return self._lazy_value
核心差异
特性 Kotlin Python
不可变性 val 编译时强制 约定,无强制
类型注解 必须或推断 完全可选
类型检查 编译时 运行时
延迟初始化 lateinit / by lazy @property__getattr__

1.2 函数定义

Kotlin
kotlin 复制代码
// 普通函数
fun add(a: Int, b: Int): Int {
    return a + b
}

// 单表达式函数
fun addSimple(a: Int, b: Int) = a + b

// 默认参数
fun greet(name: String, greeting: String = "Hello") =
    "$greeting, $name!"

// 命名参数
greet(name = "World", greeting = "Hi")

// 可变参数
fun sum(vararg numbers: Int): Int =
    numbers.sum()

// 扩展函数
fun String.shout() = this.uppercase() + "!"

"hello".shout()  // "HELLO!"

// 高阶函数
fun operate(a: Int, b: Int, op: (Int, Int) -> Int): Int =
    op(a, b)

operate(1, 2) { x, y -> x * y }  // 2

// Lambda 表达式
val square: (Int) -> Int = { x -> x * x }
val square2 = { x: Int -> x * x }

// 函数类型别名
typealias IntOp = (Int, Int) -> Int
Python
python 复制代码
from typing import Callable, TypeAlias

# 普通函数
def add(a: int, b: int) -> int:
    return a + b

# 单表达式函数(lambda 有限制)
add_simple = lambda a, b: a + b  # 不推荐复杂逻辑

# 默认参数
def greet(name: str, greeting: str = "Hello") -> str:
    return f"{greeting}, {name}!"

# 命名参数
greet(name="World", greeting="Hi")

# 可变参数
def sum_numbers(*numbers: int) -> int:
    return sum(numbers)

sum_numbers(1, 2, 3)  # 6

# 扩展函数(Python 无原生支持,用猴子补丁或独立函数)
def shout(s: str) -> str:
    return s.upper() + "!"

shout("hello")  # "HELLO!"

# 高阶函数
from typing import Callable

def operate(a: int, b: int, op: Callable[[int, int], int]) -> int:
    return op(a, b)

operate(1, 2, lambda x, y: x * y)  # 2

# Lambda 表达式(只能是单表达式)
square: Callable[[int], int] = lambda x: x * x

# 函数类型别名
IntOp: TypeAlias = Callable[[int, int], int]
核心差异
特性 Kotlin Python
单表达式函数 fun f() = expr lambda(受限)
默认参数 支持 支持
命名参数 支持 支持
可变参数 vararg *args, **kwargs
扩展函数 原生支持 无(用独立函数)
Lambda 多行支持 仅单表达式

1.3 类与对象

Kotlin
kotlin 复制代码
// 普通类
class Person(val name: String, var age: Int) {
    fun greet() = "Hi, I'm $name"
}

// 数据类(自动生成 equals, hashCode, toString, copy)
data class User(val id: Int, val name: String)

// 密封类(受限继承)
sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val message: String) : Result()
}

// 枚举类
enum class Status {
    ACTIVE, INACTIVE, PENDING
}

// 对象声明(单例)
object Database {
    fun connect() = "Connected"
}

// 伴生对象(静态成员)
class Factory {
    companion object {
        fun create() = Factory()
    }
}

// 匿名对象
val listener = object : ClickListener {
    override fun onClick() = println("Clicked")
}

// 接口
interface Drawable {
    fun draw()
    fun description() = "Drawable"  // 默认实现
}
Python
python 复制代码
from dataclasses import dataclass
from enum import Enum, auto
from typing import Protocol, runtime_checkable
import abc

# 普通类
class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def greet(self) -> str:
        return f"Hi, I'm {self.name}"

# 数据类(Python 3.7+)
@dataclass
class User:
    id: int
    name: str
    # 自动生成 __init__, __repr__, __eq__

# 密封类(无原生支持,用 Union 模拟)
from typing import Union

class Success:
    def __init__(self, data: str):
        self.data = data

class Error:
    def __init__(self, message: str):
        self.message = message

Result = Union[Success, Error]

# 枚举类
class Status(Enum):
    ACTIVE = auto()
    INACTIVE = auto()
    PENDING = auto()

# 单例模式(模块级变量或 __new__)
class Database:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def connect(self) -> str:
        return "Connected"

# 静态方法/类方法
class Factory:
    @staticmethod
    def create() -> 'Factory':
        return Factory()

    @classmethod
    def from_config(cls, config: dict) -> 'Factory':
        return cls()

# 接口(Protocol 或 ABC)
@runtime_checkable
class Drawable(Protocol):
    def draw(self) -> None: ...

# 或抽象基类
class DrawableABC(abc.ABC):
    @abc.abstractmethod
    def draw(self) -> None:
        pass
核心差异
特性 Kotlin Python
构造函数 主构造函数 + init __init__
数据类 data class @dataclass
密封类 sealed class Union + 模式匹配
单例 object 模块级变量或 __new__
静态成员 companion object @staticmethod / @classmethod
接口 interface ProtocolABC
访问控制 public/private/protected 约定 _ / __

1.4 泛型系统

Kotlin
kotlin 复制代码
// 泛型类
class Box<T>(val value: T)

// 泛型函数
fun <T> singletonList(item: T): List<T> = listOf(item)

// 类型约束
fun <T : Comparable<T>> max(a: T, b: T): T =
    if (a > b) a else b

// 多重约束
fun <T> process(item: T) where T : CharSequence, T : Comparable<T> {
    // ...
}

// 型变 - 协变 (out)
interface Producer<out T> {
    fun produce(): T
}
// Producer<String> 是 Producer<Any> 的子类型

// 型变 - 逆变 (in)
interface Consumer<in T> {
    fun consume(item: T)
}
// Consumer<Any> 是 Consumer<String> 的子类型

// 星投影
fun printList(list: List<*>) {
    list.forEach { println(it) }  // it 是 Any?
}

// 具体化泛型
inline fun <reified T> isType(value: Any): Boolean =
    value is T

isType<String>("hello")  // true
Python
python 复制代码
from typing import TypeVar, Generic, List, Any, Callable
from typing import Protocol, runtime_checkable

# 泛型类
T = TypeVar('T')

class Box(Generic[T]):
    def __init__(self, value: T):
        self.value = value

# 泛型函数
def singleton_list(item: T) -> List[T]:
    return [item]

# 类型约束 (bound)
TComparable = TypeVar('TComparable', bound='Comparable')

class Comparable(Protocol):
    def __lt__(self, other: Any) -> bool: ...

def max_val(a: TComparable, b: TComparable) -> TComparable:
    return a if a > b else b

# 多重约束(Python 3.12+ 或 Protocol 组合)
class CharSequenceComparable(Protocol):
    def __len__(self) -> int: ...
    def __lt__(self, other: Any) -> bool: ...

# 协变 (covariant)
T_co = TypeVar('T_co', covariant=True)

class Producer(Protocol[T_co]):
    def produce(self) -> T_co: ...

# 逆变 (contravariant)
T_contra = TypeVar('T_contra', contravariant=True)

class Consumer(Protocol[T_contra]):
    def consume(self, item: T_contra) -> None: ...

# Any 类似星投影
def print_list(lst: List[Any]) -> None:
    for item in lst:
        print(item)

# 具体化(Python 运行时可获取类型)
def is_type(value: Any, expected_type: type) -> bool:
    return isinstance(value, expected_type)

is_type("hello", str)  # True
核心差异
特性 Kotlin Python
泛型声明 <T> TypeVar('T')T = TypeVar('T')
类型约束 <T : UpperBound> bound=...
协变 out T covariant=True
逆变 in T contravariant=True
星投影 * Any
具体化 reified 运行时天然支持
类型擦除 JVM擦除 运行时保留

1.5 类型系统进阶

Kotlin
kotlin 复制代码
// 类型别名
typealias StringList = List<String>
typealias Predicate<T> = (T) -> Boolean

// 内联类 / 值类
@JvmInline
value class Password(val value: String)

// 交叉类型
fun <T> both(a: T) where T : CharSequence, T : Appendable

// 可空类型
val nullable: String? = null
val nonNull: String = "required"

// 智能类型转换
fun process(obj: Any) {
    if (obj is String) {
        println(obj.length)  // 自动转换为 String
    }
}

// 密封接口
sealed interface Node {
    data class Leaf(val value: Int) : Node
    data class Branch(val left: Node, val right: Node) : Node
}
Python
python 复制代码
from typing import TypeAlias, Union, Optional, Any
from typing import Protocol, runtime_checkable

# 类型别名 (Python 3.12+)
type StringList = list[str]
type Predicate[T] = Callable[[T], bool]

# 或旧语法
StringList2: TypeAlias = list[str]

# NewType(类似值类)
from typing import NewType
Password = NewType('Password', str)

# 交叉类型(Protocol 组合)
class CharSequence(Protocol):
    def __len__(self) -> int: ...

class Appendable(Protocol):
    def append(self, s: str) -> None: ...

class Both(CharSequence, Appendable, Protocol):
    pass

# 可空类型
nullable: Optional[str] = None  # 等价于 str | None
non_null: str = "required"

# 类型检查(运行时)
def process(obj: Any) -> None:
    if isinstance(obj, str):
        print(len(obj))  # 类型已知

# Union 类型 (Python 3.10+)
from typing import Union
Result = Union[int, str]  # 或 int | str

# 字面量类型
from typing import Literal
Status = Literal["active", "inactive"]
核心差异
特性 Kotlin Python
类型别名 typealias TypeAliastype
值类型 value class NewType(弱)
可空类型 T? Optional[T] 或 `T
智能转换 自动 isinstance
联合类型 密封类 Union / Literal
类型检查 编译时 运行时 + mypy

1.6 空安全处理

Kotlin
kotlin 复制代码
val nullable: String? = null

// 安全调用
val length: Int? = nullable?.length

// Elvis 运算符
val length2: Int = nullable?.length ?: 0

// 非空断言(可能抛 NPE)
val length3: Int = nullable!!.length  // 危险!

// 安全转换
val number: Int? = obj as? Int

// let 链式调用
nullable?.let {
    println(it.length)
}

// takeIf / takeUnless
val result = nullable?.takeIf { it.isNotEmpty() }

// requireNotNull
val required: String = requireNotNull(nullable) { "不能为空" }
Python
python 复制代码
from typing import Optional

nullable: Optional[str] = None

# 安全访问(无语法糖,需显式检查)
length: Optional[int] = nullable.length if nullable else None

# 默认值
length2: int = len(nullable) if nullable else 0

# 非空断言(无内置,自定义)
def require_non_null(value: Optional[T], msg: str = "不能为空") -> T:
    if value is None:
        raise ValueError(msg)
    return value

# 安全转换
def safe_int(obj: Any) -> Optional[int]:
    try:
        return int(obj)
    except (ValueError, TypeError):
        return None

# 链式调用(无 let,用 if)
if nullable is not None:
    print(len(nullable))

# 条件赋值
result = nullable if nullable and len(nullable) > 0 else None

# requireNotNull 等价
required: str = require_non_null(nullable, "不能为空")
核心差异
特性 Kotlin Python 说明
可空声明 T? Optional[T] Kotlin 编译时强制
安全调用 ?. 无语法糖 Python 需显式检查
默认值 ?: or / if else Python or 有陷阱
非空断言 !! Python 直接抛异常
安全转换 as? try/except Python 需异常处理

1.7 集合操作

Kotlin
kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5)

// 不可变 vs 可变
val immutable: List<Int> = listOf(1, 2, 3)
val mutable: MutableList<Int> = mutableListOf(1, 2, 3)

// 序列(惰性求值)
val result = numbers
    .asSequence()
    .filter { it > 2 }
    .map { it * 2 }
    .take(2)
    .toList()  // [6, 8]

// 常用操作
numbers.filter { it % 2 == 0 }  // [2, 4]
numbers.map { it * 2 }          // [2, 4, 6, 8, 10]
numbers.flatMap { listOf(it, it) }  // [1,1,2,2,3,3,4,4,5,5]
numbers.reduce { acc, n -> acc + n }  // 15
numbers.fold(0) { acc, n -> acc + n }  // 15
numbers.groupBy { it % 2 }  // {1=[1,3,5], 0=[2,4]}
numbers.associateBy { "key$it" }  // Map
numbers.partition { it > 2 }  // ([3,4,5], [1,2])
numbers.chunked(2)  // [[1,2], [3,4], [5]]
numbers.windowed(3)  // [[1,2,3], [2,3,4], [3,4,5]]

// Set 操作
val set1 = setOf(1, 2, 3)
val set2 = setOf(2, 3, 4)
set1 union set2      // {1, 2, 3, 4}
set1 intersect set2  // {2, 3}
set1 subtract set2   // {1}

// Map 操作
val map = mapOf("a" to 1, "b" to 2)
map.mapKeys { it.key.uppercase() }
map.mapValues { it.value * 2 }
Python
python 复制代码
from typing import List, Dict, Set, Optional
from itertools import islice, chain

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

# 不可变 vs 可变(Python 无编译时区分)
immutable: tuple[int, ...] = (1, 2, 3)
mutable: list[int] = [1, 2, 3]

# 生成器(惰性求值)
def process_sequence(nums):
    for n in nums:
        if n > 2:
            yield n * 2

result = list(islice(process_sequence(numbers), 2))  # [6, 8]

# 或使用生成器表达式
result2 = list(islice((n * 2 for n in numbers if n > 2), 2))

# 常用操作
list(filter(lambda x: x % 2 == 0, numbers))  # [2, 4]
[x * 2 for x in numbers]  # [2, 4, 6, 8, 10] - 列表推导式
[x for n in numbers for x in (n, n)]  # flatMap 等价
# 或
list(chain.from_iterable([[n, n] for n in numbers]))

from functools import reduce
reduce(lambda acc, n: acc + n, numbers, 0)  # 15

# groupBy
from itertools import groupby
from operator import itemgetter

sorted_nums = sorted(numbers, key=lambda x: x % 2)
grouped = {k: list(g) for k, g in groupby(sorted_nums, key=lambda x: x % 2)}

# partition
def partition(pred, iterable):
    true, false = [], []
    for x in iterable:
        (true if pred(x) else false).append(x)
    return true, false

greater, lesser = partition(lambda x: x > 2, numbers)

# chunked
def chunked(iterable, n):
    return [iterable[i:i+n] for i in range(0, len(iterable), n)]

chunked(numbers, 2)  # [[1,2], [3,4], [5]]

# windowed
def windowed(iterable, n):
    return [iterable[i:i+n] for i in range(len(iterable) - n + 1)]

windowed(numbers, 3)  # [[1,2,3], [2,3,4], [3,4,5]]

# Set 操作
set1 = {1, 2, 3}
set2 = {2, 3, 4}
set1 | set2  # union {1, 2, 3, 4}
set1 & set2  # intersect {2, 3}
set1 - set2  # difference {1}

# Map 操作
d = {"a": 1, "b": 2}
{k.upper(): v for k, v in d.items()}  # mapKeys
{k: v * 2 for k, v in d.items()}  # mapValues
核心差异

| 特性 | Kotlin | Python |
|-------|----------------|-----------------------|--------|
| 不可变集合 | List / Set | tuple / frozenset |
| 惰性求值 | Sequence | 生成器 / itertools |
| 链式调用 | 流畅 API | 需嵌套或中间变量 |
| 推导式 | 无 | [] / {} 推导式 |
| 集合运算 | 方法名 | 运算符 ` | & -` |


1.8 扩展函数与运算符重载

Kotlin
kotlin 复制代码
// 扩展函数
fun String.addExclamation() = this + "!"
"hello".addExclamation()  // "hello!"

// 扩展属性
val String.hasContent: Boolean
    get() = this.isNotEmpty()

// 运算符重载
data class Point(val x: Int, val y: Int) {
    operator fun plus(other: Point) =
        Point(x + other.x, y + other.y)

    operator fun times(scalar: Int) =
        Point(x * scalar, y * scalar)

    operator fun get(index: Int) =
        when (index) {
            0 -> x
            1 -> y
            else -> throw IndexOutOfBoundsException()
        }
}

val p1 = Point(1, 2)
val p2 = Point(3, 4)
p1 + p2  // Point(4, 6)
p1 * 2   // Point(2, 4)
p1[0]    // 1

// 解构声明
val (x, y) = p1

// in 运算符
operator fun Point.contains(point: Point) =
    point.x in 0..x && point.y in 0..y

// 范围运算符
operator fun Point.rangeTo(other: Point) =
    PointRange(this, other)

// 调用运算符
operator fun Point.invoke(action: (Int, Int) -> Unit) =
    action(x, y)
Python
python 复制代码
# 扩展函数(无原生支持,用独立函数)
def add_exclamation(s: str) -> str:
    return s + "!"

add_exclamation("hello")  # "hello!"

# 或猴子补丁(不推荐)
# str.add_exclamation = lambda self: self + "!"

# 运算符重载
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)

    def __mul__(self, scalar: int) -> 'Point':
        return Point(self.x * scalar, self.y * scalar)

    def __getitem__(self, index: int) -> int:
        if index == 0:
            return self.x
        elif index == 1:
            return self.y
        raise IndexError("Point index out of range")

    def __contains__(self, point: 'Point') -> bool:
        return 0 <= point.x <= self.x and 0 <= point.y <= self.y

    def __call__(self, action):
        return action(self.x, self.y)

p1 = Point(1, 2)
p2 = Point(3, 4)
p1 + p2  # Point(x=4, y=6)
p1 * 2   # Point(x=2, y=4)
p1[0]    # 1

# 解构(通过元组协议)
def __iter__(self):
    yield self.x
    yield self.y

x, y = p1  # 需要添加 __iter__ 方法

# 运算符对照表
"""
Kotlin operator    Python method
+ (plus)           __add__
- (minus)          __sub__
* (times)          __mul__
/ (div)            __truediv__
% (mod)            __mod__
** (无)            __pow__
in (contains)      __contains__
[] (get)           __getitem__
[] = (set)         __setitem__
() (invoke)        __call__
< > <= >=          __lt__, __gt__, __le__, __ge__
== (equals)        __eq__
"""
核心差异
特性 Kotlin Python
扩展函数 原生支持 无(用独立函数)
扩展属性 支持
运算符数量 有限集合 更丰富
解构声明 operator fun componentN() __iter____getitem__
调用运算符 operator fun invoke() __call__

2. 并发模型对照

2.1 协程 vs asyncio

Kotlin 协程
kotlin 复制代码
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

// 启动协程
fun main() = runBlocking {
    // launch: 不返回结果
    launch {
        delay(1000)
        println("World!")
    }
    println("Hello")

    // async: 返回结果
    val deferred = async {
        delay(500)
        42
    }
    println(deferred.await())  // 42
}

// 协程作用域
class ViewModel {
    private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())

    fun fetchData() {
        scope.launch {
            try {
                val data = withContext(Dispatchers.IO) {
                    apiCall()
                }
                updateUI(data)
            } catch (e: Exception) {
                handleError(e)
            }
        }
    }

    fun cleanup() {
        scope.cancel()
    }
}

// Flow(冷流)
fun numbers(): Flow<Int> = flow {
    for (i in 1..10) {
        delay(100)
        emit(i)
    }
}

// SharedFlow / StateFlow(热流)
val sharedFlow = MutableSharedFlow<Int>()
val stateFlow = MutableStateFlow(0)

// 结构化并发
suspend fun parallelTasks(): List<String> = coroutineScope {
    val deferred1 = async { task1() }
    val deferred2 = async { task2() }
    listOf(deferred1.await(), deferred2.await())
}
Python asyncio
python 复制代码
import asyncio
from typing import AsyncGenerator, List
from dataclasses import dataclass

# 启动协程
async def main():
    # create_task: 不等待结果
    task1 = asyncio.create_task(say_world())

    print("Hello")
    await task1

    # gather: 并发执行多个协程
    results = await asyncio.gather(
        task1(),
        task2(),
        return_exceptions=True  # 异常处理
    )

    # 返回结果
    result = await compute_42()
    print(result)

async def say_world():
    await asyncio.sleep(1)
    print("World!")

async def compute_42() -> int:
    await asyncio.sleep(0.5)
    return 42

# 运行
asyncio.run(main())

# 异步生成器(类似 Flow)
async def numbers() -> AsyncGenerator[int, None]:
    for i in range(1, 11):
        await asyncio.sleep(0.1)
        yield i

# 消费异步生成器
async def consume():
    async for num in numbers():
        print(num)

# 或
async def consume_all():
    result = [num async for num in numbers()]

# 结构化并发(Python 3.11+ TaskGroup)
async def parallel_tasks() -> List[str]:
    async with asyncio.TaskGroup() as tg:
        task1 = tg.create_task(do_task1())
        task2 = tg.create_task(do_task2())
    return [task1.result(), task2.result()]

# 超时控制
async def with_timeout():
    try:
        async with asyncio.timeout(5.0):
            await long_operation()
    except TimeoutError:
        print("Timeout!")

# 同步原语
class AsyncQueue:
    def __init__(self):
        self.queue = asyncio.Queue()

    async def producer(self):
        for i in range(10):
            await self.queue.put(i)
            await asyncio.sleep(0.1)

    async def consumer(self):
        while True:
            item = await self.queue.get()
            print(f"Got: {item}")
            self.queue.task_done()
核心差异
特性 Kotlin Python
协程启动 launch / async create_task / gather
挂起函数 suspend async def
挂起点 delay() await asyncio.sleep()
作用域 CoroutineScope TaskGroup (3.11+)
Flow AsyncGenerator
调度器 Dispatchers 无内置(用 run_in_executor
取消 job.cancel() task.cancel()
结构化并发 原生支持 3.11+ 支持

2.2 线程模型

Kotlin
kotlin 复制代码
import kotlinx.coroutines.*
import java.util.concurrent.Executors

// 线程池调度器
val ioDispatcher = Dispatchers.IO
val cpuDispatcher = Dispatchers.Default
val customDispatcher = Executors.newFixedThreadPool(4).asCoroutineDispatcher()

// 切换上下文
suspend fun fetchData(): Data = withContext(Dispatchers.IO) {
    apiCall()
}

// 并行分解
suspend fun loadAll(): AllData = coroutineScope {
    val user = async { loadUser() }
    val posts = async { loadPosts() }
    val friends = async { loadFriends() }
    AllData(user.await(), posts.await(), friends.await())
}

// 限制并发
suspend fun limitedConcurrency() {
    val semaphore = Semaphore(3)
    List(10) { index ->
        async {
            semaphore.acquire()
            try {
                process(index)
            } finally {
                semaphore.release()
            }
        }
    }.awaitAll()
}

// 阻塞操作
fun blockingOperation() = runBlocking {
    // 阻塞当前线程
}
Python
python 复制代码
import asyncio
import threading
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from typing import List
import multiprocessing

# 线程池
def blocking_io():
    import time
    time.sleep(1)
    return "done"

async def run_in_thread():
    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(None, blocking_io)
    return result

# 自定义线程池
executor = ThreadPoolExecutor(max_workers=4)

async def with_custom_executor():
    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(executor, blocking_io)

# 进程池(CPU 密集型)
def cpu_intensive(n):
    return sum(i * i for i in range(n))

async def run_cpu_task():
    loop = asyncio.get_event_loop()
    with ProcessPoolExecutor() as executor:
        result = await loop.run_in_executor(
            executor,
            cpu_intensive,
            10_000_000
        )
    return result

# 并发限制
import asyncio

async def limited_concurrency(tasks: List, limit: int):
    semaphore = asyncio.Semaphore(limit)

    async def limited_task(task):
        async with semaphore:
            return await task

    return await asyncio.gather(*[limited_task(t) for t in tasks])

# 多线程(非协程)
def threading_example():
    results = []
    lock = threading.Lock()

    def worker(n):
        result = n * n
        with lock:
            results.append(result)

    threads = [threading.Thread(target=worker, args=(i,)) for i in range(10)]
    for t in threads:
        t.start()
    for t in threads:
        t.join()

# 多进程(绕过 GIL)
def multiprocessing_example():
    with multiprocessing.Pool(4) as pool:
        results = pool.map(cpu_intensive, [10_000_000] * 4)
    return results
核心差异
特性 Kotlin Python
线程模型 真正多线程 GIL 限制(CPU密集需多进程)
线程池 Dispatchers.IO ThreadPoolExecutor
进程池 无内置 ProcessPoolExecutor
阻塞转非阻塞 withContext run_in_executor
并发限制 Semaphore asyncio.Semaphore

2.3 并发异常处理

Kotlin
kotlin 复制代码
import kotlinx.coroutines.*

// SupervisorJob: 子协程失败不影响其他
val scope = CoroutineScope(SupervisorJob())

scope.launch {
    // 一个失败不影响另一个
    launch { mightFail() }
    launch { otherTask() }
}

// async 异常处理
suspend fun handleErrors() = coroutineScope {
    val deferred = async {
        throw RuntimeException("Failed!")
    }

    try {
        deferred.await()
    } catch (e: Exception) {
        println("Caught: ${e.message}")
    }
}

// CoroutineExceptionHandler
val handler = CoroutineExceptionHandler { _, exception ->
    println("Caught: $exception")
}

scope.launch(handler) {
    throw RuntimeException("Error!")
}

// 结果包装
sealed class Result<out T> {
    data class Success<T>(val value: T) : Result<T>()
    data class Failure(val error: Throwable) : Result<Nothing>()
}

suspend fun <T> safeCall(block: suspend () -> T): Result<T> = try {
    Result.Success(block())
} catch (e: Exception) {
    Result.Failure(e)
}
Python
python 复制代码
import asyncio
from typing import List, Union
from dataclasses import dataclass

# gather 异常处理
async def handle_errors():
    try:
        results = await asyncio.gather(
            might_fail(),
            other_task(),
            return_exceptions=True  # 异常作为结果返回
        )
        for r in results:
            if isinstance(r, Exception):
                print(f"Error: {r}")
            else:
                print(f"Success: {r}")
    except Exception as e:
        print(f"Outer error: {e}")

# TaskGroup 异常处理 (3.11+)
async def task_group_errors():
    try:
        async with asyncio.TaskGroup() as tg:
            tg.create_task(might_fail())
            tg.create_task(other_task())
    except ExceptionGroup as eg:
        for exc in eg.exceptions:
            print(f"Caught: {exc}")

# 结果包装
@dataclass
class Result[T]:
    value: T | None = None
    error: Exception | None = None

    @property
    def is_success(self) -> bool:
        return self.error is None

async def safe_call(coro) -> Result:
    try:
        return Result(value=await coro)
    except Exception as e:
        return Result(error=e)

# 超时 + 异常
async def with_timeout_and_retry(
    coro,
    timeout: float = 5.0,
    retries: int = 3
):
    for attempt in range(retries):
        try:
            async with asyncio.timeout(timeout):
                return await coro
        except TimeoutError:
            if attempt == retries - 1:
                raise
            await asyncio.sleep(1)
核心差异
特性 Kotlin Python
异常隔离 SupervisorJob return_exceptions=True
异常组 ExceptionGroup (3.11+)
全局处理 CoroutineExceptionHandler
取消传播 自动 需显式检查

3. 标准库/生态对照

3.1 包管理

Kotlin (Gradle)
kotlin 复制代码
// build.gradle.kts
plugins {
    kotlin("jvm") version "1.9.20"
    kotlin("plugin.serialization") version "1.9.20"
}

group = "com.example"
version = "1.0.0"

repositories {
    mavenCentral()
    google()
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
    testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
}

// 多平台
kotlin {
    jvm()
    js()
    linuxX64()
}
Python
toml 复制代码
# pyproject.toml (现代标准)
[project]
name = "my-project"
version = "1.0.0"
description = "A Python project"
requires-python = ">=3.10"
dependencies = [
    "httpx>=0.25.0",
    "pydantic>=2.0.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0.0",
    "mypy>=1.0.0",
    "ruff>=0.1.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
bash 复制代码
# 包管理命令对照
# Kotlin (Gradle)          Python (pip/uv)
./gradlew build            pip install -e . / uv pip install -e .
./gradlew test             pytest
./gradlew dependencies     pip list / pip show <package>
./gradlew clean            pip cache purge
                           uv pip compile pyproject.toml -o requirements.txt
核心差异
特性 Kotlin/Gradle Python
构建工具 Gradle 无(pip 只安装)
依赖声明 build.gradle.kts pyproject.toml
锁文件 gradle.lockfile requirements.txt / uv.lock
多平台 原生支持 需条件依赖
发布 Maven Central PyPI

3.2 测试框架

Kotlin
kotlin 复制代码
import org.junit.jupiter.api.*
import org.junit.jupiter.params.*
import org.junit.jupiter.params.provider.*
import io.mockk.*
import kotlinx.coroutines.test.*
import org.amshove.kluent.*

class CalculatorTest {
    private lateinit var calc: Calculator

    @BeforeEach
    fun setup() {
        calc = Calculator()
    }

    @Test
    fun `add should return sum`() {
        calc.add(1, 2) shouldBe 3
    }

    @Test
    fun `divide by zero should throw`() {
        assertThrows<IllegalArgumentException> {
            calc.divide(1, 0)
        }
    }

    @ParameterizedTest
    @CsvSource("1, 2, 3", "2, 3, 5", "0, 0, 0")
    fun `add parameterized`(a: Int, b: Int, expected: Int) {
        calc.add(a, b) shouldBe expected
    }

    @Test
    fun `mock example`() = runTest {
        val mockApi = mockk<Api>()
        every { mockApi.fetch() } returns "data"

        val result = mockApi.fetch()
        result shouldBe "data"

        verify { mockApi.fetch() }
    }

    @Nested
    inner class EdgeCases {
        @Test
        fun `negative numbers`() {
            calc.add(-1, -2) shouldBe -3
        }
    }
}
Python
python 复制代码
import pytest
from pytest_mock import MockerFixture
from unittest.mock import Mock, patch
import asyncio

class TestCalculator:
    @pytest.fixture
    def calc(self):
        return Calculator()

    def test_add(self, calc):
        assert calc.add(1, 2) == 3

    def test_divide_by_zero(self, calc):
        with pytest.raises(ValueError):
            calc.divide(1, 0)

    @pytest.mark.parametrize("a,b,expected", [
        (1, 2, 3),
        (2, 3, 5),
        (0, 0, 0),
    ])
    def test_add_parameterized(self, calc, a, b, expected):
        assert calc.add(a, b) == expected

    def test_mock_example(self, mocker: MockerFixture):
        mock_api = mocker.Mock()
        mock_api.fetch.return_value = "data"

        result = mock_api.fetch()
        assert result == "data"

        mock_api.fetch.assert_called_once()

    class TestEdgeCases:
        @pytest.fixture
        def calc(self):
            return Calculator()

        def test_negative_numbers(self, calc):
            assert calc.add(-1, -2) == -3

    @pytest.mark.asyncio
    async def test_async(self):
        result = await async_function()
        assert result == "expected"

# pytest.ini 配置
"""
[pytest]
asyncio_mode = auto
testpaths = tests
"""
核心差异
特性 Kotlin/JUnit Python/pytest
断言 shouldBe / assertEquals assert
参数化 @ParameterizedTest @pytest.mark.parametrize
Mock MockK unittest.mock / pytest-mock
异步测试 runTest @pytest.mark.asyncio
嵌套测试 @Nested 嵌套类
Fixture @BeforeEach @pytest.fixture

3.3 常用库对照

领域 Kotlin Python
HTTP 客户端 Ktor, OkHttp, Retrofit httpx, requests, aiohttp
JSON 序列化 kotlinx.serialization, Gson orjson, pydantic, msgspec
数据库 Exposed, Ktorm, Room SQLAlchemy, Tortoise ORM, DuckDB
依赖注入 Koin, Dagger, Hilt dependency-injector, python-inject
配置管理 hoplite, konf pydantic-settings, dynaconf
日志 kotlin-logging, Logback structlog, loguru
日期时间 kotlinx-datetime datetime, pendulum, arrow
函数式 Arrow Kt returns, toolz
CLI clikt, kotlinx-cli click, typer, rich
异步 kotlinx-coroutines asyncio, anyio
测试 JUnit5, Kotest, MockK pytest, hypothesis, pytest-mock
类型检查 编译器 mypy, pyright

4. 运行时特性对照

4.1 编译 vs 解释

Kotlin
scss 复制代码
源代码 (.kt)
    ↓ kotlinc
字节码 (.class)
    ↓ JVM
机器码 (JIT编译)
  • 编译时检查:类型错误在编译时发现
  • JIT 优化:HotSpot JIT 运行时优化
  • 启动时间:较慢(JVM 预热)
  • 运行速度:快(JIT 优化后接近原生)
Python
scss 复制代码
源代码 (.py)
    ↓ CPython 编译器
字节码 (.pyc)
    ↓ CPython 虚拟机
机器码 (解释执行)
  • 运行时检查:类型错误在运行时发现
  • 无 JIT:3.13 实验性 JIT(PEP 744)
  • 启动时间:快
  • 运行速度:慢(纯解释)
性能对比示例
python 复制代码
# Python - 简单循环
def sum_loop(n):
    total = 0
    for i in range(n):
        total += i
    return total

# 耗时约 0.1s (n=10_000_000)
kotlin 复制代码
// Kotlin - 简单循环
fun sumLoop(n: Int): Long {
    var total = 0L
    for (i in 0 until n) {
        total += i
    }
    return total
}

// 耗时约 0.01s (n=10_000_000) - 快 10 倍

4.2 内存模型

Kotlin/JVM
复制代码
线程栈          堆
┌─────────┐    ┌──────────────────┐
│局部变量  │    │ 对象实例          │
│方法帧   │───→│ 数组              │
│操作数栈  │    │ 类元数据          │
└─────────┘    └──────────────────┘
  • 对象分配:堆上分配(逃逸分析可栈上分配)
  • 内存布局:对象头 + 实例数据 + 对齐填充
  • 引用类型:强/软/弱/虚引用
Python
复制代码
线程栈          堆
┌─────────┐    ┌──────────────────┐
│局部变量  │    │ PyObject          │
│帧对象   │───→│ 引用计数 = 2      │
│         │    │ 类型指针          │
└─────────┘    └──────────────────┘
  • 对象分配:所有对象堆上分配
  • 内存布局:PyObject 头(引用计数 + 类型指针)+ 实例数据
  • 引用类型:无分级,靠 GC 处理循环引用
内存占用对比
python 复制代码
# Python - int 对象
import sys
sys.getsizeof(42)  # 28 bytes (64-bit)
sys.getsizeof([1, 2, 3])  # 80 bytes + 元素
kotlin 复制代码
// Kotlin/JVM - Integer 对象
// 约 16 bytes 对象头 + 4 bytes 数据 + 填充
// 但 JVM 有 Integer 缓存 (-128 to 127)

4.3 垃圾回收

Kotlin/JVM
  • 算法:分代 GC(G1, ZGC, Shenandoah)
  • 触发:堆满时自动触发
  • 暂停:Stop-the-world(现代 GC 毫秒级)
  • 调优-Xmx, -XX:+UseG1GC, etc.
Python
  • 算法:引用计数 + 循环检测器
  • 触发:引用计数归零立即回收
  • 暂停:循环检测时有短暂暂停
  • 调优gc.disable(), gc.collect()
python 复制代码
import gc

# 手动控制
gc.disable()  # 禁用循环检测
gc.collect()  # 手动触发
gc.get_stats()  # GC 统计

# 循环引用示例
class Node:
    def __init__(self):
        self.ref = None

a = Node()
b = Node()
a.ref = b
b.ref = a  # 循环引用
del a, b   # 引用计数不为 0,需 GC 检测

5. Python 易错代码大全

以下陷阱全部经过实际验证。每个陷阱从Kotlin视角解释"为什么会踩坑"。


5.1 可变默认参数陷阱

Kotlin 开发者最容易犯的错误。Kotlin 中默认参数每次调用都是新实例,Python 不是。

python 复制代码
# ❌ 错误:所有调用共享同一个列表
def append_to(item, target=[]):
    target.append(item)
    return target

print(append_to(1))  # [1]
print(append_to(2))  # [1, 2]  ← 不是 [2]!
print(append_to(3))  # [1, 2, 3]  ← 越来越多
python 复制代码
# ✅ 正确:每次调用创建新列表
def append_to(item, target=None):
    if target is None:
        target = []
    target.append(item)
    return target

print(append_to(1))  # [1]
print(append_to(2))  # [2]
kotlin 复制代码
// Kotlin 没有这个问题:默认参数每次都是新实例
fun appendTo(item: Int, target: MutableList<Int> = mutableListOf()): MutableList<Int> {
    target.add(item)
    return target
}
appendTo(1) // [1]
appendTo(2) // [2]  ← 每次都是新的

根因 :Python 的 def 是执行语句,默认值在函数定义时求值一次,不是每次调用时。


5.2 闭包变量绑定延迟

循环中创建闭包,Kotlin 会正确捕获每次迭代的值,Python 闭包绑定的是变量名而非值。

python 复制代码
# ❌ 错误:所有闭包共享同一个变量 i
funcs = []
for i in range(3):
    funcs.append(lambda: i)

print([f() for f in funcs])  # [2, 2, 2]  ← 全是 2!
python 复制代码
# ✅ 正确:用默认参数立即绑定当前值
funcs = []
for i in range(3):
    funcs.append(lambda i=i: i)  # i=i 在定义时求值

print([f() for f in funcs])  # [0, 1, 2]
kotlin 复制代码
// Kotlin 没有这个问题:lambda 正确捕获每次迭代的值
val funcs = mutableListOf<() -> Int>()
for (i in 0 until 3) {
    funcs.add { i }
}
println(funcs.map { it() })  // [0, 1, 2]

根因 :Python 闭包是晚绑定 (late binding),变量 i 在调用时查找,此时循环已结束。


5.3 or 运算符的假值陷阱

Kotlin 的 ?: 只对 null 生效,Python 的 or 对所有假值生效。

python 复制代码
# ❌ 错误:0 和空字符串被当作"无值"
count = 0
result = count or 42
print(result)  # 42  ← 0 被当成假值!

name = ""
display = name or "Anonymous"
print(display)  # "Anonymous"  ← 空字符串被当成假值!

items = []
total = items or [1, 2, 3]
print(total)  # [1, 2, 3]  ← 空列表被当成假值!
python 复制代码
# ✅ 正确:只在 None 时提供默认值
count = 0
result = count if count is not None else 42
print(result)  # 0  ← 保留了 0

# 或封装工具函数
from typing import Any

def elvis(value: Any, default: Any) -> Any:
    """模拟 Kotlin 的 ?: 运算符,只对 None 生效"""
    return default if value is None else value

print(elvis(0, 42))         # 0
print(elvis("", "default")) # ""
print(elvis(None, 42))      # 42
kotlin 复制代码
// Kotlin 的 ?: 只对 null 生效
val count = 0
val result = count ?: 42  // 0,不是 42

根因 :Python 的 or 返回第一个"真值",而 0, "", [], {}, False 都是假值。


5.4 == vs is 的身份 vs 相等

Kotlin 的 == 调用 equals()=== 才比较引用。Python 的 == 调用 __eq__is 比较身份。

python 复制代码
# ❌ 错误:用 is 比较值
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b)   # True  ← 值相等
print(a is b)   # False ← 不是同一个对象

# ❌ 错误:用 == 比较 None(虽然能工作但不规范)
x = None
print(x == None)  # True(能工作,但不 Pythonic)
python 复制代码
# ✅ 正确:None 比较用 is
x = None
print(x is None)  # True(Pythonic 写法)

# ✅ 正确:值比较用 ==
print(a == b)  # True

# ✅ 正确:需要身份比较时用 is
c = a
print(a is c)  # True
kotlin 复制代码
// Kotlin 的区分
val a = listOf(1, 2, 3)
val b = listOf(1, 2, 3)
a == b   // true  (equals)
a === b  // false (引用)

根因is 比较的是 id()(内存地址),== 比较的是值。只有 None, True, False 应该用 is


5.5 整数缓存与身份比较

Python 缓存了小整数(-5 到 256),导致 is 比较在小整数上"碰巧"成立。

python 复制代码
# ❌ 令人困惑的行为
a = 256
b = 256
print(a is b)  # True  ← 缓存命中

a = 257
b = 257
print(a is b)  # False ← 超出缓存范围!
python 复制代码
# ✅ 正确:永远用 == 比较整数
a = 257
b = 257
print(a == b)  # True  ← 值比较,永远正确
kotlin 复制代码
// Kotlin 没有这个问题:== 始终比较值
val a = 257
val b = 257
a == b  // true
a === b // false(但没人用 === 比较基本类型)

根因 :CPython 实现细节,-5256 的整数对象被缓存复用。永远不要用 is 比较整数


5.6 列表推导式中的变量泄漏(Python 2 遗留)

Python 3 已修复此问题,但了解历史有助于理解 Python 的作用域规则。

python 复制代码
# Python 3 已修复:推导式有自己的作用域
x = "before"
squares = [x for x in range(5)]
print(x)  # "before" ← Python 3 中 x 不被污染

# 但 for 循环仍会泄漏
x = "before"
for x in range(5):
    pass
print(x)  # 4 ← for 循环的变量泄漏到外部!
python 复制代码
# ✅ 正确:for 循环后不需要用到循环变量
for x in range(5):
    process(x)
# x 在这里仍是 4,不要依赖它
kotlin 复制代码
// Kotlin 没有这个问题:for 循环变量不会泄漏
var x = "before"
for (i in 0 until 5) {
    // i 只在循环内可见
}
println(x)  // "before"

根因 :Python 的 for 循环没有独立作用域,循环变量在循环后仍存在。


5.7 self 忘记写

Kotlin 的 this 是隐式的,Python 的 self 必须显式声明。

python 复制代码
# ❌ 错误:忘记写 self,变成局部变量
class User:
    def __init__(self, name, age):
        name = name   # 局部变量赋值,不是实例属性!
        age = age     # 同上!

user = User("Alice", 30)
print(user.name)  # AttributeError: 'User' object has no attribute 'name'
python 复制代码
# ✅ 正确:所有实例属性必须加 self
class User:
    def __init__(self, name, age):
        self.name = name  # 实例属性
        self.age = age    # 实例属性
kotlin 复制代码
// Kotlin 的 this 是隐式的,不会犯这种错
class User(val name: String, val age: Int)

根因 :Python 的方法就是普通函数,第一个参数 self 是调用时自动传入的实例。不加 self. 就是创建局部变量。


5.8 __init__ 返回值陷阱

Kotlin 的构造函数不能有返回值,Python 的 __init__ 也不能,但 Python 不会在定义时报错。

python 复制代码
# ❌ 错误:__init__ 返回值会被忽略
class Config:
    def __init__(self, path):
        self.path = path
        return self.load(path)  # 返回值被静默忽略!

config = Config("config.json")
print(config)  # <Config object>,不是 load() 的返回值
python 复制代码
# ✅ 正确方案1:用类方法替代构造函数
class Config:
    def __init__(self, data: dict):
        self.data = data

    @classmethod
    def from_file(cls, path: str) -> 'Config':
        data = cls._load(path)
        return cls(data)

    @staticmethod
    def _load(path: str) -> dict:
        # 读取文件逻辑
        return {"key": "value"}

config = Config.from_file("config.json")
kotlin 复制代码
// Kotlin 的 companion object 工厂模式
class Config private constructor(val data: Map<String, Any>) {
    companion object {
        fun fromFile(path: String): Config {
            val data = load(path)
            return Config(data)
        }
    }
}

根因__init__ 是初始化方法,不是构造函数。真正的构造函数是 __new__,它负责创建实例。


5.9 字符串拼接性能陷阱

Kotlin 的 StringBuilder 和字符串模板很高效,Python 的 + 拼接在循环中性能极差。

python 复制代码
# ❌ 错误:循环中用 + 拼接字符串(O(n²))
parts = ["hello", "world", "python", "kotlin"]
result = ""
for part in parts:
    result = result + ", " + part  # 每次创建新字符串!
python 复制代码
# ✅ 正确方案1:join(推荐)
result = ", ".join(parts)  # O(n),一次分配

# ✅ 正确方案2:f-string(少量拼接时)
name = "World"
greeting = f"Hello, {name}!"

# ✅ 正确方案3:io.StringIO(大量动态拼接)
import io
buffer = io.StringIO()
for part in parts:
    buffer.write(part)
    buffer.write(", ")
result = buffer.getvalue()
kotlin 复制代码
// Kotlin 的字符串模板天然高效(编译器用 StringBuilder)
val parts = listOf("hello", "world")
val result = parts.joinToString(", ")  // 高效

根因 :Python 字符串是不可变的,+ 每次创建新对象并复制。join() 预计算总长度,一次分配。


5.10 try/except 吞掉 KeyboardInterrupt

Kotlin 的异常层次清晰,Python 的 except Exception 会吞掉 KeyboardInterrupt 以外的所有异常------包括 SystemExit

python 复制代码
# ❌ 错误:裸 except 吞掉所有异常,包括 Ctrl+C
try:
    while True:
        process()
except:  # 捕获一切!包括 KeyboardInterrupt, SystemExit
    pass   # Ctrl+C 无法退出程序!
python 复制代码
# ✅ 正确:只捕获预期的异常
try:
    result = int(user_input)
except ValueError as e:
    print(f"无效输入: {e}")

# ✅ 正确:需要捕获多种异常时明确列出
try:
    data = json.loads(text)
except (ValueError, KeyError) as e:
    print(f"解析失败: {e}")

# ✅ 正确:需要记录未预期异常但不吞掉
try:
    risky_operation()
except Exception as e:
    logger.exception(f"未预期错误: {e}")
    raise  # 重新抛出!
kotlin 复制代码
// Kotlin 的异常层次:只有非致命异常需要捕获
try {
    riskyOperation()
} catch (e: NumberFormatException) {
    println("解析失败: ${e.message}")
}

根因 :Python 的 except:(无参数)捕获所有异常包括 SystemExitKeyboardInterrupt。永远用 except Exception: 或更具体的异常类型。


5.11 *args 捕获生成器耗尽

Kotlin 的 vararg 传入数组不会改变原数组,Python 的 *args 会消耗生成器。

python 复制代码
# ❌ 错误:生成器被消耗后无法再次使用
def consume(*args):
    print(sum(args))

gen = (x for x in range(5))
consume(*gen)  # 10
consume(*gen)  # 0 ← 生成器已耗尽!
python 复制代码
# ✅ 正确:传入列表而非生成器
items = list(range(5))  # 先物化为列表
consume(*items)  # 10
consume(*items)  # 10 ← 列表可重复使用

# ✅ 正确:或使用 itertools.tee 复制生成器
import itertools
gen = (x for x in range(5))
gen1, gen2 = itertools.tee(gen)
consume(*gen1)  # 10
consume(*gen2)  # 10
kotlin 复制代码
// Kotlin 的 vararg 接收数组,不影响原数据
fun consume(vararg args: Int) = args.sum()
val items = intArrayOf(0, 1, 2, 3, 4)
consume(*items)  // 10
consume(*items)  // 10 ← 数组不受影响

根因 :生成器是迭代器,只能遍历一次。*args 展开时会完全消耗生成器。


5.12 @dataclass__hash__ 陷阱

Kotlin 的 data class 自动生成正确的 hashCode(),Python 的 @dataclass 默认设置 __hash__=None

python 复制代码
# ❌ 错误:默认 dataclass 不可哈希
from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int

u1 = User("Alice", 30)
u2 = User("Alice", 30)

user_set = {u1, u2}  # TypeError: unhashable type: 'User'!
user_dict = {u1: "admin"}  # 同样报错!
python 复制代码
# ✅ 正确方案1:frozen=True(不可变,可哈希)
@dataclass(frozen=True)
class User:
    name: str
    age: int

u1 = User("Alice", 30)
user_set = {u1}  # OK

# ✅ 正确方案2:unsafe_hash=True(可变但可哈希,需自行保证不变性)
@dataclass(unsafe_hash=True)
class User:
    name: str
    age: int

u1 = User("Alice", 30)
user_set = {u1}  # OK,但如果修改 u1.age,set 会出问题
kotlin 复制代码
// Kotlin 的 data class 自动生成 hashCode
data class User(val name: String, val age: Int)
val u1 = User("Alice", 30)
val set = setOf(u1)  // OK

根因@dataclass 默认 eq=True,Python 规定 __eq__ 定义后 __hash__ 自动设为 None(防止可变对象放入 set 后被修改导致查找失败)。


5.13 isinstance 与类型的微妙关系

Kotlin 的 is 检查精确类型,Python 的 isinstance 检查继承链。

python 复制代码
# ❌ 可能不符合预期的行为
print(isinstance(True, int))   # True ← bool 是 int 的子类!
print(isinstance(1, bool))     # False
print(isinstance(True, bool))  # True

# 这会导致类型检查出问题
def process(value: int):
    if isinstance(value, bool):  # 需要额外检查
        print("bool, not int!")
        return
    print(f"int: {value}")

process(True)   # 如果不检查 bool,会被当成 int 处理
python 复制代码
# ✅ 正确:需要区分 bool 和 int 时
from typing import Union

def process(value: Union[int, bool]):
    if isinstance(value, bool):
        print(f"bool: {value}")
    elif isinstance(value, int):
        print(f"int: {value}")

# ✅ 正确:精确类型检查用 type()
print(type(True) is bool)   # True
print(type(True) is int)    # False
print(type(1) is int)       # True
kotlin 复制代码
// Kotlin 中 Boolean 和 Int 没有继承关系
val b: Boolean = true
b is Int  // 编译错误!类型不兼容

根因 :Python 中 boolint 的子类(True == 1, False == 0)。这是历史设计决策。


5.14 dict 修改时遍历崩溃

Kotlin 的 MutableMap 遍历时修改会抛 ConcurrentModificationException,Python 也是但错误信息不够直观。

python 复制代码
# ❌ 错误:遍历时修改字典
scores = {"Alice": 90, "Bob": 85, "Charlie": 95}

for name in scores:
    if scores[name] < 90:
        del scores[name]  # RuntimeError: dictionary changed size during iteration!
python 复制代码
# ✅ 正确方案1:遍历副本的键
for name in list(scores.keys()):  # list() 创建副本
    if scores[name] < 90:
        del scores[name]

# ✅ 正确方案2:构建新字典
scores = {name: score for name, score in scores.items() if score >= 90}

# ✅ 正确方案3:先收集要删除的键
to_remove = [name for name, score in scores.items() if score < 90]
for name in to_remove:
    del scores[name]
kotlin 复制代码
// Kotlin 同样不允许
val scores = mutableMapOf("Alice" to 90, "Bob" to 85)
for ((name, _) in scores) {
    if (scores[name]!! < 90) {
        scores.remove(name)  // ConcurrentModificationException
    }
}
// 正确:用 scores.toList() 或 filter
val filtered = scores.filter { it.value >= 90 }

5.15 浅拷贝 vs 深拷贝

Kotlin 的 data classcopy() 是浅拷贝,Python 的 copy() 也是。但 Kotlin 开发者可能期望"拷贝"是深拷贝。

python 复制代码
# ❌ 错误:浅拷贝导致嵌套对象共享
from dataclasses import dataclass, replace

@dataclass
class Address:
    city: str

@dataclass
class Person:
    name: str
    address: Address

original = Person("Alice", Address("Beijing"))
copied = replace(original, name="Bob")  # 浅拷贝

copied.address.city = "Shanghai"
print(original.address.city)  # "Shanghai" ← original 也被改了!
python 复制代码
# ✅ 正确:需要深拷贝时用 copy.deepcopy
import copy

original = Person("Alice", Address("Beijing"))
copied = copy.deepcopy(original)

copied.address.city = "Shanghai"
print(original.address.city)  # "Beijing" ← 不受影响
kotlin 复制代码
// Kotlin 的 copy() 也是浅拷贝
data class Address(var city: String)
data class Person(val name: String, val address: Address)

val original = Person("Alice", Address("Beijing"))
val copied = original.copy(name = "Bob")
copied.address.city = "Shanghai"
println(original.address.city)  // "Shanghai" ← 同样的问题

根因copy() / replace() 只复制顶层字段,嵌套对象仍然是同一个引用。Kotlin 和 Python 行为一致,但都容易忘记。


5.16 boolint 的子类

python 复制代码
# ❌ 令人困惑的算术行为
print(True + True)       # 2
print(True * 10)         # 10
print(sum([True, False, True]))  # 2
print(False == 0)        # True
print(True == 1)         # True

# ❌ 类型标注无法阻止
from typing import List

def count_items(items: List[int]) -> int:
    return sum(items)

count_items([True, False, True])  # 2,不会报类型错误!
python 复制代码
# ✅ 正确:需要区分时显式检查
def count_items(items: List[int]) -> int:
    # 排除 bool
    return sum(item for item in items if not isinstance(item, bool))

# ✅ 正确:严格类型检查
def count_items_strict(items: List[int]) -> int:
    for item in items:
        if isinstance(item, bool):
            raise TypeError(f"Expected int, got bool: {item}")
    return sum(items)
kotlin 复制代码
// Kotlin 中 Boolean 和 Int 完全独立
true + true  // 编译错误
listOf(true, false).sum()  // 编译错误

根因 :Python 历史原因,bool 继承自 intTrue 的值就是 1False 就是 0


5.17 None 的比较陷阱

python 复制代码
# ❌ 错误:用 == 比较可能有歧义
class Tricky:
    def __eq__(self, other):
        return True  # 一切都相等!

t = Tricky()
print(t == None)  # True ← 不应该!
print(t == 42)    # True
print(t == "hi")  # True
python 复制代码
# ✅ 正确:None 检查永远用 is
print(t is None)  # False ← 正确

# ✅ 正确:通用空值检查
def is_empty(value) -> bool:
    return value is None
kotlin 复制代码
// Kotlin 的 == 对 null 是安全的
val t: Any? = Tricky()
t == null  // false(不会调用 Tricky 的 equals)
t === null // false

根因== 调用 __eq__,可以被重载。is 比较身份,无法被重载。None 是单例,is None 永远可靠。


5.18 lambda 在循环中的闭包陷阱

与 5.2 类似,但更常见于回调场景。

python 复制代码
# ❌ 错误:按钮点击都执行最后一个值
buttons = []
for i in range(3):
    button = {"label": f"Button {i}", "action": lambda: print(i)}
    buttons.append(button)

for btn in buttons:
    btn["action"]()
# 输出:
# 2
# 2
# 2  ← 全是 2!
python 复制代码
# ✅ 正确:默认参数捕获当前值
for i in range(3):
    button = {"label": f"Button {i}", "action": lambda i=i: print(i)}
    buttons.append(button)

for btn in buttons:
    btn["action"]()
# 输出:
# 0
# 1
# 2

# ✅ 正确:使用 functools.partial
from functools import partial

def print_value(v):
    print(v)

for i in range(3):
    button = {"label": f"Button {i}", "action": partial(print_value, i)}
    buttons.append(button)
kotlin 复制代码
// Kotlin 捕获的是值(val 是不可变的)
val buttons = mutableListOf<Map<String, Any>>()
for (i in 0 until 3) {
    buttons.add(mapOf("label" to "Button $i", "action" to { println(i) }))
}
buttons.forEach { it["action"]() }  // 0, 1, 2

5.19 multiprocessing 的 lambda 序列化失败

Kotlin 的线程可以直接传 lambda,Python 的 multiprocessing 需要序列化,lambda 不支持。

python 复制代码
# ❌ 错误:lambda 无法被 pickle 序列化
from multiprocessing import Process

def task(n):
    return sum(i * i for i in range(n))

p = Process(target=lambda: task(1000))  # AttributeError: Can't pickle lambda!
p.start()
python 复制代码
# ✅ 正确:使用顶层函数
from multiprocessing import Process

def run_task():
    result = task(1000)
    print(result)

p = Process(target=run_task)
p.start()
p.join()

# ✅ 正确:使用 functools.partial 传参数
from multiprocessing import Process
from functools import partial

p = Process(target=task, args=(1000,))
p.start()
p.join()
kotlin 复制代码
// Kotlin 线程直接支持 lambda
Thread { task(1000) }.start()  // 完全没问题

根因multiprocessing 通过 pickle 序列化对象跨进程传递,pickle 只能序列化模块级函数,不能序列化 lambda 和嵌套函数。


5.20 asyncio 中调用同步阻塞函数

Kotlin 的 withContext 可以自动切换调度器,Python 的 asyncio 中直接调用阻塞函数会冻结事件循环。

python 复制代码
# ❌ 错误:在协程中直接调用阻塞函数
import asyncio
import time

async def fetch_data():
    time.sleep(2)  # ← 阻塞整个事件循环!所有协程都卡住
    return "data"

async def main():
    # 3 个任务"并行",但实际串行,每个 2 秒,总共 6 秒
    results = await asyncio.gather(
        fetch_data(),
        fetch_data(),
        fetch_data()
    )
    return results

asyncio.run(main())  # 耗时 6 秒,不是 2 秒!
python 复制代码
# ✅ 正确:用 run_in_executor 在线程池中运行阻塞函数
import asyncio
import time
from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=4)

async def fetch_data():
    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(executor, time.sleep, 2)
    return "data"

async def main():
    # 真正并行,总共约 2 秒
    results = await asyncio.gather(
        fetch_data(),
        fetch_data(),
        fetch_data()
    )
    return results

asyncio.run(main())  # 耗时约 2 秒
kotlin 复制代码
// Kotlin 切换调度器很简单
suspend fun fetchData(): String = withContext(Dispatchers.IO) {
    Thread.sleep(2000)  // 不阻塞主线程
    "data"
}

// 并行执行
suspend fun main() {
    val results = listOf(
        async { fetchData() },
        async { fetchData() },
        async { fetchData() }
    ).awaitAll()  // 约 2 秒
}

根因asyncio 是单线程事件循环,阻塞调用会冻结整个循环。必须用 run_in_executor 把阻塞操作放到线程池。


6. 快速参考表

语法速查

概念 Kotlin Python
不可变变量 val x = 1 x = 1(约定)
可变变量 var x = 1 x = 1
空类型 String? Optional[str]
安全调用 obj?.method() obj.method() if obj else None
Elvis x ?: default x or default(注意 0/False)
字符串模板 "$name ${expr}" f"{name} {expr}"
多行字符串 """...""" """..."""
原始字符串 r"..."
范围 1..10, 1 until 10 range(1, 11), range(1, 10)
列表 listOf(1, 2, 3) [1, 2, 3]
Map mapOf("a" to 1) {"a": 1}
解构 val (a, b) = pair a, b = tuple
when when (x) { ... } match x: (3.10+)
扩展函数 fun String.f() = ...
运算符重载 operator fun plus() __add__

并发速查

概念 Kotlin Python
挂起函数 suspend fun async def
启动协程 launch { } asyncio.create_task()
异步结果 async { }.await() await coro
延迟 delay(ms) await asyncio.sleep(s)
并发执行 async { } + awaitAll() asyncio.gather()
切换线程 withContext(Dispatchers.IO) run_in_executor()
Flow<T> AsyncGenerator[T]
取消 job.cancel() task.cancel()

类型系统速查

概念 Kotlin Python
泛型 class Box<T> class Box(Generic[T])
协变 out T TypeVar(covariant=True)
逆变 in T TypeVar(contravariant=True)
类型约束 <T : Upper> bound=Upper
联合类型 密封类 Union[A, B] / `A
交叉类型 where T : A, T : B Protocol 组合
类型别名 typealias Name = Type Name: TypeAlias = Type

总结

从 Kotlin 转向 Python,核心思维转变:

  1. 类型系统:编译时 → 运行时,显式 → 隐式
  2. 空安全:语言级 → 约定 + Optional
  3. 并发:协程原生支持 → asyncio 库
  4. 扩展:扩展函数 → 独立函数
  5. 性能:JVM JIT → 解释执行(无 JIT)
  6. 工具链:Gradle 全功能 → pip + pyproject.toml

Python 优势 :简洁、快速原型、丰富生态(AI/ML/数据) Kotlin 优势:类型安全、性能、多平台、工具链成熟

相关推荐
I疯子3 小时前
2026-04-13 打卡第 6 天
开发语言·python
HaiXCoder3 小时前
python从入门到精通-第6章: 元编程 — Python的"超能力"
python
素玥3 小时前
实训7 json文件数据用python导入数据库
数据库·python·json
千枫s3 小时前
做一个电脑版爬虫程序
爬虫·python
大邳草民3 小时前
Python 对象模型与属性访问机制
开发语言·笔记·python
weixin_402486343 小时前
小分子 pdb准化为sdf
python
橘子编程3 小时前
密码学完全指南:从基础到实战
java·python·密码学
蓝色的杯子3 小时前
Python面试30分钟突击掌握-LeetCode2-Strings
python
ZC跨境爬虫3 小时前
海南大学交友平台开发实战 day9(头像上传存入 SQLite+BLOB 存储 + 前后端联调避坑全记录)
前端·数据库·python·sqlite