为什么改变班级的属性会导致不同的后果?

时间:2015-01-08 02:01:24

标签: python class attributes

我创建了一个类卡,其中包含属性suitList和数字。当我改变它们时,我预计它不会影响不同的对象。但结果令人困惑。为什么更改suitList会影响其他对象'suitList?请解释一下。

class Card:
  suitList = ["CLubs"]
  number = 1

  def __init__ (self, rank = 0):
      self.rank = rank

  def __str__ (self):
      return (self.suitList[self.rank] + "  " + str(self.number) + ";\n")
c1 = Card()
c2 = Card()
print c1
c1.suitList[0] = "Heart"
c1.number = 3
print c1
print c2
c3 = Card()
print c3

3 个答案:

答案 0 :(得分:2)

这是因为您已经为suitList提供了一个类属性,它在该类的所有实例之间共享。如果您希望每个实例都有一个唯一的suitList列表,那么您应该将其设为实例属性

def __init__(self, rank = 0):
     self.rank = rank
     self.suitList = ["CLubs"]

您可能还想将number的定义移到__init__方法中,以便它也成为实例属性:

def __init__(self, rank = 0):
     self.rank = rank
     self.suitList = ["CLubs"]
     self.number = 1

有关详细信息,请参阅Python: Difference between class and instance attributes


此外,您会注意到我使用self.为所有名称添加前缀您需要这样做,以便将值作为类的属性。如果我们这样做了:

def __init__(self, rank = 0):
     self.rank = rank
     suitList = ["CLubs"]
     number = 1

suitListnumber将成为__init__方法的本地。

答案 1 :(得分:1)

这两个属性是类属性static variables。如果要声明非静态属性,则必须在变量名称前加上self,它引用您正在使用的类的当前实例:

class MyClass:
    def __init__(self):
        self.suitList = ["CLubs"]
        self.number = 1

有关什么是self以及静态和非静态类变量之间差异的更多信息:

  1. Python __init__ and self what do they do?

  2. Python 'self' keyword

  3. Explaining the python 'self' variable to a beginner

  4. What is the purpose of self?

  5. https://stackoverflow.com/questions/3332454/oop-python-oriented-tutorials

  6. Python: Difference between class and instance attributes

答案 2 :(得分:1)

正如所指出的,您将类属性与实例属性混淆。

在你的例子中,suitList和number是class属性,它们在所有实例(c1,c2,c3)之间共享 当您在c1.suitList[0] = "Heart"中更改类属性时,它将反映在所有类实例中。

要解决这个问题,你有一些选择:我给你两个。

1)仅使用实例属性:

class Card:
    def __init__(self,number=0,suit="CLubs"):
        self.number = number
        self.suit = suit

    def __str__(self):
        return "%s %d"%(self.suit,self.number)

c1 = Card()
c2 = Card()
c1.suit = "Heart"
c1.number = 3
print c1
print c2

在这种情况下,没有类属性,可以使用c1.suit更改您指定的卡套件。

2)使用类/属性的混合:

class Card:
    suitList = ["CLubs", "Heart"]
    def __init__(self,number=0,rank=0):
        self.rank = rank
        self.number = number

    def __str__(self):
        return (Card.suitList[self.rank] + "  " + str(self.number))

c1 = Card()
c2 = Card()
c1.rank = 1
c1.number = 3
print c1
print c2

在这种情况下,Rank是一个在suitList中查找的索引。要更改卡片的套装,请更改它的等级,而不是更换套装。

两个例子都是输出:

Heart 3
CLubs 0