首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python面试必考:内存管理、is与==的区别及名称绑定原理

Python面试必考:内存管理、is与==的区别及名称绑定原理

作者头像
玄同765
发布2026-01-14 13:41:30
发布2026-01-14 13:41:30
880
举报

引言

Python面试中,is和==的区别、赋值操作的本质常让候选人困惑。为什么1000 is 1000会是False?为什么修改列表会影响其他变量?这些问题背后,是Python内存管理机制的差异。

本文不讲表面答案,而是从CPython的内存模型出发,解释虚拟地址空间如何影响对象存储,is和==如何比较对象身份与值,以及=符号为何是“名称绑定”而非“值赋值”。通过代码和原理分析,我们一步步揭开这些现象的真相。

你将看到:为什么小整数会被缓存,为什么字符串驻留,为什么列表修改会连锁反应。理解这些,代码会更健壮,面试也更从容。


第一部分:Python内存管理基础与虚拟地址空间

1.1 Python对象模型与内存分配

在Python中,所有事物都是对象。无论是整数、字符串、列表还是函数,它们都以对象的形式存在于内存中。CPython(Python最常用的实现)的内存管理基于对象模型,其核心机制如下:

  • 对象结构:每个Python对象在内存中都有固定结构,包含三个关键部分:
    • ob_refcnt:引用计数(用于垃圾回收)
    • ob_type:指向对象类型(如int、list)的指针
    • ob_size:对象大小(用于动态内存分配)
    • 数据区:实际存储对象值(如整数的值、列表的元素指针)

例如,当执行a = 10时:

  1. CPython在堆内存中分配一个int对象的空间
  2. 初始化ob_refcnt=1, ob_type=PyLong_Type, ob_size=1
  3. 将整数值10存入数据区
  4. 创建名称a并绑定到该对象的地址
1.2 虚拟地址空间与Python内存

