关于类和对象课后习题的困惑
我在学习类和对象的课程,其中课后作业分别有两道题如下:1.
>>> class C:
... x = []
... def add_x(self, x):
... self.x.append(x)
...
>>> c = C()
>>> d = C()
>>> c.add_x(250)
>>> d.add_x(520)
>>> c.x
2、
>>> class C:
... def __init__(self):
... self.x = []
... def add_x(self, x):
... self.x.append(x)
...
>>> c = C()
>>> d = C()
>>> c.add_x(250)
>>> d.add_x(520)
>>> c.x
我的困惑是第一题中当x为空列表时,c.x的值为何包含250和520两个值,而第二题通过构造函数创建self.x为空列表时,c.x的值为何只包含250一个值?
为何都是空列表,结果却不同?
你好!这是一个非常棒的观察,这正好触及了 Python 中 类属性(class attribute) 和 实例属性(instance attribute) 的核心区别。
让我们来逐题分析:
第一题:x 是类属性(共享的)
class C:
x = []# 这是一个类属性,属于类C本身。所有实例共享这一个列表!
def add_x(self, x):
self.x.append(x)# 这里操作的是共享的类属性列表
过程解析:
1.`x = []` 定义在类内部,但在所有方法之外。它是一个 类属性,只会在类 C 被定义时创建 一次。
2.当你创建 c = C() 和 d = C() 时,它们两个实例并没有自己独立的 x 属性。
3.执行 c.add_x(250) 时,Python 会先在实例 c 中找 x,没找到,于是向上找到类的 x(那个空列表),并向其中添加了 250。
4.执行 d.add_x(520) 时,同样的过程发生。实例 d 也没有自己的 x,于是它操作的也是同一个 类属性 x 列表。所以这个列表现在包含了 。
5.最后访问 c.x,实例 c 还是没有自己的 x,所以它返回的是类属性 x,也就是被两个实例修改过的那个共享列表。
第二题:x 是实例属性(独立的)
class C:
def __init__(self):
self.x = []# 这是一个实例属性。每个实例在创建时都会得到一个全新的、属于自己的空列表。
def add_x(self, x):
self.x.append(x)# 这里操作的是每个实例自己的列表
过程解析:
1.`self.x = []` 定义在 __init__ 方法里。这是一个 实例属性。
2.每次你创建实例,比如 c = C(), __init__ 方法都会执行,为这个 特定的实例 c 创建一个全新的、只属于它的空列表,并赋值给 c.x。
3.同样地,d = C() 也会为实例 d 创建一个全新的、只属于它的空列表,赋值给 d.x。这两个列表互不相干。
4.执行 c.add_x(250),它操作的是 c 自己的列表,变成 。
5.执行 d.add_x(520),它操作的是 d 自己的列表,变成 。这个操作完全不影响 c 的列表。
6.最后访问 c.x,返回的就是实例 c 自己的那个列表,所以只有 。
总结一下关键区别:
[*]第一题 (类属性): 像一个[教室里的公共储物柜]。所有同学(实例)都在往里放东西,大家看到和操作的是同一个柜子里的内容。
[*]第二题 (实例属性): 像每个同学[自己的书包]。每个同学都有一个,里面放自己的东西,互不干扰。
所以,虽然看起来“都是空列表”,但它们的归属和创建时机完全不同,导致了最终结果的差异。理解这一点对掌握面向对象编程至关重要!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 第一个的 x 是 C 的,c 和 d 使用一个列表
第二个的 x 在 init 里,所以每次创建一个实例就会有一个列表,c 和 d 有自己的列表
求最佳
页:
[1]