Multiple instances of a class being overwritten at the same time? (Python)

为君一笑 提交于 2021-02-07 06:27:05

问题


Here's a very simple code I made to demonstrate the problem I'm encountering. What's happening here is that I'm creating two different instances of the same class but changing an attribute of one will change the corresponding attribute of the other instance. I'm not sure why this is. Is this normal in Python or am I encountering something being totally messed up?

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)

Here is what the program looks like coming out of my console:

>>> 
X attributes: 

60
Bar
Y attributes: 

60
Bar
>>> 

I think it should be saying:

X attributes:

20
Foo
Y attributes:

60
Bar

What am I doing wrong?


回答1:


You're creating class attributes, when you want instance attributes. Use this:

class exampleClass(object):
    def __init__(self):
        self.attribute1 = 0
        self.attribute2 = "string"

Also, you aren't creating any instances of exampleClass, you need this:

x = exampleClass()
y = exampleClass()

Your code is simply using new names for the class, and changing its attributes.




回答2:


You've made the attributes class attributes. This means that they are scoped to the class itself, not to objects of the class.

If you want object-scoping you could do something like:

class exampleClass(object):
        def __init__(self):
            self.attribute1=0
            self.attribute2="string"

x = exampleClass()
y = exampleClass()

Then when you change the attribute value of an object, it only affects that particular, as opposed to ALL objects of that class.




回答3:


Modifications made so it is clearer.

With the code that you have, your issue is that you are making the variables x and y refer to the class definition rather than instantiating the objects which I believe have now surfaced as the issue with all the discussion and posts.

x = exampleClass

Now means that x now points to the class definition. It's interesting because since you have attribute1 as a variable of the exampleClass, you can do this:

x.attribute1 = 3

Now if you did the following:

exampleClass.attribute1

Instead of seeing 0 as you originally set it, you will now see 3!

To instantiate objects of the class you need to do the following:

x = exampleClass()
y = exampleClass()

Now both variables are referencing new objects that each have their own attributes so if you did:

x.attribute1 = 219

Then you will find that y.attribute1 is not modified :) Using the name of the class and function is common in python as a reference to the definition. So do be careful, if you want to instantiate an object make sure to use parentheses, if you want to call a function, make sure you do that too, otherwise using the name is a reference to the definition.

I suggest you read Ned Batchelder's answer though (and others now) as you should be making instance variables in that way with init function as it is much cleaner and more toward the design standards that most follow.

But overall since it inherits from Object class then you can assume doing it this way will create instances (with the parentheses) and such and so you can modify the object values as I believe they should be instance variables even without the "self".




回答4:


Classes are objects too, in Python. Hence, they can be assigned to variables and have their own attributes, same as any other object.

All the names you bind in a class block become attributes of the class that is created. They are not attributes of the future instances of that class. But when you try to read an attribute from an instance and the instance doesn't have that attribute, Python defaults to looking at the instance's class' attributes, and will return that if it finds one. That's actually how methods work in Python; they're just attributes on the class, and when you try to retrieve them from the instance (where they don't exist) they get found by looking at the class.

With that in mind, your program doesn't do what you think it does.

class exampleClass(object):

    attribute1=0
    attribute2="string"

Here you've created a class named exampleClass, with two attributes attribute1 and attribute2. They are not instance attributes; this is a really common mistake of people learning Python. You need to train yourself out of this, because for simple examples it will often appear to work "as if" they were instance attributes. Binding names in a class block creates attributes on the class object. The only way to create instance attributes is to get a reference to the instance once it exists and assign the attributes on it; Python gives you the __init__ method (which will be called when the instance is created) as the place to do this.

So the basic rule of thumb is: names defined in a class block are attributes on the class object, names assigned as attributes of self in __init__ are attributes on all of the instances of that class.

Your confusion is further compounded by another issue:

x=exampleClass
x.attribute1=20
x.attribute2="Foo"

Because classes are objects like everything else in Python, this is perfectly reasonable Python code, but it doesn't do what you think it does. You haven't actually created an instance of your class; for that you need to call the class as in exampleClass(). The bare name exampleClass simply refers to the class object itself, so you've just bound the name x to that object and then assigned some of its attributes. Naturally, when you then bind y to the class object as well and assign attributes on that object through y, the object referred to by x is affected (it's the same object).



来源:https://stackoverflow.com/questions/11217458/multiple-instances-of-a-class-being-overwritten-at-the-same-time-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!