这是一个非常简单的代码,用于演示我遇到的问题。这里发生的是我正在创建同一个类的两个不同实例,但更改一个属性会改变另一个实例的相应属性。我不确定为什么会这样。这在Python中是正常的还是我遇到了一些完全混乱的东西?
class exampleClass(object):
attribute1=0
attribute2="string"
x=exampleClass
x.attribute1=20
x.attribute2="Foo"
y=exampleClass
y.attribute1=60
y.attribute2="Bar"
print("X attributes: \n")
print(x.attribute1)
print(x.attribute2)
print("Y attributes: \n")
print(y.attribute1)
print(y.attribute2)
这是程序从我的控制台出来的样子:
>>>
X attributes:
60
Bar
Y attributes:
60
Bar
>>>
我认为应该说:
X attributes:
20
Foo
Y attributes:
60
Bar
我做错了什么?
答案 0 :(得分:8)
当您需要实例属性时,您正在创建类属性。使用此:
class exampleClass(object):
def __init__(self):
self.attribute1 = 0
self.attribute2 = "string"
此外,您没有创建exampleClass的任何实例,您需要这样:
x = exampleClass()
y = exampleClass()
您的代码只是为类使用新名称,并更改其属性。
答案 1 :(得分:5)
您已经创建了属性类属性。这意味着它们的范围限于类本身,而不是类的对象。
如果你想要对象范围,你可以做类似的事情:
class exampleClass(object):
def __init__(self):
self.attribute1=0
self.attribute2="string"
x = exampleClass()
y = exampleClass()
然后,当您更改对象的属性值时,它只影响该特定的值,而不是该类的所有对象。
答案 2 :(得分:3)
所做的修改更清晰。
使用您拥有的代码,您的问题是您正在使变量x和y引用类定义,而不是实例化我认为现在已经作为所有讨论和帖子出现问题的对象。
x = exampleClass
现在意味着x现在指向类定义。这很有意思,因为你将attribute1作为exampleClass的一个变量,你可以这样做:
x.attribute1 = 3
现在,如果您执行了以下操作:
exampleClass.attribute1
您不会在最初设置时看到0,而是会看到3!
要实例化该类的对象,您需要执行以下操作:
x = exampleClass()
y = exampleClass()
现在两个变量都引用了每个都有自己属性的新对象,所以如果你这样做了:
x.attribute1 = 219
然后你会发现y.attribute1没有被修改:)使用类和函数的名称在python中很常见,作为对定义的引用。所以要小心,如果你想要实例化一个对象,请确保使用括号,如果你想调用一个函数,请确保你也这样做,否则使用该名称就是对定义的引用。
我建议您阅读Ned Batchelder的答案(现在还有其他人),因为您应该使用 init 函数以这种方式制作实例变量,因为它更清晰,更符合大多数关注的设计标准
但总的来说,它继承自Object类,那么你可以假设这样做会创建实例(带括号)等等你可以修改对象值,因为我相信它们应该是实例变量,即使没有“自我” ”
答案 3 :(得分:1)
在Python中,类也是对象。因此,它们可以分配给变量并具有自己的属性,与任何其他对象相同。
您在class
块中绑定的所有名称都将成为创建的类的属性。它们是该类的未来实例的 not 属性。但是当您尝试从实例读取属性并且实例没有该属性时,Python默认查看实例的类属性,如果找到,则返回该属性。这实际上是方法在Python中的工作方式;它们只是类的属性,当你尝试从实例中检索它们时(它们不存在),通过查看类来找到它们。
考虑到这一点,你的程序没有按照你的想法做到。
class exampleClass(object):
attribute1=0
attribute2="string"
在这里,您创建了一个名为exampleClass
的类,其中包含两个属性attribute1
和attribute2
。它们是不是实例属性;这是人们学习Python的一个非常常见的错误。你需要训练自己,因为对于简单的例子,它通常似乎“好像”它们是实例属性。 class
块中的绑定名称会在类对象上创建属性。创建实例属性的唯一方法是在实例存在时获取对该实例的引用并在其上分配属性; Python为您提供__init__
方法(在创建实例时将调用它)作为执行此操作的位置。
所以基本的经验法则是:在类块中定义的名称是类对象的属性,在self
中作为__init__
属性分配的名称是该类的所有实例上的属性
另一个问题使你的困惑更加复杂:
x=exampleClass
x.attribute1=20
x.attribute2="Foo"
因为类是像Python中其他所有类的对象,所以这是完全合理的Python代码,但它并不像你认为的那样做。你还没有真正创建过你的类的实例;为此,您需要像exampleClass()
中一样调用该类。裸名exampleClass
只是引用类对象本身,因此您只需将名称x
绑定到该对象,然后分配其一些属性。当然,当您然后将y
绑定到类对象并通过y
为该对象分配属性时,x
引用的对象会受到影响(它是同一个对象)。 / p>