A.I, Data and Software Engineering

Advanced Python: classes String and computed attribute


This article demonstrates more advanced features of Python classes and their customisation. Specifically, how enum objects are created, class to strings, and computed attribute.

Class string values

A string is typically an informal representation of the object. However, it’s just a nicely in human-readable form. Python provides 2 common methods, i.e. str() and repr(). We can customise the two built-in methods to display the information that we want from an object.

class Person():
    def __init__(self):
        self.fname = "Joe"
        self.lname = "Marini"
        self.age = 25
    # use __repr__ to create a string useful for debugging
    def __repr__(self):
        return "<Person Class - fname:{0}, lname:{1}, age{2}>".format(self.fname, self.lname, self.age)
    # use str for a more human-readable string
    def __str__(self):
        return "Person ({0} {1} is {2})".format(self.fname, self.lname, self.age)
    # use bytes to convert the informal string to a bytes object
    def __bytes__(self):
        val = "Person:{0}:{1}:{2}".format(self.fname, self.lname, self.age)
        return bytes(val.encode('utf-8'))

Now if we create a Person object and print it out using these functions:

    # create a new Person object
    cls1 = Person()
    # use different Python functions to convert it to a string
    print("Formatted: {0}".format(cls1))

We will have the following output:

#<Person Class - fname:Joe, lname:Marini, age25>
#Person (Joe Marini is 25)
#Formatted: Person (Joe Marini is 25)

str() and repr() both are used to get a string representation of an object. But they have the following differences:

  • str() is used for creating output for end user while repr() is mainly used for debugging and development. repr’s goal is to be unambiguous and str’s is to be readable. For example, if we suspect a float has a small rounding error, repr will show us while str may not.
  • repr() compute the “official” string representation of an object (a representation that has all information about the object) and str() is used to compute the “informal” string representation of an object (a representation that is useful for printing the object).
  • The print statement and str() built-in function uses __str__ to display the string representation of the object while the repr() built-in function uses __repr__ to display the object.
s = 'Hello, Petamind.'
s = 'Hello, Petamind.'
Hello, Petamind.
‘Hello, Petamind.’
repr vs str

Defining enumerations

Python supports enumerations just like other popular programming languages and they’re useful in a variety of scenarios. Usually, they are used to assign easy-to-read names to constant values in a program. Also, you can iterate over them like you would other iterable in Python. 

We define enumerations using the class syntax. In the following code, we create an enum type Fruit of unique value with @unique annotation. We can use auto() function to automatically assign values to enums.

# define enumerations using the Enum base class
from enum import Enum, unique, auto
class Fruit(Enum):
    APPLE = 1
    BANANA = 2
    ORANGE = 3
    TOMATO = 4
    PEAR = auto()

Enums have human-readable values and types. Let print their values and types:

#<enum 'Fruit'>
#<Fruit.APPLE: 1>
# enums have name and value properties
print(Fruit.APPLE.name, Fruit.APPLE.value)
# print the auto-generated value

Enums are hashable so we can use them as unique keys of a dictionary.

myFruits = {}
myFruits[Fruit.BANANA] = "Come Mr. Tally-man"
#Come Mr. Tally-man


Python provides a set of methods that classes can use to access the attributes of an object. Whenever we retrieve or set an object’s attributes, Python calls one of these functions to perform any desired processing. 

The first two, getattribute and getattr, are called to retrieve an attribute value. These are slightly different from each other. Getattr is called only when the requested attribute can’t be found on the object. Meanwhile, getattribute is called unconditionally every time an attribute name is requested. Additionally, there are setattrdelattr, and dir to set, delete and discover supported attributes.

class myColor():
    def __init__(self):
        self.red = 50
        self.green = 75
        self.blue = 100
    # use getattr to dynamically return a value
    def __getattr__(self, attr):
        if attr == "rgbcolor":
            return (self.red, self.green, self.blue)
        elif attr == "hexcolor":
            return "#{0:02x}{1:02x}{2:02x}".format(self.red, self.green, self.blue)
            raise AttributeError
    # use setattr to dynamically return a value
    def __setattr__(self, attr, val):
        if attr == "rgbcolor":
            self.red = val[0]
            self.green = val[1]
            self.blue = val[2]
            super().__setattr__(attr, val)
    # use dir to list the available properties
    def __dir__(self):
        return ("rgbolor", "hexcolor")

The above code modifies the attribute related methods to get colour information. As user passes a supported attribute name, e.g. `rgbcolor`, python will return the value corresponding to the name.

# create an instance of myColor
cls1 = myColor()
# print the value of a computed attribute
#(50, 75, 100)
#(50, 75, 100)

Click here for other advanced python topics.

Add comment


A.I, Data and Software Engineering

PetaMinds focuses on developing the coolest topics in data science, A.I, and programming, and make them so digestible for everyone to learn and create amazing applications in a short time.