(Programação orientada a objetos com Python)
Daniel Moser
Feb 14th, 2017
2nd IAG Python Boot Camp
Table of contents
OOP is a programming paradigm. It is usually compared with the traditional procedural programming.
The procedural programming is based on procedures (i.e., routines and sub-routines), where the procedures and data variables are independent. Examples: Cobol, C, Fortran...
program Fibonacci; function fib(n: Integer): Integer; var a: Integer = 1; b: Integer = 1; f: Integer; i: Integer; begin if (n = 1) or (n = 2) then fib := 1 else begin for i := 3 to n do begin f := a + b; b := a; a := f; end; fib := f; end; end; begin WriteLn(fib(6)); end.
OOP is based in objects, a variable that combines methods (procedures) and attributes (data).
Examples of OOP compatible languages: C#, C++, Java, Lisp, Python, Ruby...
class Fibonacci: def __init__(self): self.cache = {} def fib(self, n): if self.cache.has_key(n): return self.cache[n] if n == 1 or n == 2: return 1 else: a = 1 b = 1 for i in range(2, n): f = a + b; b = a; a = f; self.cache[n] = f; return f; fibonaccyCounter = Fibonacci() # print(fibonaccyCounter.fib(600)) # %time fibonaccyCounter.fib(600) # %time fibonaccyCounter.fib(600)
Why OOP compatible? Because usually in a OOP language one can still work as a procedural language...
Examples of pure OOP languages: Smalltalk and Self.
"Class has no life, it's just a concept."
class testing: """This is a IAG Python Boot Camp class definition""" def __init__(self, init_value): """This is a constructor""" self.some_value = init_value return def double_attr(self): """This is a method that double the ``some_value`` atribute""" self.some_value *= 2 return
class Pets(object): owner = "Python Boot Camp" def __init__(self, name, age, condition='healthy'): print("A new pet entry!") self.name = name self.age = age self.condition = condition def __repr__(self): return "Pet '{0}', {1} year(s)".format(self.name, self.age) class Dog(Pets): def bark(self): print(" Woof-woof!!") return class Monkey(Pets): def __init__(self, name, age, condition=''): """Overwriting the Pets() constructor""" condition = 'custom' Pets.__init__(self, name, age, condition) def gibber(self): print(" (gibber)!!") return class Horse(Pets): def __init__(self, name, age): super(Horse, self).__init__(name, age) def neigh(self): print(" Neigh!!") return class Cat(Pets): def __init__(self): super(Pets, self).__init__() def meow(self): print(" Meow!!") return
class Toys: color = 'light blue' class Lassie(Pets, Toys): pass
Must read: Python’s super() considered super!
class A(object): def __init__(self, a, b, c): self.a = a self.b = b self.c = c def addNums(): self.b + self.c class B(object): def __init__(self, d, e): self.d = d self.e = e def addAllNums(self, Ab, Ac): x = self.d + self.e + Ab + Ac return x ting = A("yo", 2, 6) ling = B(5, 9) print ling.addAllNums(ting.b, ting.c)
class A(object): def __init__(self, a, b, c): self.a = a self.b = b self.c = c def addNums(): self.b + self.c class B(object): def __init__(self, d, e, A): self.d = d self.e = e self.A = A def addAllNums(self): x = self.d + self.e + self.A.b + self.A.c return x ting = A("yo", 2, 6) ling = B(5, 9, ting) print ling.addAllNums()
class A(object): def __init__(self, a, b, c): self.a = a self.b = b self.c = c def addNums(): self.b + self.c class B(object): def __init__(self, d, e): self.d = d self.e = e self.A = A("yo", 2, 6) def addAllNums(self): x = self.d + self.e + self.A.b + self.A.c return x ling = B(5, 9) print ling.addAllNums()
Remember: those "association/combination" names may vary in the literature.
class C(object): def __init__(self): self.a = 1 # OK to access directly self._a = 2 # should be considered private self.__a = 3 # considered private, name Disfigured
Warning! Some people say that *encapsulation* can prevent the data from being modified. This is **not** the case in Python (and even Java[!]. Other methods need to used to avoid modification).
class Person(object): def pay_bill(): raise NotImplementedError class Millionare(Person): def pay_bill(): print "Here you go! Keep the change!" class GradStudent(Person): def pay_bill(): print "Can I owe you ten bucks or do the dishes?"
import scipy scipy.interpolate scipy.interpolate.quad scipy.integrate
As far as the function in_the_forest is concerned, the Person object is a duck:
class Duck: def quack(self): print("Quaaaaaack!") def feathers(self): print("The duck has white and gray feathers.") class Person: def quack(self): print("The person imitates a duck.") def feathers(self): print("The person takes a feather from the ground and shows it.") def name(self): print("John Smith") def in_the_forest(duck): duck.quack() duck.feathers() def game(): donald = Duck() john = Person() in_the_forest(donald) in_the_forest(john) game()
Advantages of OOP:
Disadvantages of OOP
This kind of tools can be used, for example, together with abstraction level concepts for automatic programming (or automatic coding)!
class test: def __init__(self): print "init 1" def __init__(self): print "init 2"
"""http://python-3-patterns-idioms-test.readthedocs.io/en/latest/ChangeInterface.html""" class WhatIHave: def g(self): pass def h(self): pass class WhatIWant: def f(self): pass class ProxyAdapter(WhatIWant): def __init__(self, whatIHave): self.whatIHave = whatIHave def f(self): # Implement behavior using # methods in WhatIHave: self.whatIHave.g() self.whatIHave.h() class WhatIUse: def op(self, whatIWant): whatIWant.f() # Approach 2: build adapter use into op(): class WhatIUse2(WhatIUse): def op(self, whatIHave): ProxyAdapter(whatIHave).f() # Approach 3: build adapter into WhatIHave: class WhatIHave2(WhatIHave, WhatIWant): def f(self): self.g() self.h() # Approach 4: use an inner class: class WhatIHave3(WhatIHave): class InnerAdapter(WhatIWant): def __init__(self, outer): self.outer = outer def f(self): self.outer.g() self.outer.h() def whatIWant(self): return WhatIHave3.InnerAdapter(self) whatIUse = WhatIUse() whatIHave = WhatIHave() adapt= ProxyAdapter(whatIHave) whatIUse2 = WhatIUse2() whatIHave2 = WhatIHave2() whatIHave3 = WhatIHave3() whatIUse.op(adapt) # Approach 2: whatIUse2.op(whatIHave) # Approach 3: whatIUse.op(whatIHave2) # Approach 4: whatIUse.op(whatIHave3.whatIWant())