操作系统为每个进程分配虚拟地址空间(Virtual Address Space),这是操作系统提供的抽象层,使程序无需关心物理内存布局。虚拟地址空间包含多个区域:

  • 代码段(Text Segment):存放可执行指令
  • 数据段(Data Segment):存放全局变量和静态变量
  • 堆(Heap):动态内存分配区域(如malloc/new
  • 栈(Stack):函数调用和局部变量

Python如何利用虚拟地址空间

  • Python进程在启动时,操作系统为其分配虚拟地址空间。
  • CPython的内存分配器(如pymalloc)在堆区域管理对象内存。
  • 所有id(obj)返回的值是对象在虚拟地址空间中的指针(即虚拟地址),而非物理地址。

关键点id(obj)返回的地址是虚拟地址,由操作系统在进程启动时映射。这意味着:

  • 在同一进程中,id(obj)是唯一的。
  • 不同进程中的相同对象(如两个独立Python进程)会有不同的虚拟地址。
1.3 CPython的内存分配策略

CPython使用内存池(Memory Pool)优化小对象分配,避免频繁调用系统API(如malloc)。

  • 小对象缓存(Small Object Cache)
    • 对于小对象(如整数、短字符串),CPython维护多个内存池。
    • 例如:整数缓存池(small_ints)缓存-5到256的整数,这些整数在全局唯一。
    • 字符串驻留(String Interning):短字符串自动驻留,避免重复创建。
  • pymalloc分配器
    • 为小对象(<512字节)提供高效分配。
    • 按大小分组(如8字节、16字节、32字节等),减少碎片。
    • 例如:创建一个列表[1,2,3],CPython从对应大小的内存池分配。

为什么虚拟地址空间重要

  • Python的内存操作(如id())直接操作虚拟地址。
  • 虚拟地址空间的隔离性保证了Python进程的独立性。
  • 内存泄漏或越界操作会影响整个进程,因为它们在同一个虚拟地址空间中。
1.4 内存使用示例:sys.getsizeof

通过sys.getsizeof可以查看对象在内存中的大小(不包括引用计数等额外开销):

代码语言:javascript
复制
import sys

a = 10
print(sys.getsizeof(a))  # 输出28(在64位系统上)

b = [1, 2, 3]
print(sys.getsizeof(b))  # 输出64(列表对象本身大小)
print(sys.getsizeof(b[0]))  # 输出28(整数对象大小)

输出解释

  • 整数对象:28字节(包含引用计数、类型指针、值等)。
  • 列表对象:64字节(包含引用计数、类型指针、大小、指针数组)。
  • 列表元素:每个元素是整数对象(28字节),但列表本身存储的是指向这些对象的指针(8字节/指针)。

关键洞察:列表的内存大小由其存储的指针数量决定,而非实际元素大小。这解释了为什么[1,2,3]的内存大小与[1000000, 2000000, 3000000]相同。

1.5 垃圾回收与引用计数

Python使用引用计数作为主要垃圾回收机制:

  • 每个对象维护ob_refcnt,记录有多少引用指向它。
  • 当引用计数归零时,对象立即被回收。

虚拟地址空间的影响

  • 垃圾回收操作在虚拟地址空间内进行,通过遍历引用链。
  • 例如:当a = [1,2]时,列表对象的引用计数为1;当b = a时,引用计数变为2。

常见误解

  • “Python没有垃圾回收”:错误。Python有垃圾回收,但主要依赖引用计数(辅助机制如标记清除处理循环引用)。
  • “内存泄漏只发生在循环引用”:不全面。任何未释放的引用都会导致内存泄漏。
1.6 虚拟地址空间与面试题关联

在面试中,虚拟地址空间的概念常被用于解释以下现象:

  • 为什么a = 1; b = 1a is b可能为True?
    • 答:因为小整数在CPython中缓存,ab绑定到同一个虚拟地址。
  • 为什么a = [1,2]; b = a后修改a会影响b
    • 答:ab绑定到同一个列表对象的虚拟地址,修改的是同一块内存。

总结第一部分:Python内存管理依赖于操作系统提供的虚拟地址空间。CPython通过对象模型、内存池和引用计数实现高效内存分配。理解虚拟地址空间是理解is/==和名称绑定的前提。


第二部分:is与==的深度解析

2.1 语法与本质区别

操作符

比较内容

实现原理

适用场景

is

对象身份(地址)

比较id(a) == id(b)

检查单例(None, True, False)

==

对象值

调用a.__eq__(b)或b.__eq__(a)

比较内容等价性

关键区别

  • is:比较内存地址(虚拟地址)。
  • ==:比较对象值(通过__eq__方法)。
2.2 is与==的底层实现

is操作符

在CPython中,is被编译为直接比较id(a)id(b)

源码逻辑(Objects/object.c):

代码语言:javascript
复制
static PyObject *
is_impl(PyObject *a, PyObject *b)
{
    return a == b ? Py_True : Py_False;
}

==操作符

__eq__方法实现,可被重写。

源码逻辑(Objects/object.c):

代码语言:javascript
复制
static PyObject *
richcompare(PyObject *a, PyObject *b, int op)
{
    PyObject *result;
    if (op == Py_EQ) {
        result = PyObject_RichCompare(a, b, Py_EQ);
    }
    // ... 其他操作符
    return result;
}
2.3 整数比较:is与==的陷阱

案例1:小整数缓存

代码语言:javascript
复制
a = 10
b = 10
print(a is b)  # True (CPython缓存-5~256)
print(a == b)  # True

为什么?CPython在启动时预分配-5到256的整数对象,ab绑定到同一虚拟地址。

案例2:大整数

代码语言:javascript
复制
a = 1000
b = 1000
print(a is b)  # False (通常)
print(a == b)  # True

为什么?1000超出缓存范围,CPython为每个赋值创建新对象,ab指向不同虚拟地址。

面试陷阱

  • 面试官问:“为什么1000 is 1000可能为False?”
  • 正确回答:CPython对小整数(-5~256)缓存,但大整数不缓存,每次赋值创建新对象。
2.4 字符串比较:驻留机制

字符串驻留(String Interning)

  • 短字符串(通常长度<20)在编译时或运行时驻留。
  • 驻留字符串在内存中唯一,避免重复创建。

案例1:短字符串

代码语言:javascript
复制
a = "hello"
b = "hello"
print(a is b)  # True (驻留)
print(a == b)  # True

案例2:长字符串

代码语言:javascript
复制
a = "a" * 1000
b = "a" * 1000
print(a is b)  # False (未驻留)
print(a == b)  # True

为什么?CPython对长字符串不驻留,ab指向不同对象。

验证驻留机制

代码语言:javascript
复制
import sys
s1 = "short"
s2 = "short"
print(s1 is s2)  # True

s3 = "a" * 20
s4 = "a" * 20
print(s3 is s4)  # True (CPython默认驻留短字符串)

s5 = "a" * 21
s6 = "a" * 21
print(s5 is s6)  # False (超出默认长度)
2.5 列表、字典等可变对象

可变对象的比较

代码语言:javascript
复制
a = [1, 2, 3]
b = [1, 2, 3]
print(a is b)  # False (不同对象)
print(a == b)  # True (值相等)

为什么ab是两个独立的列表对象,内存地址不同,但内容相同。

修改影响

代码语言:javascript
复制
a = [1, 2, 3]
b = a
a.append(4)
print(b)  # [1, 2, 3, 4] (b也被修改)
print(a is b)  # True

关键点ab绑定到同一对象,is为True,修改影响两者。

2.6 None、True、False的特殊性

单例对象

  • NoneTrueFalse是Python的单例对象,全局唯一。
  • is比较是安全的。

案例

代码语言:javascript
复制
print(None is None)  # True
print(True is True)  # True
print(False is False)  # True

# 但注意:不要用is比较布尔值
print(True == 1)  # True (值比较)
print(True is 1)  # False (身份不同)

面试陷阱

  • 面试官问:“为什么if x is Noneif x == None更好?”
  • 正确回答:is比较身份,更高效且避免__eq__被重写(如自定义类中__eq__可能返回非布尔值)。
2.7 操作符重载的影响

自定义类的__eq__

代码语言:javascript
复制
class MyClass:
    def __init__(self, value):
        self.value = value
    def __eq__(self, other):
        return self.value == other.value

a = MyClass(10)
b = MyClass(10)
print(a == b)  # True (通过__eq__)
print(a is b)  # False (不同对象)

为什么==调用__eq__,而is始终比较地址。

常见错误

  • 误以为==总是等同于is(仅在单例或缓存对象中成立)。
2.8 面试高频问题解析

问题1:为什么"abc" is "abc"为True,但"a" + "b" + "c" is "abc"为False?

代码语言:javascript
复制
s1 = "abc"
s2 = "abc"
print(s1 is s2)  # True (字面量驻留)

s3 = "a" + "b" + "c"
s4 = "abc"
print(s3 is s4)  # False (字符串拼接创建新对象)

原因:字符串字面量在编译时驻留,但运行时拼接("a" + "b" + "c")会创建新对象。

问题2:为什么1.0 is 1为False,但1.0 == 1为True?

代码语言:javascript
复制
print(1.0 is 1)  # False (float vs int)
print(1.0 == 1)  # True (值比较,类型转换)

原因is比较身份,1.01是不同对象;==进行类型转换后比较值。

问题3:在函数默认参数中,为什么def func(a=[])是错误的?

代码语言:javascript
复制
def func(a=[]):
    a.append(1)
    return a

print(func())  # [1]
print(func())  # [1, 1] (错误!)

原因:默认参数在函数定义时绑定,a=[]只创建一次。每次调用func()a绑定到同一列表对象,导致意外修改。

2.9 为什么is比==更高效?
  • is:只需比较两个指针(CPU指令cmp)。
  • ==:可能触发方法调用(__eq__),涉及函数调用开销和逻辑判断。

性能对比

代码语言:javascript
复制
import time

a = [1] * 1000
b = [1] * 1000

start = time.time()
for _ in range(100000):
    a is b  # 0.005s
print("is time:", time.time() - start)

start = time.time()
for _ in range(100000):
    a == b  # 0.05s (慢10倍)
print("== time:", time.time() - start)

结论is是O(1)常数时间,==可能O(n)(如列表比较需遍历元素)。


第三部分:=符号的本质:名称绑定

3.1 误解:赋值 vs 绑定

常见错误观点

  • a = 1将值1赋给变量a。”
  • “变量a存储值1。”

正确观点

  • Python中,=是名称绑定(Name Binding),将名称a绑定到对象1的引用。
  • 没有“变量”,只有名称(name)和对象(object)。
3.2 名称绑定的底层机制

内存视角

  1. 创建对象:1是一个整数对象,存储在堆内存。
  2. 绑定名称:a是一个名称,指向该对象的虚拟地址。

类比:将名称a想象为“指针”(但Python没有指针概念,只有引用)。

关键点

  • 所有变量名都是引用(reference),指向对象。
  • 对象本身在内存中,名称只是“标签”。
3.3 不可变对象与绑定

不可变对象(整数、字符串、元组):

  • 修改对象会创建新对象。
  • 绑定名称后,新绑定不影响旧对象。

示例

代码语言:javascript
复制
a = 10
b = a  # b绑定到a指向的整数对象
a = 20  # a绑定到新对象20,b仍指向10
print(a)  # 20
print(b)  # 10

内存图

代码语言:javascript
复制
对象池: 10 (地址0x7f8d) | 20 (地址0x7f8e)
名称: a -> 0x7f8e | b -> 0x7f8d

为什么?整数是不可变的,a = 20创建新对象并重新绑定a

3.4 可变对象与绑定

可变对象(列表、字典、集合):

  • 修改对象会改变所有绑定的名称。
  • 绑定名称后,修改对象影响所有绑定。

示例

代码语言:javascript
复制
a = [1, 2]
b = a  # b绑定到a指向的列表对象
a.append(3)  # 修改列表对象
print(b)  # [1, 2, 3] (b也被修改)

内存图

代码语言:javascript
复制
对象池: [1,2] (地址0x7f8d)
名称: a -> 0x7f8d | b -> 0x7f8d
修改后: [1,2,3] (地址不变)

为什么?列表是可变的,append在原对象上修改。

3.5 深拷贝与浅拷贝

浅拷贝copy.copy()):

  • 创建新对象,但元素引用相同。
  • 适用于可变对象的嵌套。

