列为类属性

时间:2019-10-08 14:34:18

标签: python list class

我不完全了解,以下示例中的类属性整数或列表的区别是什么:

class MyClass(object):

    a = [1]
    b = 1

    def __init__(self):
        print(self.a, id(MyClass.a))
        print(self.b, id(MyClass.b))

    def modify(self):
        self.a.append(2)
        print("modfied list attribute:", MyClass.a, id(MyClass.a))
        print("modfied listattribute:", self.a, id(self.a))

        self.b += 1
        print("modfied int attribute:", MyClass.b, id(MyClass.b))
        print("modfied int attribute:", self.b, id(self.b))

x = MyClass()
x.modify()
y = MyClass()

在此示例的输出中,可以看到,如果我在一个实例(x)中更改了列表,则MyClass中的实际属性也会被更改。但是,在一个实例中更改该整数后,该类的整数将保持不变。我认为,这与列表的功能有关,即,如果附加了某些值,则ID将保留。

有人可以简要地给我一个简短的解释,这种行为背后的主要原因是什么?

2 个答案:

答案 0 :(得分:3)

int的值是不可变的。您没有修改现有的int,而是用不同 self.b的值替换了int

list的值 是可变的,并且list.append修改调用它的实例。 self.a被就地修改,而不用新列表替换现有列表。

基本上,如果不知道+=的值类型,就无法预测其行为。在b = 0; b += 1中,b指的是int的新实例。但是在b = []; b += [2,3]中,现有列表得到了扩展(就像您曾经呼叫过b.extend([2,3])一样。)

答案 1 :(得分:0)

看看如何使用is语句(不使用==)使它可视化:

class MyClass(object):

    a = [1]
    b = 1

    def __init__(self):
        print(self.a, id(MyClass.a))
        print(self.b, id(MyClass.b))

    def modify(self):
        self.a.append(2)
        print("modfied list attribute:", MyClass.a, id(MyClass.a))
        print("modfied listattribute:", self.a, id(self.a))

        self.b += 1
        print("modfied int attribute:", MyClass.b, id(MyClass.b))
        print("modfied int attribute:", self.b, id(self.b))

x = MyClass()
y = MyClass()
print(x.a is y.a)  # True
print(x.b is y.b)  # True

x.modify()

print(x.a is y.a)  # True
print(x.b is y.b)  # Falseclass MyClass(object):

    a = [1]
    b = 1

    def __init__(self):
        print(self.a, id(MyClass.a))
        print(self.b, id(MyClass.b))

    def modify(self):
        self.a.append(2)
        print("modfied list attribute:", MyClass.a, id(MyClass.a))
        print("modfied listattribute:", self.a, id(self.a))

        self.b += 1
        print("modfied int attribute:", MyClass.b, id(MyClass.b))
        print("modfied int attribute:", self.b, id(self.b))

x = MyClass()
y = MyClass()

# Before changing something a and b is a reference to the same object
print(x.a is y.a)  # True
print(x.b is y.b)  # True

x.modify()

# After that only x.b is a reference to a new object
# you accessed the list object that is shared and append a value
print(x.a is y.a)  # True
print(x.b is y.b)  # False

# If you would give x.a a new list it would look like this
x.a = []
print(x.a is y.a)  # False
print(x.b is y.b)  # False
# x.a is now not the same list as y.a

除非您有理由使用a和b作为类属性,否则我建议您将其设置为实例属性:

class MyClass(object):

    def __init__(self):
        self.a = [1]
        self.b = 1
        print(self.a, id(self.a))
        print(self.b, id(self.b))

    def modify(self):
        self.a.append(2)
        print("modfied list attribute:", self.a, id(self.a))
        print("modfied listattribute:", self.a, id(self.a))

        self.b += 1
        print("modfied int attribute:", self.b, id(self.b))
        print("modfied int attribute:", self.b, id(self.b))

x = MyClass()
y = MyClass()
print(x.a is y.a)  # False
print(x.b is y.b)  # False

x.modify()

print(x.a is y.a)  # False
print(x.b is y.b)  # False


x.a = []
print(x.a is y.a)  # False
print(x.b is y.b)  # False