You can use magic methods (also called dunder methods) in your Python class to override certain functionality of your class instance.
Some examples of magic methods are "__repr__", "__hash__", "__get__" and more. These are part of the Python 3 data model.
"__repr__" - String representation
This method allows you to define a string output for every class instance that is created. You will get as an output the memory address of the called class instance, if you call a class instance of a class without this method "__repr__".
class Car:
def __init__(self, manufacturer, model):
self.manufacturer = manufacturer
self.model = model
def __repr__(self):
return self.manufacturer + " - " + self.model
if __name__ == '__main__':
bluecar1 = Car("The Car Company" , "XY 199")
print(bluecar1)
But you can instead print with this method your own defined string. "__init__" is an constructor implementation and it allows to define what should hapen when an instance of this class is created. In this method you will have the definition of the variable of a class instance.
"__hash__" - Customized hash for hashable objects
If you use for example collections (such as "set", "frozenset" or "dict"), then you can customize the creation of the hash value of your object.
class Car:
def __init__(self, manufacturer, model):
self.manufacturer = manufacturer
self.model = model
def __hash__(self):
return int(hash(self.manufacturer)%10000)
if __name__ == '__main__':
bluecar1 = Car("The Car Company" , "XY 199")
print(bluecar1.__hash__())
In this example the hash value of objects cannot have more than four digits and it is created from string object "manufacturer".
"__get__" - Value of variable of a class instance
This method is called when a variable of an class instance is accessed. You can override so it returns a custom value instead.
class EndPrice:
def __get__(self, instance, owner):
if instance.manufacturer=="The Car Company":
return instance.stockprice-(instance.stockprice*0.10)
else:
return instance.stockprice-(instance.stockprice*0.05)
class Car:
endprice = EndPrice()
def __init__(self, manufacturer, model, stockprice):
self.manufacturer = manufacturer
self.model = model
self.stockprice = stockprice
def __repr__(self):
return self.manufacturer + " - " + self.model
if __name__ == '__main__':
bluecar1 = Car("The Car Company" , "XY 199", 2000)
print(bluecar1.endprice)
redcar1 = Car("NoName Company" , "ZZ 2", 2000)
print(redcar1.endprice)
If you access a variable (in this example: "endprice") of your class instance object, then Python calls the method "__get__(instance, owner)" in the background. "instance" is the class instance for which the class variable is called. "owner" is who own this class object and it is an optional argument.
"__set__" is also available. You can also change how values of a variable are set.
Example:
def __set__(self, instance, value):
instance.stockprice = value * 100
In this example we convert the stock price automatically to cents.
"__add__" / "__sub__" - Arithmetical methods
You can use these methods to change values of variables in your class instance, when an arithmetic operator was used.
class Car:
def __init__(self, manufacturer, model, stockprice):
self.manufacturer = manufacturer
self.model = model
self.stockprice = stockprice
def __add__(self, other):
if type(other) is int:
self.stockprice + other
else:
raise Exception("Please enter only an integer value!")
def __sub__(self, other):
if type(other) is int:
self.stockprice - other
else:
raise Exception("Please enter only an integer value!")
def __repr__(self):
return str(self.stockprice)
if __name__ == '__main__':
bluecar1 = Car("The Car Company" , "XY 199", 2000)
bluecar1 + 2000
print(bluecar1)
bluecar1 - 1000
print(bluecar1)
"__add__" is called when you do an addition ("+") with another class instance variable or value. "__sub__" when you do an substraction ("-").
There are also other arithmetical methods:
"__mul__": For multiplication - Operator: "*"
Example:
def __mul__(self, other):
self.stockprice * other
classobject1 * classobject2
"__truediv__": For division - Operator: "/"
def __truediv__(self, other):
self.stockprice / other
classobject1 / classobject2
Comparison operators
"__lt__" - Lower than - Comparison
You can override that method to return a certain string when a "lower than" comparison is done with two class instance objects. This method is called through the operator "<".
class Car:
def __lt__(self, other):
if other.stockprice < self.stockprice:
return "Second car cheaper than first car"
else:
return "Second car is NOT cheaper than first car"
if __name__ == '__main__':
bluecar1 = Car("The Car Company" , "XY 199", 2000)
redcar1 = Car("NoName Company" , "ZZ 2", 3000)
print(bluecar1<redcar1)
Other comparison methods
- "__le__" - lower equals - Operator: "<="
- "__eq__" - equals - Operator: "="
- "__ne__" - not equals - Operator: "!="
- "__gt__" - greater than - Operator: >
- "__ge__" - greater equals - Operator: ">="
All these methods have also the argument variable "other", such as in our example "__lt__" above.
There are much more magic methods such as "__len__" (changes "len" value of an object) and more. New methods are introduced in every new Python version. Please refer to the Python documentation for more information.
More about magic methods:
https://docs.python.org/3/reference/datamodel.html#special-method-names