我创建了一个类卡,其中包含属性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
答案 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
suitList
和number
将成为__init__
方法的本地。
答案 1 :(得分:1)
这两个属性是类属性或static variables。如果要声明非静态属性,则必须在变量名称前加上self
,它引用您正在使用的类的当前实例:
class MyClass:
def __init__(self):
self.suitList = ["CLubs"]
self.number = 1
有关什么是self
以及静态和非静态类变量之间差异的更多信息:
答案 2 :(得分:1)
正如所指出的,您将类属性与实例属性混淆。
在你的例子中,suitList和number是class属性,它们在所有实例(c1,c2,c3)之间共享
当您在c1.suitList[0] = "Heart"
中更改类属性时,它将反映在所有类实例中。
要解决这个问题,你有一些选择:我给你两个。
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更改您指定的卡套件。
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