Python代码中['boo there']来源及输出推导逻辑咨询
问题解析:Python类实例的输出逻辑与列表修改问题
首先,咱们先把你没写完的代码补全(最后一行应该是print(x.get_bar())),完整代码如下:
class A: def __init__(self, a: int, b: [str]): self._foo = a self._bar = b def get_foo(self): return self._foo def get_bar(self): return self._bar def do_that(given: A): x = given.get_foo() x += 10 y = given.get_bar() y[0] += ' there' y = ['cool'] given = A(-10, ['bye']) x = A(1, ['boo']) print(x.get_foo()) print(x.get_bar()) do_that(x) print(x.get_foo()) print(x.get_bar())
接下来咱们一步步拆解代码的执行逻辑和输出:
1. 初始输出阶段
- 当你创建
x = A(1, ['boo'])时,实例x的_foo属性是1,_bar属性是列表['boo']。 - 第一次
print(x.get_foo())→ 直接返回_foo的值,输出1。 - 第一次
print(x.get_bar())→ 直接返回_bar的列表,输出['boo']。
2. do_that(x)函数执行的关键细节
这里的核心是Python中不可变对象和可变对象的传递差异,咱们逐个分析函数里的操作:
x = given.get_foo():given就是实例x,get_foo()返回的是_foo的值1(int是不可变对象)。此时函数里的x是一个局部变量,只是拿到了1的副本,后续x +=10只是把这个局部变量改成了11,完全不会影响实例x的_foo属性。y = given.get_bar():get_bar()返回的是实例x的_bar列表的引用(列表是可变对象)。这意味着函数里的y和实例x的_bar指向同一个列表对象。- 所以
y[0] += ' there'是直接修改了这个共享列表的第一个元素,把'boo'改成了'boo there'。 - 之后
y = ['cool']只是把函数里的局部变量y重新赋值为一个全新的列表,和原来的共享列表没有关系了,所以这一步不会影响实例x的_bar。
- 所以
3. 函数调用后的输出
print(x.get_foo()):实例x的_foo从来没被修改过,所以还是输出1。print(x.get_bar()):因为之前在函数里修改了共享列表的元素,所以现在返回的列表是['boo there']——这就是你疑惑的这个值的来源!
简单总结一下:
- 像int、str这类不可变对象,赋值给变量时是传值副本,修改局部变量不会影响原对象。
- 像list、dict这类可变对象,赋值给变量时是传引用,修改引用指向的对象内容会同步到原对象,除非你给变量重新赋值新的对象。
内容的提问来源于stack exchange,提问作者sparklecoding
相关产品推荐
相关产品推荐