深拷贝copy.deepcopy()):

  • 递归创建新对象,完全独立。

绑定与拷贝的区别

代码语言:javascript
复制
import copy

a = [1, [2, 3]]
b = a  # 浅拷贝:b绑定到a
c = copy.copy(a)  # 浅拷贝:c是新列表,但内部列表引用相同
d = copy.deepcopy(a)  # 深拷贝:d是完全独立

a[1][0] = 10
print(b)  # [[10, 3]] (b也被修改)
print(c)  # [[10, 3]] (c也被修改)
print(d)  # [1, [2, 3]] (d未修改)

关键点=是浅绑定,不创建新对象。

3.6 函数参数传递:绑定的延伸

Python的函数参数传递是引用传递(但名称绑定机制决定行为)。

不可变对象

代码语言:javascript
复制
def modify(x):
    x = 20  # 重新绑定x,不影响外部

a = 10
modify(a)
print(a)  # 10 (未修改)

可变对象

代码语言:javascript
复制
def modify(x):
    x.append(3)  # 修改x指向的对象

a = [1, 2]
modify(a)
print(a)  # [1, 2, 3] (被修改)

面试陷阱

  • 面试官问:“为什么修改列表会改变外部变量,但修改整数不会?”
  • 正确回答:因为整数不可变,x = 20重新绑定x;列表可变,x.append(3)修改原对象。
