对Python类的误解:访问和更改实例变量

0 投票
1 回答
46 浏览
提问于 2025-04-13 00:21

我正在尝试修改一个对象的实例变量 var3,这个对象是 Class3 的一个实例。我想通过将这个实例变量 var3 传递给另一个类的方法来进行修改(见下面的代码)。

我在 Class1 的 init 方法中实例化了 Class2 和 Class3,得到了对象 self.class2 和 self.class3。

然后,我把实例变量 self.class3.var3 传给 Class2 中定义的一个方法(change_class3_var),这个方法会在 var3 后面添加一个字符串。

但是,当我去打印实例变量 var3(class1.class3.var3)时,发现这个变量并没有像预期那样改变,它没有被添加内容,仍然只是 "class3"(而不是 "class3 appended by class2")。

我想了解不同的答案,比如:

  1. 为什么这样做不行
  2. 为什么这种代码风格不好,以及你认为实现这种在不同类之间流畅传递和修改实例变量的最佳替代方案是什么

这段代码并不是用于什么重要的事情,我只是想进一步理解。我的想法是使用一个基础类(Class1)将所有类连接在一起,在一个 PyQt 应用中流畅地传递和改变实例变量,使用一系列实例化的类对象。

谢谢!!

class Class1:
    var = "class1"

    def __init__(self):
        self.class2 = Class2()
        self.class3 = Class3()

    def class2_to_class3(self):
        self.class2.change_class3_var(self.class3.var3)


class Class2:
    var2 = "class2"

    def change_class3_var(self, instance_var):
        instance_var += " appended by class2"
        print(instance_var)


class Class3:
    var3 = "class3"


class1 = Class1()

class1.class2_to_class3()

print(class1.class3.var3)

像这样写代码是可以达到预期效果的,但我可能并不总是想使用静态或类方法装饰器(见下文),也就是说,我可能希望在同一个方法中使用实例 self。

class Class1:
    var = "class1"

    def class2_to_class3(self):
        Class2.from_class3(Class3)


class Class2:
    var2 = "class2"

    @staticmethod
    def from_class3(cls):
        cls.var3 += " appended by class2"
        print(cls.var3)
        return


class Class3:
    var3 = "class3"

    def hello(self):
        print("hello from class 3")


class1 = Class1()

class1.class2_to_class3()

print(Class3.var3)

这也可以工作,但我不太喜欢在 Class1 "外部" 实例化类的方式。而且,我也不喜欢如果我在 def from_class3 中请求 VScode 跳转到 var3 的定义,它却找不到 var3 的位置,因为它在寻找 instance.var3,而不是 class3.var3。

class Class1:
    var = "class1"

    def class2_to_class3(self):
        class2.from_class3(class3)


class Class2:
    var2 = "class2"

    def from_class3(self, instance):
        instance.var3 += " appended by class2"


class Class3:
    var3 = "class3"


class1 = Class1()
class2 = Class2()
class3 = Class3()

print(class3.var3)
class1.class2_to_class3()
print(class3.var3)

1 个回答

0

简单来说,字符串是不可变的,这意味着一旦创建就不能更改。在你代码的这一部分:

instance_var += " appended by class2"

你是在给本地变量 instance_var 添加一个字符串。除了字符串,元组也是不可变的(这就是元组和列表的区别)。你的这种尝试只适用于可变对象,比如列表。对于不可变对象,由于你不能直接修改它们,你需要一种方法来更新原始对象中的引用。

至于为什么这样做不好,是因为你把类之间的关系绑得太紧了。这会让类变得不够模块化,也更难维护。你还会让数据流变得模糊,难以追踪数据是在哪里被修改的。好的类设计应该使用封装,也就是说,每个类都应该负责管理自己的状态。

撰写回答