Lecture 7: Objects and Classes Continued: Magic Methods

Eric Brauer

Review: Why Use Objects?

  • Allows us to better organise code
  • Combine relevant attributes and methods together
  • Keep attributes private, only expose what another developer might need
  • Lets us keep things simple!

“In Python, Everything Is An Object”

#!/usr/bin/env python3
x=3
>>>> print(x)
3
>>>> 3 > 4.0
False
>>>> help(int)

Running the builtin help() will show you all the methods that belong to integer objects.

What are Magic Methods?

Notice all the methods that start & end with __? These are dunder methods (“double underline”). Otherwise called magic methods.

We don’t call these methods directly by name.

Rather these are called when we use the object with different operators or builtin functions.

__eq__

>>>> x = 3
>>>> x == 4.0
False

When we use the integer object with a == symbol, we are actually calling the __eq__ method, which will return a True or False.

def __eq__(self, other):
    return self==other

For operators, “self” will refer to the left side of the equation, and “other” will refer to the right.

Magic Methods

Every built-in object in Python will be implementing a lot of these magic methods. This helps us because it means that objects in Python will behave in predictable ways. By implementing magic methods in our classes, we can allow the user to use our objects in intuitive ways.

A Quick Example

Class Temperature:

    def __init__(self, temp, unit):
        self.temp = temp
        self.unit = unit

    def rtrn_celsius(self):
        if self.unit == 'F':
            return self.temp / 1.8 - 32
        else:
            return self.temp 

    def rtrn_fahrenheit(self):
        if self.unit == 'C':
            return self.temp * 1.8 + 32  # equation to convert C to F.
        else:
            return self.temp

    def return_unit(self):
        return self.unit

A Quick Example II

It might be more intuitive when comparing temperatures if we let our == symbol ‘detect’ the unit of the other temperature.

    def __eq__(self, other):
        if other.return_unit() == 'C':
            return self.rtrn_celsius() == other.rtrn_celsius()
        elif other.return_unit() == 'F':
            return self.rtrn_fahrenheit() == other.rtrn_fahrenheit()

Implementation

temp1 = Temperature(28, 'C')
temp2 = Temperature(82.4, 'F')
if temp1 == temp2:
    print('It is the same!')

Notice how we don’t have to read the docs to make this work!

Printing Objects

>>>> t1 = Timer(2, 0)
>>>> print(t1)
<Timer object at 0x7f24b9419940>

This output isn’t very useful to the programmer.

Using str

Class Timer:

    def __init__(self, mins, secs):
        self.mins = mins
        self.secs = secs

    def __str__(self):  # gets called inside print() or str()
        return f"{self.mins:02d}:{self.secs:02d}"

This is an example of using f-strings, which are very useful! No data conversion is required. :02d will convert to a 2 digit decimal number with leading zeros, eg. 02

str VS. repr

repr is used inside the Python interpreter. It will return a representation of the object, when you call the object outside of print() or str().

>>>> t = Timer(2, 0)
>>>> t  # calls __repr__
<template.Timer object at 0x7f199cb4f820>
>>>> print(t)  # calls __str__
02:00

List of Magic Methods

Magic Methods will define the behaviour of:

  • Comparison Operators == != < > <= >=
  • Math Operators + - * / ** //
  • Other Math functions: abs()
  • Slicing: card_deck[0:4] # calls get_item
  • And more…..