Programming Paradigms

  • (examples are in Python unless otherwise noted)
  • called programming paradigms
  • main difference between different types is the handling of state
    • state: value of program's variables while it is running
    • Global state: value of program's global variables while it is running
  • to work professionally need to know procedural and at least one of the other two types
    • most often this will be OO and employers will expect you to know it

Procedural

  • write a series of steps moving towards a solution
  • each step changes the state
  • format: do('this') then: do('that')
  • you store data in global variables and then manipulate them with functions
    • fine for small programs, but once the program is large it because almost impossible to keep track of everything
  • relies on side effects...what happens when you change the state of a global variable...it's easy to accidentally cause unintended side effects
  • problems with procedural led to development of OO and Functional

Functional

  • addresses the problems that arise in procedural programming by eliminating global state
  • do not use global variables keep track of data by passing it as a parameter from one function to another
  • Python example:
    def increment(a):
      return a + 1
    only relies on data inside itself
  • an advantage is that it eliminates an entire category of errors caused by global state
  • a disadvantage is that certain problems are easier to conceptualize with state

Object-Oriented

  • also eliminates global state, but instead of storing state in functions like function, it stores state in objects
  • everything in Python is an object
  • create an object using a class
  • it is like a blueprint for creating objects
  • every object created is an instance of a class
  • class names are always capitalized and in camel case
  • create new object with ObjectName(), called instantiating a class
  • define a method inside a class then you can call the method/s on the created objects
    • method names should be lowercase with underscores
    • def __init__(self): called every time a new object is created
    • methods that start and end with __ are called magic methods
    • methods must take at least one param, because when they are called the object is passed to the method
  • Python example:
    class Orange:
      
        def __init__(self):
            print('Created!')
      
    orange = Orange()
    created the object orange and prints Created!
  • in a class you can define instance variables, a variable that belongs to an object
    • should be defined in __init__ function except in special cases
    • example:
      class Orange:
          def __inti__(self, w, c):
              self.weight = w
              self.weight = c
              print("Created!")
      
      orange_one = Orange(2, 'orange')
      orange_two = Orange(9, 'light orange')
      orange_three = Orange(7, 'dark orange')
      
      print(orange_one)
      print(orange_one.weight)
      print(orange_one.color)
      print(\n)
      
      print(orange_two)
      print(orange_two.weight)
      print(orange_two.color)
      print(\n)
      
      print(orange_three)
      print(orange_three.weight)
      print(orange_three.color)
      prints
      <__main>>.Orange object at 0x10576d0b9>
      2
      orange
      
      <__main>>.Orange object at 0x1057c8c88>
      9
      light orange
      
      <__main>>.Orange object at 0x1057c8cc0>
      7
      dark orange
    • can change instance variables with object_name.ins_variable_name
  • can define methods
    • continuation of previous example:
          def rot(self, days, temp):
              self.mold = days * temp
      
      orange_one.rot = (6, 0)
      print(orange_one.mold)
      orange_one.rot = (10, 98)
      print(orange_one.mold)
      prints
      0
      980
  • OO allows you to model a 'has a' relationship by storing an object as a variable in another object
    • this is composition
    • example:
      class Dog():
          def __init__(self, name, breed, owner):
              self.name = name
              self.breed = breed
              self.owner = owner
      
      class Person():
          def __init__(self, name):
              self.name = name
      
      mick = Person('Mick Jagger')
      stan = Dog('Stanley', 'Bulldog', mick)  # pass ina Person object as an argument
      print(stan.owner.name)
      prints Mick Jagger
  • OO advantages:
    • encourages code reuse
    • thus decreases amount of time developing and maintaining code
    • encourages breaking problems up
    • code that is easy to maintain
  • OO disadvantages;
    • takes extra effort
    • great deal of planning

Variable Types

  • class variables
    • belong to both the object and the objects class
    • can share variables between all the instances of a class without global variables (these are static variables in java)
    • create by making a variable inside a class but without self
    • allows you to share data between all instances of the class
    • example:
      class Rectangle:
          recs = []
      
          def __init__(self, width, height):
              self.width = width
              self.height = height
              self.recs.append((self.width, self.height))
      
          def calculate_perimeter(self):
              return 2 * (self.width + self.height)
      
          def print_size(self):
              print('{} by {}'.format(self.width, self.height))
      
      rect_one = Rectangle(3, 4)
      rect_two = Rectangle(9, 9)
      print(Rectangle.recs)
      prints [(3, 4), (9, 9)]
      • every time you create a new Rectangle it is added to the list
  • instance variables
    • belong to objects

Four Pillars of OO

Encapsulation

  1. objects group variables, which hold state, and methods that alter their state, in a single unit -- the object
  2. hiding a class's internal data to prevent the client(code from outside the class) from directly accessing it
  • private variables and private methods: variables and methods that objects can access but clients cannot
  • Python doesn't have private variables, so they address the problem with naming conventions
    • a variable or method that they shouldn't use will be preceded with an underscore _unsafe_variable _unsafe_method()

Abstraction

  • process of 'taking away or removing characteristics from something to reduce it to a set of essential characteristics'

Polymorphism

  • the ability in programming to present the same interface for different data types
    • example: the print function is an example of this...you don't need different print functions for different types of data, i.e. print_int, print_float, print_string

Inheritance

  • classes can inherit methods and variables from another class
  • class inherited from is the parent class, class that inherits is the child class
    • pass the name of the parent to the child when you create it
  • a child can override the parent method by defining a method with the same name
  • every object in Python inherits from the parent class Object
    • example:
      class Lion:
          def __init__(self, name):
              self.name = name
      
      lion = Lion('Dilbert')
      print(lion)
      prints <__main__.Lion object at 0x104e64128> (its type and location in memory) because of the __repr__ method in Object. You can override this method.
      class Lion:
          def __init__(self, name):
              self.name = name
      
          def __repr__(self):
              return self.name
      
      lion = Lion('Dilbert')
      print(lion)
      now it prints 'Dilbert'
    • example: integers have a magic method __add__. If you override this method you can make then do whatever you want when you 'add' them

Copyright © 2022