Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the class attribute being modified?

Tags:

python

class

In my book it says

Use class attributes to define properties that should have the same value for every class instance. Use instance attributes for properties that vary from one instance to another.

But then, in an example, the species class attribute is modified for miles as shown below:

class Dog:
    species = "Canis familiaris"
   
miles = Dog()
snoopy = Dog()
miles.species = "Felis silvestris"

That means that the species class attribute is not for the entire Dog class. Have I misunderstood something or is it simply normal to customise class attributes?

like image 918
Despereaux Avatar asked Jan 25 '23 07:01

Despereaux


2 Answers

Why is the class attribute being modified?

It isn't. miles is an instance of the Dog class, so assigning to miles.species creates an instance attribute.

That means that the species class attribute is not for the entire Dog class.

In the code you have shown, there are two things called species.

  • An attribute of the class Dog ("Canis familiaris"), which is unchanged for the whole program.
  • An attribute of the instance miles ("Felis silvestris"), which only applies to miles, but not to the whole Dog class, nor to the snoopy instance.

Since snoopy doesn't have its own species instance attribute, accessing snoopy.species will fall back to Dog.species.

like image 179
mkrieger1 Avatar answered Jan 26 '23 19:01

mkrieger1


Your book's summary of the idea is correct but I can see that it may be vague to a new OOP learner.

Proper practice dictates that class attributes be defined as such:

class Dog:
    species = "Canis familiaris"
    # ... other methods, etc.

but instance attributes are meant to be individual to each object you create from the class. When defining a class properly, you would also want to include an initialization method to be executed on object creation. i.e.:

class Dog:
    def __init__(self, species):
        self.species = "Canis familiaris"  # This is an instance attribute

To differentiate between a class attribute and an instance attribute, they are referred to differently: (See Sumant's answer for a good rundown)

# class Dog: ...
miles = Dog()
print(Dog.species)  # This prints the class attribute
print(miles.species)  # This prints the instance attribute (if found)

It is a confusing concept but I hope that this answer clarifies it at least a little.

like image 38
Jerrybibo Avatar answered Jan 26 '23 19:01

Jerrybibo