3.7 名称绑定与作用域

局部变量 vs 全局变量

代码语言:javascript
复制
x = 10  # 全局变量

def func():
    x = 20  # 局部变量:创建新绑定,不影响全局x
    print(x)

func()
print(x)  # 10 (全局x未变)

使用global

代码语言:javascript
复制
x = 10

def func():
    global x
    x = 20  # 修改全局绑定

func()
print(x)  # 20

为什么global声明使局部名称绑定到全局作用域。

3.8 名称绑定的常见错误

错误1:误以为a = b复制了对象

代码语言:javascript
复制
a = [1, 2]
b = a
b[0] = 10
print(a)  # [10, 2] (意外修改)

正确做法:使用b = a.copy()(浅拷贝)或b = copy.deepcopy(a)(深拷贝)。

错误2:默认参数中的绑定问题

代码语言:javascript
复制
def func(a=[]):
    a.append(1)
    return a

print(func())  # [1]
print(func())  # [1, 1] (错误)

原因a=[]在函数定义时绑定,所有调用共享同一列表。

修复

代码语言:javascript
复制
def func(a=None):
    if a is None:
        a = []
    a.append(1)
    return a

错误3:循环中绑定问题

代码语言:javascript
复制
funcs = []
for i in range(3):
    funcs.append(lambda: i)  # 闭包绑定i的引用

print(funcs[0]())  # 2 (所有函数返回2)

原因lambda绑定到i的引用,循环结束时i=2

