How object and class attributes work.
What’s a class attribute
A class attribute is a Python variable that belongs to a class rather than a particular object. It is shared between all the objects of this class and it is defined outside the constructor function, __init__(self,...), of the class.
like this:
class Dog:
species = 'Doggo'
def __init__(self, name, age):
self.name = name
self.age = age
What’s an instance attribute
An instance attribute is a Python variable belonging to one, and only one, object. This variable is only accessible in the scope of this object and it is defined inside the constructor function, __init__(self,..) of the class.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
What are the differences between class and instance attributes
- If a class variable is set by accessing an instance, it will override the value only for that instance. This essentially overrides the class variable and turns it into an instance variable available, intuitively, only for that instance.
- lass attributes are attributes which are owned by the class itself. They will be shared by all the instances of the class. Therefore they have the same value for every instance.
The Pythonic way of doing it
The recommended way to doing it is using getters and setters
In Python property()is a built-in function that creates and returns a property object. A property object has three methods, getter(), setter(), and delete(). property() function in Python has four arguments property(fget, fset, fdel, doc), fget is a function for retrieving an attribute value. fset is a fuction for setting an attribute value. fdel is a function for deleting an attribute value. doc creates a docstring for attribute. A property object has three methods, getter(), setter(), and delete() to specify fget, fsetand fdel individually.
class Dog:
species = 'Doggo'
def __init__(self, name, age):
self.name = name
self.age = age
@property
def name(self):
""" getting width """
return self.__name
# Using setter to set the width
@name.setter
def name(self, value):
""" setting width """
self.__name = value
@property
def age(self):
""" getting width """
return self.__age
# Using setter to set the width
@age.setter
def age(self, value):
""" setting width """
self.__age = value
- We use getters & setters to add validation logic around getting and setting a value.
- To avoid direct access of a class field i.e. private variables cannot be accessed directly or modified by external user.
Using property to get the name and age from the user allows us to attach code to the attribute self.name and self.age. Any code that gets or assigns the value of width will automatically call name in def name and age in def age.
Advantages and drawbacks
- Instance attributes are owned by the specific instances of a class. This means for two different instances the instance attributes are usually different. they are useful for things that change with the whole class such as an instance parameter counter of objects instances but also is his drawback, because maybe on accidentally we can create a class attribute that was meant to be an instance attribute can cause some unexpected behavior between instances.
- As class attributes can be accessed as attributes of the class itself, it’s often nice to use them for storing Class-wide, Class-specific constants, creating class methods is useful because they can be called whether you reference them using the class name or a particular instance name.
- His drawback will be that we have too much access to these functions through instance names an can quickly cause confusion as it will not be clear that a particular operation
How does Python deal with the object and class attributes using the __dict__
Module objects have a secret read-only attribute called __dict__ which returns the dictionary used to implement the module’s namespace; the name __dict__ is an attribute but not a global name. Obviously, using this violates the abstraction of namespace implementation, and should be restricted to things like post-mortem debuggers.
In Python, attributes are stored in dictionaries which are key:value pairs where the key is some string or name and the value is the corresponding value that is stored in these variables.
for the doggo it will print
my_dog = Dog("perrito", 4)
print(my_dog.__dict__)
output:
{'_Dog__name': 'perrito', '_Dog__age': 4}