Data Type Objects

Python allows you to create your own data types using classes, first however lets look at types, you can use the type command to see what type an object is and also to compare objects. One feature of python is Duck typing, Duck typing is a concept related to dynamic typing, where the type or the class of an object is less important than the methods it defines. When you use duck typing, you do not check types at all. Instead, you check for the presence of a given method or attribute.

Types of an object
print(type(5))                              # int
print(type("Hello"))                        # str
print(type(['Hello','World']))              # list

print(type("Hello") == type("World"))       # true as both are str type
print(isinstance("Hello", str))             # true as "hello" is a str type
Comparing objects
class A:
    pass


class B(A):
    pass


b = B()

print(type(b))                              # results in <class '__main__.B'>
print(b.__class__)                          # same as above

print(isinstance(b, (B)))                   # True, as b is an instance of class B

Special Method Attributes

A special method attribute is an attribute of a class that has s special meaning, it is defined as a method normally they are automatically invoke in response to a demend made on an object of that class. The simplest is the __str__ which acts like the toString() in Java, if you use print on the object name the __str__ is called and thus is used to display the data inside the object in a readable format.

There are many special methods and I will demostrate a few below but see the Python documentation for a full list.

__str__ example
class Employee:
    def __init__(self, fname, lname):
        self.fname = fname
        self.lname = lname

    def __str__(self):
        return "Name is {0} {1}".format(self.fname, self.lname)


emp1 = Employee("Paul","Valle")

print(emp1)                         # uses the __str__ to display object

The magic method __getitem__ is basically used for accessing list items, dictionary entries, array elements etc. It is very useful for a quick lookup of instance attributes, you also have __setitem__ which sets list items, etc.

__getitem__ and __setitem__ example
class Employees:
    def __init__(self, employees):
        self.employees = [None]*employees

    def __setitem__(self, employee_number, value):
        self.employees[employee_number] = value

    def __getitem__(self, employee_number):
        return "Employee: " + self.employees[employee_number]


company_employees = Employees(4)                        # uses the __init__

company_employees[0] = "Paul Valle"                     # will use the __setitem__
company_employees[1] = "Will Hay"                       # will use the __setitem__
company_employees[2] = "Moore Marriott"                 # will use the __setitem__
company_employees[3] = "Graham Moffatt"                 # will use the __setitem__

print(company_employees[0])                             # will use the __getitem__
print(company_employees[1])                             # will use the __getitem__
print(company_employees[2])                             # will use the __getitem__
print(company_employees[3])                             # will use the __getitem__

The magic method __del__ is used for cleanup and is called when the object is garbage collected

__del__ example
class Dummy1:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name

    def __del__(self):                                                 # is called when object is garbage collected
        print("Called if object is deleted or garage collected,used for cleanup")


d = Dummy1("Paul Valle")
print(d)

## __del__ will get called here when program terminates