修复

代码语言:javascript
复制
funcs = []
for i in range(3):
    funcs.append(lambda i=i: i)  # 默认参数绑定i的值
print(funcs[0]())  # 0
3.9 名称绑定与虚拟地址空间

绑定过程

  1. a = 10:CPython在堆中创建整数对象(虚拟地址0x7f8d)。
  2. 将名称a绑定到该地址(存储在局部作用域字典中)。

内存关系

  • 作用域(如局部函数)是名称到地址的映射
  • id(a)返回名称a绑定对象的虚拟地址。

验证

代码语言:javascript
复制
a = 10
print(id(a))  # 140733027828000 (虚拟地址)

b = a
print(id(b))  # 140733027828000 (相同地址)
3.10 面试高频问题解析

问题1:为什么a = [1,2]; b = a; a = [3,4]b[1,2]

  • 答案a = [1,2]a绑定到列表[1,2];b = ab绑定到同一列表;a = [3,4]a重新绑定到新列表[3,4],b仍绑定原列表。

问题2:如何安全地复制列表?

  • 答案:使用list.copy()(浅拷贝)或copy.deepcopy()(深拷贝)。

问题3:为什么a = 1; b = a; a += 1b是1?

  • 答案a += 1等价于a = a + 1,创建新整数对象并重新绑定ab仍指向原对象。

问题4:在类方法中,self.x = 1x = 1的区别?

  • 答案self.x = 1x绑定到实例属性(self.__dict__);x = 1是局部变量,不影响实例。

第四部分:综合案例分析

4.1 面试题:字符串驻留与is

题目

代码语言:javascript
复制
s1 = "hello world"
s2 = "hello world"
print(s1 is s2)  # ?

s3 = "hello" + " world"
s4 = "hello world"
print(s3 is s4)  # ?

分析

  1. s1s2是字符串字面量,CPython在编译时驻留,is为True。
  2. s3是运行时拼接,创建新字符串,is为False。

面试回答

“字符串字面量在编译时驻留,因此s1s2绑定到同一对象,is为True。但s3是运行时拼接("hello" + " world"),CPython不会驻留,因此s3s4指向不同对象,is为False。==比较值,两者均为"hello world",结果为True。”

4.2 面试题:列表与is

题目

代码语言:javascript
复制
a = [1, 2, 3]
b = a
c = a[:]
print(a is b)  # ?
print(a is c)  # ?

分析

  • a is b:True(相同对象)。
  • a is c:False(c是浅拷贝,新列表对象)。

面试回答

b = a是名称绑定,ab指向同一列表对象,因此is为True。c = a[:]是切片复制,创建新列表对象,因此a is c为False。a == c为True,因为值相等。”

4.3 面试题:整数缓存范围

题目

代码语言:javascript
复制
print(256 is 256)  # ?
print(257 is 257)  # ?

分析

  • 256在缓存范围内(-5~256),is为True。
  • 257超出范围,is为False。

面试回答

“CPython对整数-5到256缓存,因此256的is比较为True。257超出缓存,每次赋值创建新对象,is为False。这解释了为什么面试中常问大整数的is行为。”

4.4 面试题:函数默认参数

题目

代码语言:javascript
复制
def add_item(item, lst=[]):
    lst.append(item)
    return lst

print(add_item(1))  # [1]
print(add_item(2))  # [1, 2]

分析

  • 默认参数lst=[]在函数定义时绑定,所有调用共享同一列表。

面试回答

“默认参数在函数定义时绑定,lst=[]只创建一次。每次调用add_itemlst绑定到同一列表,导致意外累积。正确做法是使用None作为默认值:def add_item(item, lst=None): if lst is None: lst = []。”

4.5 面试题:闭包与绑定

题目

代码语言:javascript
复制
funcs = []
for i in range(3):
    funcs.append(lambda: i)

print(funcs[0]())  # ?
print(funcs[1]())  # ?
print(funcs[2]())  # ?

分析

  • 所有lambda绑定到循环变量i的引用,循环结束后i=2,因此所有函数返回2。

面试回答

“在Python中,闭包绑定变量的引用,而非值。循环中i被修改,所有lambda捕获i的引用,最终i=2,因此所有函数返回2。修复方法是使用默认参数:funcs.append(lambda i=i: i),将i的值绑定到lambda。”


