+ 1

Class and instance attributes

Hello dear coders! Could you please explain how class and instance attributes are accessed according to following code: class Dog: legs = 4 def __init__(self): self.legs = 3 def setLegs(self, newLegs): legs = newLegs fido = Dog() print(fido.legs) print(Dog.legs) fido.setLegs(2) print(fido.legs) print(Dog.legs) Output: 3 4 3 4 I don’t get why after instantiation the legs number of class isn’t changed. Also even setLegs doesn’t change the number of instance legs.

9th Dec 2022, 7:55 AM
Ruslan Guliyev
Ruslan Guliyev - avatar
15 Réponses
+ 7
Ruslan Guliyev Yes, you are correct. In the code you provided, fido.legs should use the class value of 4 because it is closer in scope than the global value of 7. This is because when you access an attribute of an object, the interpreter first looks for the attribute in the object's instance namespace, and if it is not found, it will look in the class namespace. However, in the code you provided, the attribute legs is not actually defined in the class Dog, so when you access fido.legs, the interpreter will not find it in the instance or class namespace, and will instead use the global value of 7.
9th Dec 2022, 12:39 PM
Sadaam Linux
Sadaam Linux - avatar
+ 6
In the code you provided, the Dog class has a class attribute called legs, which is initialized to 4 in the class definition. This means that the legs attribute is shared among all instances of the Dog class. When an instance of the Dog class is created, it has its own legs attribute, which is initialized to 3 by the __init__ method. This attribute is called an instance attribute, and it is specific to each instance of the class. The setLegs method is a bit confusing, because it tries to reassign the legs attribute, but it is actually creating a new local variable called legs inside the method. This local variable shadows the class attribute, so the class attribute is not changed.
9th Dec 2022, 12:09 PM
Sadaam Linux
Sadaam Linux - avatar
+ 6
When you print the legs attribute of fido, it prints 3, because that is the value of the instance attribute. When you print the legs attribute of the Dog class, it prints 4, because that is the value of the class attribute. The setLegs method does not change the legs attribute of the fido instance, because it is not modifying the instance attribute. Instead, it is creating a new local variable, which is only visible inside the method and is discarded after the method returns. Here is an updated version of the code that modifies the legs attribute of the fido instance: https://code.sololearn.com/cfU74b163L4l/?ref=app
9th Dec 2022, 12:11 PM
Sadaam Linux
Sadaam Linux - avatar
+ 6
In this updated version, the setLegs method uses the self keyword to access the legs attribute of the fido instance, so it can modify the instance attribute. This is why the legs attribute of the fido instance changes when the setLegs method is called. The legs attribute of the Dog class remains the same, because it is not modified by the setLegs method
9th Dec 2022, 12:14 PM
Sadaam Linux
Sadaam Linux - avatar
+ 3
class attributes are shared among object instances, while instance attributes are unique to object instances. https://www.freecodecamp.org/news/JUMP_LINK__&&__python__&&__JUMP_LINK-attributes-class-and-instance-attribute-examples/
10th Dec 2022, 4:11 AM
Bob_Li
Bob_Li - avatar
+ 2
Class attributes are attributes that belong to the class itself, rather than to any particular instance of the class. In the code you posted, the legs attribute is a class attribute because it is defined directly on the class, outside of any method. Instance attributes are attributes that belong to a specific instance of a class. In the code you posted, the legs attribute inside the __init__ method is an instance attribute because it is assigned using the self keyword, which refers to the instance of the class. When you try to access an attribute on an instance of a class, Python first looks for an instance attribute with that name. If it doesn't find one, it looks for a class attribute with that name. This is why, in the code you posted, fido.legs returns 3 even though the legs attribute is defined as 4 on the Dog class.
9th Dec 2022, 7:59 AM
Calviղ
Calviղ - avatar
+ 2
If you want the setLegs method to actually change the number of legs on the fido instance, you need to assign the new value to the legs instance attribute using the self keyword. Here's how you can do that: class Dog: legs = 4 def __init__(self): self.legs = 3 def setLegs(self, newLegs): self.legs = newLegs fido = Dog() print(fido.legs) # prints 3 fido.setLegs(2) print(fido.legs) # prints 2 https://code.sololearn.com/cc65BUbgvTZA/?ref=app
9th Dec 2022, 8:02 AM
Calviղ
Calviղ - avatar
+ 2
The Dog class has an attribute legs with a value of 4. However, when you create an instance of the Dog class called fido, you are setting the value of fido.legs to the value of the variable legs defined outside the class. This variable has a value of 7, so fido.legs ends up having a value of 7. When you print the value of fido.legs, it prints 7. On the other hand, when you print the value of Dog.legs, it prints the value of the legs attribute as defined in the Dog class, which is 4. This is because Dog.legs refers to the attribute defined in the class, whereas fido.legs refers to the attribute that is specific to the fido instance.
9th Dec 2022, 9:01 AM
Calviղ
Calviղ - avatar
+ 2
@Ruslan Guliyev the class variable where legs=4 is technically Dog.legs or self.legs. legs will refer to the global variable legs=7. Try this: in your __ini__ method, just use self.legs or even don't define it. do not use self.legs=legs. you will get the correct result.
9th Dec 2022, 1:02 PM
Bob_Li
Bob_Li - avatar
+ 2
also, something related to name mangling..here is a related video... https://youtu.be/0hrEaA3N3lk but it will probably confuse you more. It's confusing to me...😵
10th Dec 2022, 5:41 AM
Bob_Li
Bob_Li - avatar
+ 1
Calviղ, thank you! Could you please also explain why fido.legs access 7 instead of class value of 4 in the following code: legs = 7 class Dog: legs = 4 def __init__(self, color): self.legs = legs self.color = color fido = Dog("brown") print(fido.legs) print(Dog.legs)
9th Dec 2022, 8:56 AM
Ruslan Guliyev
Ruslan Guliyev - avatar
0
Calviղ, but logically fido.legs should use the class value of 4 instead of 7 because it is closer than the value outside of the class. As I understand, the scheme is like this: Instance value - class value - outside value(global) Isn’t it correct?
9th Dec 2022, 9:24 AM
Ruslan Guliyev
Ruslan Guliyev - avatar
0
Sadaam Linux, thank for your insights! Could you please also explain why fido.legs access 7 instead of class value of 4 in the following code: legs = 7 class Dog: legs = 4 def __init__(self, color): self.legs = legs self.color = color fido = Dog("brown") print(fido.legs) print(Dog.legs) Logically fido.legs should use the class value of 4 instead of 7 because it is closer than the value outside of the class. As I understand, the scheme is like this: Instance value - class value - outside value(global) Isn’t it correct?
9th Dec 2022, 12:33 PM
Ruslan Guliyev
Ruslan Guliyev - avatar
0
Bob_Li, thank you for your answer. It works well, however I would like to understand the process behind assigning the global value instead of class one.
10th Dec 2022, 4:00 AM
Ruslan Guliyev
Ruslan Guliyev - avatar
0
Bob_Li thank you! I will go through these articles.
11th Dec 2022, 9:13 AM
Ruslan Guliyev
Ruslan Guliyev - avatar