为什么改变类的属性会导致不同的后果?
Why change class's attributes result in different consequences?
我创建了一张 class 卡片,其属性为 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
那是因为您已将 suitList
设为 class 属性 ,该属性在 class 的所有实例之间共享。如果您希望每个实例都有一个唯一的 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.
前缀。您需要这样做,以便将值设为 class 的属性。如果我们改为这样做:
def __init__(self, rank = 0):
self.rank = rank
suitList = ["CLubs"]
number = 1
suitList
和 number
将成为 __init__
方法的局部。
这 2 个属性是 class 属性 或 static variables。如果要声明非静态属性,则必须在变量名称前加上 self
,它指的是您正在使用的 class 的当前实例:
class MyClass:
def __init__(self):
self.suitList = ["CLubs"]
self.number = 1
有关什么是 self
以及静态和非静态 class 变量的区别的更多信息:
Python __init__ and self what do they do?
Python 'self' keyword
Explaining the python 'self' variable to a beginner
What is the purpose of self?
Python: Difference between class and instance attributes
如前所述,您混淆了 class 属性和实例属性。
在你的例子中,suitList 和 number 是 class 属性,它们在所有实例(c1,c2,c3)之间共享
当您像 c1.suitList[0] = "Heart"
中那样更改 class 属性时,它将反映在所有 class 个实例中。
要解决此问题,您有一些选择:我给您两个。
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
在这种情况下,没有 class 属性,要更改您直接使用 c1.suit 分配的卡组。
2) 混合使用 class/attribute:
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
我创建了一张 class 卡片,其属性为 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
那是因为您已将 suitList
设为 class 属性 ,该属性在 class 的所有实例之间共享。如果您希望每个实例都有一个唯一的 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.
前缀。您需要这样做,以便将值设为 class 的属性。如果我们改为这样做:
def __init__(self, rank = 0):
self.rank = rank
suitList = ["CLubs"]
number = 1
suitList
和 number
将成为 __init__
方法的局部。
这 2 个属性是 class 属性 或 static variables。如果要声明非静态属性,则必须在变量名称前加上 self
,它指的是您正在使用的 class 的当前实例:
class MyClass:
def __init__(self):
self.suitList = ["CLubs"]
self.number = 1
有关什么是 self
以及静态和非静态 class 变量的区别的更多信息:
Python __init__ and self what do they do?
Python 'self' keyword
Explaining the python 'self' variable to a beginner
What is the purpose of self?
Python: Difference between class and instance attributes
如前所述,您混淆了 class 属性和实例属性。
在你的例子中,suitList 和 number 是 class 属性,它们在所有实例(c1,c2,c3)之间共享
当您像 c1.suitList[0] = "Heart"
中那样更改 class 属性时,它将反映在所有 class 个实例中。
要解决此问题,您有一些选择:我给您两个。
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
在这种情况下,没有 class 属性,要更改您直接使用 c1.suit 分配的卡组。
2) 混合使用 class/attribute:
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