第五部分:深入思考与扩展

5.1 虚拟地址空间与Python性能

内存访问速度

  • 虚拟地址空间由操作系统管理,CPU高速缓存(Cache)优化访问。
  • 本地对象(同一缓存行)访问更快,跨缓存行更慢。

影响

  • 列表遍历:连续内存访问(缓存友好)。
  • 字典查询:哈希表导致随机内存访问(缓存不友好)。

优化建议

  • 优先使用列表(连续内存)而非字典进行遍历。
  • 避免大列表切片(复制开销)。
5.2 与C语言的对比

概念

Python

C语言

变量

名称绑定到对象

直接存储值(栈/堆)

指针

无显式指针,引用隐式存在

显式指针(int* p)

内存分配

通过CPython内存池管理

malloc/free

作用域

名称绑定到作用域字典

栈帧/全局内存

关键差异

  • Python的“变量”本质是引用,C的“变量”是值存储
  • Python无指针操作,避免了C中的指针错误(如野指针)。
5.3 虚拟地址空间的现代实现

Python 3.8+的改进

  • 使用pymalloc优化小对象分配。
  • 通过sys.getsizeof更准确测量对象大小。
  • 字符串驻留范围可配置(sys.intern)。

示例

代码语言:javascript
复制
import sys
sys.intern("long_string")  # 强制驻留
5.4 为什么面试常考这些概念?
  1. 考察底层理解:区分表面行为与底层机制。
  2. 检测实际经验:避免“纸上谈兵”式开发。
  3. 预测代码质量:理解内存和绑定的开发者更少犯错。
  4. 区分水平:普通开发者知道is==不同,但高级开发者能解释原因。

结论

本文深入解析了Python面试常考的核心概念:内存与虚拟地址空间、is与==的区别、=符号的本质(名称绑定)。通过底层原理分析和代码示例,我们揭示了:

  1. 内存与虚拟地址空间:Python对象在虚拟地址空间中管理,CPython的内存池优化小对象分配。
  2. is与==的区别is比较对象身份(内存地址),==比较值;小整数和短字符串缓存导致is可能为True,但不可依赖。
  3. =符号的本质:Python中=是名称绑定,将名称绑定到对象引用,而非赋值值;不可变对象修改创建新对象,可变对象修改影响所有绑定。

理解这些概念,不仅能让你在面试中从容应对,更能编写出高效、安全的Python代码。避免常见陷阱(如默认参数、列表绑定),掌握名称绑定和内存模型,是Python开发的必经之路。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 第一部分:Python内存管理基础与虚拟地址空间
    • 1.1 Python对象模型与内存分配
    • 1.2 虚拟地址空间与Python内存
    • 1.3 CPython的内存分配策略
    • 1.4 内存使用示例:sys.getsizeof
    • 1.5 垃圾回收与引用计数
    • 1.6 虚拟地址空间与面试题关联
  • 第二部分:is与==的深度解析
    • 2.1 语法与本质区别
    • 2.2 is与==的底层实现
    • 2.3 整数比较:is与==的陷阱
    • 2.4 字符串比较:驻留机制
    • 2.5 列表、字典等可变对象
    • 2.6 None、True、False的特殊性
    • 2.7 操作符重载的影响
    • 2.8 面试高频问题解析
    • 2.9 为什么is比==更高效?
  • 第三部分:=符号的本质:名称绑定
    • 3.1 误解:赋值 vs 绑定
    • 3.2 名称绑定的底层机制
    • 3.3 不可变对象与绑定
    • 3.4 可变对象与绑定
    • 3.5 深拷贝与浅拷贝
    • 3.6 函数参数传递:绑定的延伸
    • 3.7 名称绑定与作用域
    • 3.8 名称绑定的常见错误
    • 3.9 名称绑定与虚拟地址空间
    • 3.10 面试高频问题解析
  • 第四部分:综合案例分析
    • 4.1 面试题:字符串驻留与is
    • 4.2 面试题:列表与is
    • 4.3 面试题:整数缓存范围
    • 4.4 面试题:函数默认参数
    • 4.5 面试题:闭包与绑定
  • 第五部分:深入思考与扩展
    • 5.1 虚拟地址空间与Python性能
    • 5.2 与C语言的对比
    • 5.3 虚拟地址空间的现代实现
    • 5.4 为什么面试常考这些概念?
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档