You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中同类型对象作为方法参数传递及实例异常变更原因排查

问题描述

我正在用Python创建一个表示三维点的类(我知道已有相关库可实现,这只是类的练习)。我希望实现一个能将一个点的坐标与另一个点相加的方法,尝试通过将另一个点作为方法参数来实现。编写的代码如下:

class Point:
    crd = [0,0,0]

    def add_vector(self, coord = [], *args) :
        self.crd[0] += coord[0]
        self.crd[1] += coord[1]
        self.crd[2] += coord[2]

    def subtract_point_from_point(self, other) :
        self.crd[0] = self.crd[0] - other.crd[0]
        self.crd[1] = self.crd[1] - other.crd[1]
        self.crd[2] = self.crd[2] - other.crd[2]

测试代码:

a = Point()
b = [2, 2, 4]
a.add_vector(b)

print('Before making c:')
print('a.crd: ' + str(a.crd[0]))
print('a.crd: ' + str(a.crd[1]))
print('a.crd: ' + str(a.crd[2]))

c = Point()
d = [7, 7, 9]
c.add_vector(d)

print('After adding d to c:')
print('a.crd: ' + str(a.crd[0]))
print('a.crd: ' + str(a.crd[1]))
print('a.crd: ' + str(a.crd[2]))

a.subtract_point_from_point(c)

print('After making c: ')
print('a.crd: ' + str(a.crd[0]))
print('a.crd: ' + str(a.crd[1]))
print('a.crd: ' + str(a.crd[2]))

运行结果:

Before making c:
a.crd: 2
a.crd: 2
a.crd: 4
After adding d to c:
a.crd: 9
a.crd: 9
a.crd: 13
After making c:
a.crd: 0
a.crd: 0
a.crd: 0

疑问:

  1. 为什么给实例c添加向量d时,实例a的坐标会发生变化?
  2. 如何在Python中将同类型对象作为方法参数传递?
解答

1. 实例a坐标变化的原因

你定义的crd = [0,0,0]是类属性,不是实例属性。类属性属于整个类,所有该类的实例会共享同一个类属性对象。也就是说,a.crd和c.crd指向的是同一个列表,修改其中一个实例的crd,本质上是修改了这个共享的列表,另一个实例的crd自然会同步变化。

要解决这个问题,需要把crd改为每个实例独有的属性,在类的__init__方法中初始化:

class Point:
    def __init__(self):
        # 每个实例初始化时创建自己的坐标列表
        self.crd = [0, 0, 0]

    # 后续方法逻辑保持不变
    def add_vector(self, coord = [], *args) :
        self.crd[0] += coord[0]
        self.crd[1] += coord[1]
        self.crd[2] += coord[2]

    def subtract_point_from_point(self, other) :
        self.crd[0] = self.crd[0] - other.crd[0]
        self.crd[1] = self.crd[1] - other.crd[1]
        self.crd[2] = self.crd[2] - other.crd[2]

2. 传递同类型对象作为方法参数

你的subtract_point_from_point方法其实已经在接收同类型对象other了,只是之前的类属性问题导致结果不符合预期。修正属性问题后,可以进一步完善相关方法,比如实现点与点相加的功能:

新增一个add_point方法,直接接收另一个Point实例作为参数:

def add_point(self, other_point):
    self.crd[0] += other_point.crd[0]
    self.crd[1] += other_point.crd[1]
    self.crd[2] += other_point.crd[2]

调用时直接传入Point实例即可:

p1 = Point()
p1.crd = [1, 2, 3]
p2 = Point()
p2.crd = [4, 5, 6]
p1.add_point(p2)
print(p1.crd)  # 输出 [5, 7, 9]

另外,你的add_vector方法存在默认参数陷阱——Python中默认参数只会初始化一次,多次调用时如果修改了默认的空列表,后续调用会使用修改后的列表。建议修改为:

def add_vector(self, coord=None, *args):
    if coord is None:
        coord = [0, 0, 0]
    self.crd[0] += coord[0]
    self.crd[1] += coord[1]
    self.crd[2] += coord[2]

内容的提问来源于stack exchange,提问作者Isaiah Blanks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 09:05:22