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:
only relies on data inside itselfdef increment(a): return a + 1
- 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:
created the objectclass Orange: def __init__(self): print('Created!') orange = Orange()
orange
and printsCreated!
- 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:
printsclass 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)
<__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
- should be defined in
- can define methods
- continuation of previous example:
printsdef 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)
0 980
- continuation of previous example:
- OO allows you to model a 'has a' relationship by storing an object as a variable in another object
- this is composition
- example:
printsclass 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)
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:
printsclass 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)
[(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
- objects group variables, which hold state, and methods that alter their state, in a single unit -- the object
- 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()
- a variable or method that they shouldn't use will be preceded with an underscore
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
- example:
the print function is an example of this...you don't need different print functions for different types of data,
i.e.
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:
printsclass Lion: def __init__(self, name): self.name = name lion = Lion('Dilbert') print(lion)
<__main__.Lion object at 0x104e64128>
(its type and location in memory) because of the__repr__
method in Object. You can override this method.
now it printsclass Lion: def __init__(self, name): self.name = name def __repr__(self): return self.name lion = Lion('Dilbert') print(lion)
'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
- example: