Python OOP

Python OOP Classes and Instances:


class Employee:



    def __init__(self, first, last, pay):

        self.first = first

        self.last = last

        self.email = first + '.' + last + '@email.com'

        self.pay = pay



    def fullname(self):

        return '{} {}'.format(self.first, self.last)



emp_1 = Employee('Alex', 'Brown', 50000)

emp_2 = Employee('Lisa', 'Miller', 60000)



print(type(emp_1)) # <class '__main__.Employee'>



print(emp_1.email) # Alex.Brown@email.com



print(emp_2.fullname()) # Lisa Miller

print(Employee.fullname(emp_2)) # Lisa Miller

Python OOP Class Variables:

Class Variables shared for all instances of the class.


class Employee:

    raise_amount = 1.04

    num_of_emps = 0

    

    def __init__(self, first, last, pay):

        self.first = first

        self.last = last

        self.email = first + '.' + last + '@email.com'

        self.pay = pay



        Employee.num_of_emps += 1



    def fullname(self):

        return '{} {}'.format(self.first, self.last)

    

    def apply_raise(self):

        self.pay = int(self.pay * self.raise_amount)

        

emp_1 = Employee('Alex', 'Brown', 50000)

emp_2 = Employee('Lisa', 'Miller', 60000)



print(emp_1.raise_amount) # 1.04

print(Employee.raise_amount) # 1.04

print(emp_1.pay) # 50000

emp_1.apply_raise()

print(emp_1.pay) # 52000



Employee.raise_amount = 1.05



print(Employee.raise_amount) # 1.05

print(emp_2.raise_amount) # 1.05



emp_2.raise_amount = 1.07



print(emp_2.raise_amount) # 1.07



print(emp_1.__dict__)

# {'first': 'Alex', 'last': 'Brown', 'email': 'Alex.Brown@email.com', 'pay': 50000}



print(emp_2.__dict__)

# {'first': 'Lisa', 'last': 'Miller', 'email': 'Lisa.Miller@email.com', 'pay': 60000, 'raise_amount': 1.07}



print(Employee.__dict__)

# {'__module__': '__main__', 'raise_amount': 1.04, 'num_of_emps': 2,

# '__init__': <function Employee.__init__ at 0x000001F34784EF28>,

# 'fullname': <function Employee.fullname at 0x000001F347852048>,

# 'apply_raise': <function Employee.apply_raise at 0x000001F3478520D0>,

# '__dict__': <attribute '__dict__' of 'Employee' objects>,

# '__weakref__': <attribute '__weakref__' of 'Employee' objects>, '__doc__': None}



print(Employee.num_of_emps) # 2

Python OOP classmethods


class Employee:

    raise_amount = 1.04

    num_of_emps = 0

    

    def __init__(self, first, last, pay):

        self.first = first

        self.last = last

        self.email = first + '.' + last + '@email.com'

        self.pay = pay



        Employee.num_of_emps += 1



    def fullname(self):

        return '{} {}'.format(self.first, self.last)

    

    def apply_raise(self):

        self.pay = int(self.pay * self.raise_amount)



    @classmethod

    def set_raise_amount(cls, amount):

        cls.raise_amount = amount



    @classmethod

    def from_string(cls, emp_str): # Alternative constructor

        first, last, pay = emp_str.split('-')

        return cls(first, last, pay)

        

emp_1 = Employee('Alex', 'Brown', 50000)

emp_2 = Employee('Lisa', 'Miller', 60000)





print(Employee.raise_amount) # 1.04

print(emp_1.raise_amount) # 1.04

print(emp_2.raise_amount) # 1.04



Employee.set_raise_amount(1.05)

print(Employee.raise_amount) # 1.05

print(emp_1.raise_amount) # 1.05

print(emp_2.raise_amount) # 1.05



emp_3 = Employee.from_string('Bob-Fox-70000')

print(emp_3.fullname()) # Bob Fox

Python OOP staticmethods


class Employee:

    raise_amount = 1.04

    num_of_emps = 0

    

    def __init__(self, first, last, pay):

        self.first = first

        self.last = last

        self.email = first + '.' + last + '@email.com'

        self.pay = pay



        Employee.num_of_emps += 1



    def fullname(self):

        return '{} {}'.format(self.first, self.last)

    

    def apply_raise(self):

        self.pay = int(self.pay * self.raise_amount)



    @classmethod

    def set_raise_amount(cls, amount):

        cls.raise_amount = amount



    @classmethod

    def from_string(cls, emp_str): # Alternative constructor

        first, last, pay = emp_str.split('-')

        return cls(first, last, pay)



    @staticmethod

    def is_workday(day):

        if day.weekday() == 5 or day.weekday() == 6: # Saturday or Sunday

            return False

        return True

        

emp_1 = Employee('Alex', 'Brown', 50000)

emp_2 = Employee('Lisa', 'Miller', 60000)





import datetime



my_date = datetime.date(2015,4,19)

print(Employee.is_workday(my_date)) # False

Python OOP Inheritance - Creating Subclasses


class Employee:

    raise_amount = 1.04

    num_of_emps = 0

    

    def __init__(self, first, last, pay):

        self.first = first

        self.last = last

        self.email = first + '.' + last + '@email.com'

        self.pay = pay



        Employee.num_of_emps += 1



    def fullname(self):

        return '{} {}'.format(self.first, self.last)

    

    def apply_raise(self):

        self.pay = int(self.pay * self.raise_amount)



    @classmethod

    def set_raise_amount(cls, amount):

        cls.raise_amount = amount



    @classmethod

    def from_string(cls, emp_str): # Alternative constructor

        first, last, pay = emp_str.split('-')

        return cls(first, last, pay)



    @staticmethod

    def is_workday(day):

        if day.weekday() == 5 or day.weekday() == 6: # Saturday or Sunday

            return False

        return True



class Developer(Employee):

    raise_amount = 1.10



    def __init__(self, first, last, pay, prog_lang):

        super().__init__(first, last, pay)

        # Employee.__init__(self, first, last, pay) # Same as before

        self.prog_lang = prog_lang



class Manager(Employee):



    def __init__(self, first, last, pay, employees=None):

        super().__init__(first, last, pay)

        if employees is None:

            self.employees = []

        else:

            self.employees = employees



    def add_emp(self, emp):

        if emp not in self.employees:

            self.employees.append(emp)



    def del_emp(self, emp):

        if emp in self.employees:

            self.employees.remove(emp)



    def print_emps(self):

        for emp in self.employees:

            print('=emp=', emp.fullname())





dev_1 = Developer('Alex', 'Brown', 50000, 'Python')

dev_2 = Developer('Lisa', 'Miller', 60000, 'JavaScript')



print(type(dev_1)) # <class '__main__.Developer'>

# print(help(Developer)) # Shows info on Developer class



print(dev_1.fullname()) # Alex Brown

print(dev_2.fullname()) # Lisa Miller



print(dev_1.prog_lang) # Python

print(dev_2.prog_lang) # JavaScript



print(dev_1.pay) # 50000

dev_1.apply_raise()

print(dev_1.pay) # 55000



mgr_1 = Manager('Jack', 'Russell', 70000)

mgr_1.add_emp(dev_1)

mgr_1.print_emps() # Alex Brown

mgr_1.add_emp(dev_2)

mgr_1.print_emps() # Alex Brown, Lisa Miller



print(isinstance(mgr_1, Manager)) # True

print(isinstance(mgr_1, Employee)) # True



print(isinstance(dev_1, Manager)) # False



print(issubclass(Manager, Employee)) # True

print(issubclass(Manager, Developer)) # False

Python OOP Special (Magic/Dunder) Methods

More info on Special (Magic/Dunder) Methods

Special method names.


class Employee:

    raise_amount = 1.04

    num_of_emps = 0

    

    def __init__(self, first, last, pay):

        self.first = first

        self.last = last

        self.email = first + '.' + last + '@email.com'

        self.pay = pay



        Employee.num_of_emps += 1



    def fullname(self):

        return '{} {}'.format(self.first, self.last)

    

    def apply_raise(self):

        self.pay = int(self.pay * self.raise_amount)



    # This method is used for debug. It makes print(cls) and repr(cls) look pretty

    def __repr__(self):

        return "Employee('{}', '{}', {})".format(self.first, self.last, self.pay)



    # This method is used for debug. It makes print(cls) and str(cls) look pretty

    def __str__(self):

        return '{} - {}'.format(self.fullname(), self.email)



    def __len__(self):

        return len(self.fullname())

        

emp_1 = Employee('Alex', 'Brown', 50000)

emp_2 = Employee('Lisa', 'Miller', 60000)



print(emp_1) # Alex Brown - Alex.Brown@email.com



print(repr(emp_1)) # Employee('Alex', 'Brown', 50000)

print(emp_1.__repr__()) # same as prev line

print(str(emp_1)) # Alex Brown - Alex.Brown@email.com

print(emp_1.__str__()) # same as prev line



print(len(emp_1)) # 10

Python OOP Property Decorators - Getters, Setters, and Deleters


class Employee:

    

    def __init__(self, first, last):

        self.first = first

        self.last = last



    @property

    def email(self):

        return '{}.{}@email.com'.format(self.first, self.last)



    @property

    def fullname(self):

        return '{} {}'.format(self.first, self.last)



    @fullname.setter

    def fullname(self, name):

        self.first, self.last = name.split(' ')

        

    @fullname.deleter

    def fullname(self):

        print('Deleted!')

        self.first = None

        self.last = None

        

emp_1 = Employee('Alex', 'Brown')

emp_2 = Employee('Lisa', 'Miller')



emp_1.first = 'Jim'

print(emp_1.fullname) # Jim Brown

print(emp_1.email) # Jim.Brown@email.com





emp_1.fullname = 'Jack Russell'



print(emp_1.first) # Jack

print(emp_1.fullname) # Jack Russell

print(emp_1.email) # Jack.Russell@email.com



del emp_1.fullname



print(emp_1.first) # None

print(emp_1.fullname) # None None

Source: CoreyMS.com