Python tem sido uma linguagem orientada a objectos desde que existe. Por causa disso, criar e usar classes e objetos é muito fácil. Este capítulo ajuda-o a tornar-se um especialista no uso do suporte à programação orientada a objetos do Python.
Se você não tem nenhuma experiência anterior com programação orientada a objetos (OO), você pode querer consultar um curso introdutório sobre ele ou pelo menos um tutorial de algum tipo para que você tenha uma compreensão dos conceitos básicos.
No entanto, aqui está uma pequena introdução à Programação Orientada a Objetos (OOP) para lhe trazer velocidade –
Visão geral da Terminologia OOP
-
Class – Um protótipo definido pelo usuário para um objeto que define um conjunto de atributos que caracterizam qualquer objeto da classe. Os atributos são membros de dados (variáveis de classe e variáveis de instância) e métodos, acessados via notação de pontos.
-
Variável de classe – Uma variável que é compartilhada por todas as instâncias de uma classe. Variáveis de classe são definidas dentro de uma classe, mas fora de qualquer método da classe. Variáveis de classe não são utilizadas com tanta freqüência quanto as variáveis de instância.
-
Membro de dados – Uma variável de classe ou de instância que contém dados associados a uma classe e seus objetos.
-
Sobrecarga de funções – A atribuição de mais de um comportamento a uma determinada função. A operação realizada varia pelos tipos de objetos ou argumentos envolvidos.
-
Variável de instância – Uma variável que é definida dentro de um método e pertence apenas à instância atual de uma classe.
-
Inheritance – A transferência das características de uma classe para outras classes que são derivadas dela.
-
Instance – Um objeto individual de uma determinada classe. Um objeto objeto que pertence a uma classe Circle, por exemplo, é uma instância da classe Circle.
-
Instantiation – A criação de uma instância de uma classe.
-
Método – Um tipo especial de função que é definida em uma definição de classe.
-
Objeto – Uma instância única de uma estrutura de dados que é definida pela sua classe. Um objeto compreende tanto membros de dados (variáveis de classe e variáveis de instância) quanto métodos.
-
Operator overloading – A atribuição de mais de uma função a um determinado operador.
Creating Classes
A declaração de classe cria uma nova definição de classe. O nome da classe segue imediatamente a palavra-chave classe seguida por dois pontos, como segue –
class ClassName: 'Optional class documentation string' class_suite
-
A classe tem uma cadeia de documentação, que pode ser acessada via ClassName.__doc__.
-
A class_suite consiste de todas as instruções componentes que definem os membros da classe, atributos de dados e funções.
Exemplo
A seguir é o exemplo de uma classe Python simples –
class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary
-
A variável empCount é uma variável de classe cujo valor é compartilhado entre todas as instâncias de uma classe. Isto pode ser acessado como Employee.empCount de dentro da classe ou fora da classe.
-
O primeiro método __init__() é um método especial, que é chamado de construtor de classe ou método de inicialização que Python chama quando você cria uma nova instância desta classe.
-
Você declara outros métodos de classe como funções normais, com a exceção de que o primeiro argumento para cada método é self. Python adiciona o argumento self à lista para você; você não precisa incluí-lo quando você chama os métodos.
Criando Objetos de Instância
Para criar instâncias de uma classe, você chama a classe usando o nome da classe e passa em quaisquer argumentos seu método __init__ aceita.
"This would create first object of Employee class"emp1 = Employee("Zara", 2000)"This would create second object of Employee class"emp2 = Employee("Manni", 5000)
Acesso a Atributos
Você acessa os atributos do objeto usando o operador de pontos com objeto. A variável de classe seria acessada usando o nome da classe da seguinte forma –
emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount
Agora, juntando todos os conceitos –
#!/usr/bin/pythonclass Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary"This would create first object of Employee class"emp1 = Employee("Zara", 2000)"This would create second object of Employee class"emp2 = Employee("Manni", 5000)emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount
Quando o código acima é executado, ele produz o seguinte resultado –
Name : Zara ,Salary: 2000Name : Manni ,Salary: 5000Total Employee 2
Você pode adicionar, remover, ou modificar atributos de classes e objetos a qualquer momento –
emp1.age = 7 # Add an 'age' attribute.emp1.age = 8 # Modify 'age' attribute.del emp1.age # Delete 'age' attribute.
Em vez de usar as instruções normais para acessar atributos, você pode usar as seguintes funções –
-
The getattr(obj, name) – para acessar o atributo de objeto.
-
The hasattr(obj,name) – para verificar se um atributo existe ou não.
-
The setattr(obj,name,value) – para definir um atributo. Se o atributo não existe, então ele seria criado.
-
The delattr(obj,name) – para excluir um atributo.
hasattr(emp1, 'age') # Returns true if 'age' attribute existsgetattr(emp1, 'age') # Returns value of 'age' attributesetattr(emp1, 'age', 8) # Set attribute 'age' at 8delattr(empl, 'age') # Delete attribute 'age'
Built-In Class Attributes
Todas as classes Python continuam seguindo atributos incorporados e podem ser acessadas usando o operador de pontos como qualquer outro atributo –
-
__dict__ – Dicionário contendo o namespace da classe.
-
__doc__ – Cadeia de documentação da classe ou nenhuma, se indefinida.
-
__nome__ – Nome da classe.
-
__módulo__ – Nome do módulo no qual a classe é definida. Este atributo é “__main__” no modo interativo.
-
__bases__ – Um tuple possivelmente vazio contendo as classes base, na ordem de sua ocorrência na lista de classes base.
Para a classe acima vamos tentar acessar todos estes atributos –
#!/usr/bin/pythonclass Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salaryprint "Employee.__doc__:", Employee.__doc__print "Employee.__name__:", Employee.__name__print "Employee.__module__:", Employee.__module__print "Employee.__bases__:", Employee.__bases__print "Employee.__dict__:", Employee.__dict__
Quando o código acima é executado, ele produz o seguinte resultado –
Employee.__doc__: Common base class for all employeesEmployee.__name__: EmployeeEmployee.__module__: __main__Employee.__bases__: ()Employee.__dict__: {'__module__': '__main__', 'displayCount':<function displayCount at 0xb7c84994>, 'empCount': 2, 'displayEmployee': <function displayEmployee at 0xb7c8441c>, '__doc__': 'Common base class for all employees', '__init__': <function __init__ at 0xb7c846bc>}
Destroying Objects (Garbage Collection)
Python elimina automaticamente os objetos desnecessários (tipos embutidos ou instâncias de classe) para liberar o espaço de memória. O processo pelo qual Python periodicamente recupera blocos de memória que não estão mais em uso é chamado de Garbage Collection.
Python’s garbage collector roda durante a execução do programa e é acionado quando a contagem de referência de um objeto chega a zero. A contagem de referência de um objeto muda quando o número de aliases que apontam para ele muda.
A contagem de referência de um objeto aumenta quando é atribuído um novo nome ou colocado em um recipiente (lista, tuple ou dicionário). A contagem de referência do objeto diminui quando ele é apagado com del, sua referência é reatribuída, ou sua referência sai do escopo. Quando a contagem de referência de um objeto chega a zero, Python o coleta automaticamente.
a = 40 # Create object <40>b = a # Increase ref. count of <40> c = # Increase ref. count of <40> del a # Decrease ref. count of <40>b = 100 # Decrease ref. count of <40> c = -1 # Decrease ref. count of <40>
Você normalmente não vai notar quando o coletor de lixo destrói uma instância órfã e recupera seu espaço. Mas uma classe pode implementar o método especial __del__(), chamado destruidor, que é invocado quando a instância está prestes a ser destruída. Este método pode ser usado para limpar quaisquer recursos que não sejam de memória utilizados por uma instância.
Exemplo
Este __del__() destructor imprime o nome da classe de uma instância que está prestes a ser destruída –
#!/usr/bin/pythonclass Point: def __init__( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "destroyed"pt1 = Point()pt2 = pt1pt3 = pt1print id(pt1), id(pt2), id(pt3) # prints the ids of the obejctsdel pt1del pt2del pt3
Quando o código acima é executado, ele produz o seguinte resultado –
3083401324 3083401324 3083401324Point destroyed
Note – Idealmente, você deve definir suas classes em um arquivo separado, então você deve importá-las no seu arquivo principal do programa usando o comando import.
Class Inheritance
Em vez de começar do zero, você pode criar uma classe derivando-a de uma classe preexistente, listando a classe pai entre parênteses após o novo nome da classe.
A classe filha herda os atributos da sua classe pai, e você pode usar esses atributos como se eles estivessem definidos na classe filha. Uma classe filha também pode sobrepor membros de dados e métodos do pai.
Sintaxe
As classes derivadas são declaradas muito parecidas com a sua classe pai; no entanto, uma lista de classes base a herdar é dada após o nome da classe –
class SubClassName (ParentClass1): 'Optional class documentation string' class_suite
Exemplo
#!/usr/bin/pythonclass Parent: # define parent class parentAttr = 100 def __init__(self): print "Calling parent constructor" def parentMethod(self): print 'Calling parent method' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Parent attribute :", Parent.parentAttrclass Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method'c = Child() # instance of childc.childMethod() # child calls its methodc.parentMethod() # calls parent's methodc.setAttr(200) # again call parent's methodc.getAttr() # again call parent's method
Quando o código acima é executado, ele produz o seguinte resultado –
Calling child constructorCalling child methodCalling parent methodParent attribute : 200
Modo simples, você pode conduzir uma classe a partir de múltiplas classes pai como segue –
class A: # define your class A.....class B: # define your class B.....class C(A, B): # subclass of A and B.....
Você pode usar as funções issubclass() ou isinstance() para verificar uma relação de duas classes e instâncias.
-
A função issubclass(sub, sup) boolean retorna verdadeiro se a subclasse dada é de fato uma subclasse da superclasse sup.
-
A função isinstance(obj, Class) boolean retorna true se obj for uma instância da classe Class ou for uma instância de uma subclasse da classe
Overriding Methods
Pode sempre substituir os métodos da sua classe pai. Uma razão para sobrepor os métodos da classe pai é porque você pode querer funcionalidades especiais ou diferentes na sua subclasse.
Exemplo
#!/usr/bin/pythonclass Parent: # define parent class def myMethod(self): print 'Calling parent method'class Child(Parent): # define child class def myMethod(self): print 'Calling child method'c = Child() # instance of childc.myMethod() # child calls overridden method
Quando o código acima é executado, ele produz o seguinte resultado –
Calling child method
Base Overloading Methods
A tabela seguinte lista algumas funcionalidades genéricas que você pode sobrepor nas suas próprias classes –
Sr.No. | Método, Descrição &Amostra de chamada |
---|---|
1 |
__init__ ( self ) Construtor (com qualquer argumento opcional) Amostra de chamada : obj = className(args) |
2 |
__del__( self ) Destrutor, apaga um objecto Amostra de Chamada : del obj |
3 |
__repr__( self ) Representação de cordas valorizáveis Amostras de Chamada : repr(obj) |
4 |
__str__( self ) Representação de cadeia de caracteres imprimível Amostras de Chamada : str(obj) |
5 |
__cmp__ ( self, x ) Comparação de objectos Amostras de Chamada : cmp(obj, x) |
Operadores de sobrecarga
Se você criou uma classe Vetor para representar vetores bidimensionais, o que acontece quando você usa o operador mais para adicioná-los? Muito provavelmente o Python irá gritar com você.
Pode, no entanto, definir o método __add__ em sua classe para realizar a adição de vetores e então o operador plus se comportaria como por expectativa –
Exemplo
#!/usr/bin/pythonclass Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b)v1 = Vector(2,10)v2 = Vector(5,-2)print v1 + v2
Quando o código acima é executado, ele produz o seguinte resultado –
Vector(7,8)
Esconder dados
Os atributos de um objeto podem ou não ser visíveis fora da definição da classe. Você precisa nomear atributos com um prefixo de sublinhado duplo, e esses atributos então não são diretamente visíveis para outsiders.
Exemplo
#!/usr/bin/pythonclass JustCounter: __secretCount = 0 def count(self): self.__secretCount += 1 print self.__secretCountcounter = JustCounter()counter.count()counter.count()print counter.__secretCount
Quando o código acima é executado, ele produz o seguinte resultado –
12Traceback (most recent call last): File "test.py", line 12, in <module> print counter.__secretCountAttributeError: JustCounter instance has no attribute '__secretCount'
Python protege esses membros alterando internamente o nome para incluir o nome da classe. Você pode acessar atributos como object._className__attrName. Se você substituir sua última linha como a seguinte, então ela funciona para você –
.........................print counter._JustCounter__secretCount
Quando o código acima é executado, ele produz o seguinte resultado –