为什么从方法和外部读取的类变量不同?

时间:2018-08-06 11:55:55

标签: python oop

所以,我创建了一些课程

class Some:
    @classmethod
    def __init__(cls, somevar):
        cls.somevar = somevar

    @classmethod
    def read(cls):
        return cls.somevar

现在我试图在外部设置变量并从类中读取它:

instance = Some([1, 2, 3])
instance.somevar = [4, 5, 6]
print(instance.read())

>>>> [1, 2, 3]

但是在类外部调用相同的命名变量却给了我预期的输出,

print(instance.somevar)
>>>> [4, 5, 6]

我对OOP的误解是什么?

编辑

我的目标是创建Some的多个实例,这些实例将具有自己的值。

4 个答案:

答案 0 :(得分:5)

实际上,您误解了 class变量是什么。当您使用

instance.somevar = [4, 5, 6]

它不会改变您认为的价值。相反,您需要做的是像这样更改实际的类变量,

instance = Some([1, 2, 3])
instance.somevar = [4, 5, 6]
print(instance.read())
instance2 = Some([4, 5, 6])
print(instance.read())

>>>>
[1, 2, 3]
[4, 5, 6]

的确,不要忘记使用@classmethod装饰器,cls实际上是类本身。因此,在您的情况下,cls.somevar将在所有类之间共享。另外,由于装饰了__init__,因此每次实例化该类时都将更改该变量的值,如上面的示例中的经验所示。


请注意,这可能不是您要查找的实现。您可能想像这样使用self

class Some:
    def __init__(self, somevar):
        self.somevar = somevar

    def read(self):
        return self.somevar

instance = Some([1, 2, 3])
print(instance.read())
instance.somevar = [4, 5, 6]
print(instance.read())

>>>>
[1, 2, 3]
[4, 5, 6]

答案 1 :(得分:1)

使用print(instance.somevar)来获取somevar值,但是您可以在函数内部而不是全局范围内对其进行更改

答案 2 :(得分:1)

您可能需要更好地理解类和实例之间的区别。也许以下代码会有所帮助。

class Some():
    classvar = 123

    def __init__ (self, value):
        self.instvar = value

    def read_instvar (self):
        return self.instvar

    def read_classvar (self):
        return self.__class__.classvar

    @classmethod
    def update_classvar(cls, value):
        cls.classvar = value

所以现在我们可以创建几个对象,并查看它们如何相互作用。

>>> first = Some(12)
>>> second = Some(34)
>>> second.update_classvar(456)
>>> first.read_classvar()
456
>>> first.read_instvar()
12
>>> second.read_instvar()
34
>>> second.read_classvar()
456

观察instvar是每个实例的属性;因此first的值不同于second的值。但是请注意,classvar在这些实例之间是如何共享的,因为它们属于同一类,并且class变量是该类的属性,而不是任何一个实例的属性。具体而言,即使我们通过second更改了class变量,该更改在first中也可见。

答案 3 :(得分:0)

它更像是示波器问题。

instance = Some([1, 2, 3])
instance.somevar = [4, 5, 6]
print(instance.read())

>> [1, 2, 3]

Some.somevar = [4, 5, 6]
print(instance.read())

>> [4, 5, 6]

全部基于以下事实:在Python中,可以在实例范围和类范围中使用两个具有相同名称的变量,并且它们具有不同的值。