associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

Diferenças para "IntroducaoOop"

Diferenças entre as versões de 1 e 24 (23 versões de distância)
Revisão 1e 2005-11-14 09:16:16
Tamanho: 18480
Comentário: Original em inglês
Revisão 24e 2008-09-26 14:06:23
Tamanho: 30484
Editor: localhost
Comentário: converted to 1.6 markup
Deleções são marcadas assim. Adições são marcadas assim.
Linha 1: Linha 1:
Introduction

I've been programming with Python for over two years now [1]. I had done some procedural programming about eight years previously - but I wasn't familiar with objects or OOP.

The whole design philosophy of Python encourages a clean programming style. It's basic datatypes and system of namespaces makes it easier to write elegant, modular code [2].

These factors, and the unique block structure by indentation rule, make Python an ideal first language. Despite this I struggled with learning classes and objects. It seemed a huge hurdle to overcome, like all new systems do.

In fact the basic principles of object oriented programming are relatively easy to learn. Like other aspects of Python they are nicely implemented and well thought out. This tutorial is the introduction to object oriented programming that I wished I'd had back then.

This article assumes a basic knowledge of Python syntax. If you know how to create the basic data-types and call functions, but want to know more about objects and classes - you should find this article helpful.
Objects and OOP

Objects and OOP are at the heart of the way Python works. You aren't forced to use the OOP paradigm in your programs - but understanding the concepts is essential to becoming anything more than a beginner. Not least because you will need to use the classes and objects provided in the standard library.

=OOP the New Paradigm=

Programming itself is a relatively young discipline. Surprisingly, object oriented programming goes back as far as the 1960's. Simula is considered to be the first object oriented programming language.

It's not an uncontroversial paradigm, in fact it's not even clear what a strict definition of Object Oriented programming is.

Some people think that OOP has nearly had it's day, and we need to find the Post OOP Paradigm.

Others like Paul Graham think it was never necessary in the first place.

So What is an Object ?

What is an Object ? Well, this is programming - so an object is a concept. Calling elements of our programs objects is a metaphor - a useful way of thinking about them.

In Python the basic elements of programming are things like strings, dictionaries, integers, functions, and so on [3] ... They are all objects [4]. This means they have certain things in common.

Before we look closer at what this means we'll hurriedly cover some basic programming concepts.
Procedural Programming

If you have done any programming before, you will be familiar with the procedural style of programming. This divides your program into reusable 'chunks' called procedures or functions [5].

As much as possible you try to keep your code in these modular chunks - using logic to decide which chunk is called. This makes it less mental strain to visualise what your program is doing. It also makes it easier to maintain your code - you can see which parts does what job. Improving one function (which is reused) can improve performance in several places of your program.

Note

For an interesting look at the development of procedural programming, read a mini history of programming
Data Separation

The procedural style of programming maintains a strict separation between your code and your data.

You have variables, which contain your data, and procedures. You pass your variables to your procedures - which act on them and perhaps modify them.

If a function wants to modify the contents of a variable by passing it to another function it needs access to both the variable and the function it's calling. If you're performing complex operations this could be lots of variables and lots of functions.
Enter the Object

Basic Elements of OOP

Any traditional OOP programmer might tell you that essential elements of OOP are encapsulation and message passing.

The Python equivalents are namespaces and methods.

Python doesn't subscribe to protecting the code from the programmer, [6] like some of the more BSD languages. Python does encapsulate objects as a single namespace but it's a transluscent encapsulation. Smile

It turns out that lots of operations are common to objects of the same type. For example most languages have built in ways to create a lowercase version of a string.

There are lots of standard operations that are associated only with strings. These include making a lowercase version, making an uppercase version, splitting the string up, and so on. In an object oriented language we can build these in as properties of the string object. In Python we call these methods [7].

Every string object has a standard set of methods - some of which you've probably already used.

For example :
original_string = ' some text '

# remove leading and trailing whitespace
string1 = original_string.strip()

# make uppercase
## page was renamed from IntroducaoOOP
## page was renamed from IntroduçãoaOOP
Tradução do "Introduction to OOP with Python" do site www.voidspace.org.uk

= Introdução =

Eu tenho programado com Python por mais de 2 anos [1]. Antes, havia feito alguma programação procedural por cerca de 8 anos - mas eu não estava familiarizado com objetos ou OOP.

A filosofia usada no design da Python encoraja um estilo de programação limpo. Os seus tipos de dados básicos (datatypes) e o sistema de espaço de nomes (namespaces) facilitam a escrita de código elegante e modular [2].

Estes fatores, mais a peculiar regra de estruturação de bloco por indentação, tornam a Python uma linguagem ideal para iniciantes. Apesar disso, eu tive dificuldades em aprender sobre classes e objetos. Foi um grande obstáculo a ser vencido, assim como são todos os novos sistemas.

De fato os princípios básicos da programação orientada a objetos são relativamente fáceis de aprender. Assim como outros aspectos da Python, eles são bem concebidos e implementados. Este tutorial é uma introdução a programação orientada a objetos, que eu gostaria de ter tido quando precisei aprender tais princípios.

Este artigo assume um conhecimento básico da sintaxe da Python. Se você sabe como criar os tipos de dados básicos e chamar funções, mas quer saber mais sobre objetos e classes - então você achará esse artigo extremamente útil.

= Objetos e OOP =

Objetos e OOP estão no coração do modo como a Python funciona. Você não é forçado a usar o paradigma OOP em seus programas - mas entender os conceitos é essencial para se tornar algo mais que um iniciante. Mesmo porque, você precisará usar as classes e objetos fornecidos pela biblioteca padrão da linguagem.

= OOP o Novo Paradigma =

A programação de computadores é uma disciplina relativamente nova. Surpreendentemente, a programação orientada a objetos data da longínqua década de 60. Simula é considerada a primeira linguagem de programação orientada a objetos.

A OOP não é um paradigma incontroverso, de fato não é claro o que venha a ser uma definição exata de Programação Orientada a Objetos.

Algumas pessoas acham que a OOP já teve a sua chance, e nós já deveríamos procurar pelo paradigma pós-OOP.

Outros como Paul Graham acham que, em primeiro lugar, a OOP nunca foi necessária.

= Então, o quê é um Objeto? =

O quê é um Objeto? Bem, estamos falando de programação - portanto um objeto é um conceito. Chamar elementos de nossos programas de objetos é uma metáfora - um modo útil de pensar sobre eles.

Em Python os elementos básicos da programação são coisas como strings, dicionários, inteiros, funções, e assim por diante [3] ... Todos eles são objetos [4]. Isto significa que eles possuem certas coisas em comum.

Antes de olharmos mais de perto o que isto significa, nós iremos rapidamente cobrir alguns conceitos básicos de programação.

= Programação Procedural =

Se você já programou antes, você deve estar familiarizado com o estilo procedural de programação. Neste estilo, você divide o seu programa em 'pedaços' reutilizáveis chamados procedimentos (procedures) ou funções (functions) [5].

Sempre que possível você tenta manter o seu código nestes pedaços modulares - usando a lógica para decidir qual pedaço é chamado. Este estilo faz com que você não se esforce tanto ao visualizar o que o seu programa está fazendo. Ele também facilita a manutenção do seu código - você pode ver quais partes fazem o quê. Ao melhorar uma função (que é reutilizada) você pode, consequentemente, melhorar a performance em várias partes do seu programa.

===== Nota =====

Para um visão interessante do desenvolvimento da programação procedural, leia uma mini história da programação

= Separação de Dados =

O estilo de programação procedural mantém uma estrita separação entre o seu código e seus dados.

Você tem variáveis, que contém os seus dados, e procedimentos. Você passa suas variáveis para os seus procedimentos - que ajem sobre elas e talvez até as modifiquem.

Se uma função quer modificar o conteúdo de uma variável ao passá-la para outra função, ela necessita acesso a ambas, variável e função chamada. Se você realizar operações complexas isto pode compreender o uso de muitas variáveis e muitas funções.

= Entra o Objeto =

== Elementos Básicos da OOP ==

Qualquer programador OOP experiente lhe dirá que os elementos essênciais da OOP são encapsulamento e passagem de mensagens.

Os equivalentes destes elementos na Python são namespaces e métodos.

A Python não adota o conceito de proteger (ocultar) o código do programador, [6] assim como a maioria das linguagens BSD. Ela encapsula os objetos em um namespace, mas através de um encapsulamento translúcido. :)

Isso leva a conclusão de que muitas operações são comuns a objetos do mesmo tipo. Por exemplo, a maioria das linguagens possuem modos nativos de criar uma versão ''somente em minúsculas'' (caixa baixa) de uma string.

Existem várias operações padrão que estão associadas apenas a strings. Dentre elas temos, por exemplo, retornar uma versão em minúsculas, retornar uma versão em maiúsculas, particionar a string, e assim por diante. Em uma linguagem orientada a objetos nós podemos embutir essas operações como propriedades do objeto string. Em Python nós chamamos estas operações de métodos [7].

Todo objeto string possui um conjunto padrão de métodos - alguns dos quais você provavelmente já usou.

Por exemplo :

{{{#!python
string_original = ' algum texto '

# remove espaços em branco no início e fim da string
string1 = string_original.strip()

# retorna uma versão em maiúsculas
Linha 74: Linha 84:
SOME TEXT

# make lowercase
ALGUM TEXTO

# retorna uma versão em minúsculas
Linha 79: Linha 89:

Python uses the dot syntax to access attributes of objects. The statement string2.lower() means call the lower method of the object string2. This method returns a new string - the result of calling the method.

So every string is actually a string object - and has all the methods of a string object [8]. In Python terminology we say that all strings are of the string type.

In the object model the functions (methods) and other attributes that are associated with a particular kind of object become part of the object. The data and the functions for dealing with it are no longer separate - but are bound together in one object.
Creating New Objects

Let's look a bit more clearly at what's going on.

In Python there is a blueprint string object called the string type. It's actual name is str. It has all the methods and properties associated with the string.

Everytime a new string is created, the blueprint is used to create a new object with all the properties of the blueprint.

All the built in datatypes have their own 'blueprint' - the integer (int), the float (float), booleans (bool), lists (list), dictionaries (dict), and more.

For these built in datatypes, we can either use normal Python syntax to create them - or we can use the blueprint itself (the type).
# create a dictionary the normal way
a_dict = {
}}}

A Python usa a sintaxe de ponto para acessar os atributos dos objetos. A instrução string2.lower() significa chamar o método lower do objeto string2. Este método retorna uma nova string - o resultado da chamada ao método.

Então toda string é atualmente um objeto string - e tem todos os métodos de um objeto string [8]. Na terminologia da Python nós dizemos que todas as strings são do tipo string.

No modelo de objetos as funções (métodos) e outros atributos que estão associados a um tipo particular de objeto, tornam-se parte do objeto. Os dados, e as funções que lidam com esses dados não estão mais separados - mas '''empacotados''' juntos no objeto.

== Criando Novos Objetos ==

Olhemos mais claramente para o que está acontecendo.

Em python existe um objeto de modelo para o tipo string. Seu nome real é str. Ele tem todos os métodos e propriedades associadas com a string.

Toda vez que uma nova string é criada, o modelo é usado para criar um novo objeto com todas as propriedades do modelo.

Todos os tipo de dados nativos têm seu próprio "modelo" - o inteiro (int), o ponto flutante (float), booleanos (bool), listas (list), dicionários (dict), e mais.

Para estes tipo de dados nativos, nós podemos ou usar a sintaxe normal da Python para criá-los - ou nós podemos usar o próprio modelo (o tipo).

{{{#!python
# cria um dicionário da forma normal
dicionario = {
    'chave' : 'valor',
    'chave2' : 'valor2'
    }
# usa 'dict' para criá-lo
lista_de_tuplas = [('chave', 'valor'),
                 ('chave2', 'valor2')]
outro_dicionario = dict(lista_de_tuplas)
#
print dicionario == outro_dicionario
True
print type(dicionario)
<type 'dict'>
print type(outr_dicionario)
<type 'dict'>
}}}

Veja como nós criamos o objeto outro_dicionario por passar uma lista de tuplas para o dicionário. São coisas básicas, mas ilustram que novos objetos são criados a partir de modelos. Estes objetos têm todos os métodos definidos no modelo.

O novo objeto é chamado 'instância' - e o processo de criá-lo é chamado 'instanciação' (isto é, a criação de uma instância). Para os tipos de dados nativos o modelo é conhecido como o tipo do objeto. Você pode testar o tipo de um objeto por usar a função nativa 'type' [9].

Pode parecer muito para digerir - mas isso provavelmente não envolve nada que você já não conheça.

= Python como uma Linguagem Orientada a Objeto =

## If you scour the internet you may find some unhelpful discussion as to whether ## Python is really object oriented or not. (For some value of object oriented). This ## debate is particularly beloved of Ruby programmers who like to claim thier language is ## more object oriented than Python.

Se você fizer uma busca pela internet poderá encontrar algumas discussões inúteis sobre se Python é ou não orientado a objeto. Este debate é particularmente amado pelos programadores Ruby que como reivindicam que sua linguagem é mais orientada a objeto do que Python.

Isso parece vir dos dias pré-Python 2.2 quando existia uma grande diferença entre os tipos nativos e as classes definidas pelo usuário. Desde a 2.2 você pode fazer classes que herdam de tipos nativos. Na Python 3.0 a unificação será completa.

## We've already seen an example of using some string methods. We'll close off this ## section by using some dictionary methods.

Nós já vimos um exemplo usando alguns métodos de string. Nós fecharemos esta seção usando alguns métodos de dicionário.

{{{#!python
um_dicionario = {
Linha 101: Linha 151:
# use 'dict' to create one
list_of_tuples = [('key', 'value'),
                 ('key2', 'value2')]
a_dict_2 = dict(list_of_tuples)
outro_dicionario = um_dicionario.copy()
print um_dicionario == outro_dicionario
True
um_dicionario.clear()
print um_dicionario
{}
print um_dicionario.clear
<built-in method clear of dict object at 0x0012E540>
print type(um_dicionario.clear)
<type 'builtin_function_or_method'>
}}}

## Above we used the clear method of a_dict by calling a_dict.clear(). When we printed ## clear, instead of calling it, we can see that it's just another object. It's a ## method object of the appropriate type.

Acima nós usamos o método 'clear' da variável 'um_dicionario' chamando 'um_dicionario.clear()'. Quando nós imprimos 'clear', em vez de chamá-lo, podemos ver que é apenas outro objeto. É um objeto de método do tipo apropriado.

## Functions are Objects

== Funções são Objetos ==

## Just to demonstrate that functions are objects, I'll show you a trick with them.

Apenas para mostrar que funções são objetos, mostrarei um truque elegante com elas.

## Have you ever written code that looks a bit like this ?

Você já escreveu código parecido com este ?

{{{#!python
if valor == 'um':
    # faça alguma coisa
    funcao1()
elif valor == 'dois':
    # faça outra coisa
    funcao2()
elif valor == 'três':
    # faça outra coisa
    funcao3()
}}}

## Other languages have a construct called switch that makes writing code like that a bit easier.

Outras linguagens tem uma construção chamada 'switch' que escreve código como o anterior de uma maneira mais fácil.

## In Python we can achieve the same thing (in less lines of code) using a dictionary of functions.

Em Python nós podemos conseguir a mesma coisa (em um menor número de linhas de código) usando dicionário de funções.

## As an example, suppose we have three functions. You want to call one of the functions, depending on the value in a variable called choice.

Como exemplo, suponha que tenhamos três funções. Você quer chamar uma das funções, dependendo do valor na variável chamada 'escolha'.

{{{#!python
def funcao1():
    print 'Você escolheu um.'
def funcao2():
    print 'Você escolheu dois.'
def funcao3():
    print 'Você escolheu três.'
Linha 106: Linha 211:
print a_dict == a_dict_2
True
print type(a_dict)
<type 'dict'>
print type(a_dict_2)
<type 'dict'>

See how we created a_dict_2 by passing a list of tuples to dict. All basic stuff, but it illustrates that new objects are created from blueprints. These objects have all the methods defined in the blueprint.

The new object is called an instance - and the process of creating it is called instantiation (meaning creating an instance). For the built in datatypes the blueprint is known as the type of the object. You can test the type of an object By using the built in function type [9].

That might seem like a lot to digest in one bite - but it probably doesn't involve anything you don't do already.

Python as an Object Oriented Language

If you scour the internet you may find some unhelpful discussion as to whether Python is really object oriented or not. (For some value of object oriented). This debate is particularly beloved of Ruby programmers who like to claim thier language is more object oriented than Python.

This seems to come from the pre Python 2.2 days when there was a big difference between the built in types and user defined classes. Since 2.2 you can subclass the built in types. In Python 3.0 the unification will be complete.

We've already seen an example of using some string methods. We'll close off this section by using some dictionary methods.
a_dict = {
    'key' : 'value',
    'key2' : 'value2'
    }
a_dict_2 = a_dict.copy()
print a_dict == a_dict_2
True
a_dict.clear()
print a_dict
{}
print a_dict.clear
<built-in method clear of dict object at 0x0012E540>
print type(a_dict.clear)
<type 'builtin_function_or_method'>

Above we used the clear method of a_dict by calling a_dict.clear(). When we printed clear, instead of calling it, we can see that it's just another object. It's a method object of the appropriate type.
Functions are Objects

Just to demonstrate that functions are objects, I'll show you a neat trick with them.

Have you ever written code that looks a bit like this ?
if value == 'one':
    # do something
    function1()
elif value == 'two':
    # do something else
    function2()
elif value == 'three':
    # do something else
    function3()

Other languages have a construct called switch that makes writing code like that a bit easier.

In Python we can achieve the same thing (in less lines of code) using a dictionary of functions.

As an example, suppose we have three functions. You want to call one of the functions, depending on the value in a variable called choice.
def function1():
    print 'You chose one.'
def function2():
    print 'You chose two.'
def function3():
    print 'You chose three.'
#
# switch is our dictionary of functions
# 'switch' é nosso dicionário de funções
Linha 171: Linha 213:
    'one': function1,
    'two': function2,
    'three': function3,
    'um': funcao1,
    'dois': funcao2,
    'três': funcao3,
Linha 176: Linha 218:
# choice can eithe be 'one', 'two', or 'three'
choice = raw_input('Enter one, two, or three :')
# escolha pode ser 'um', 'dois', ou 'três'
escolha = raw_input('Enter um, dois, or três :')
Linha 179: Linha 221:
# call one of the functions # chama uma das funções
Linha 181: Linha 223:
    result = switch[choice]     resultado = switch[escolha]
Linha 183: Linha 225:
    print 'I didn\'t understand your choice.'     print 'Não entendi sua escolha.'
Linha 185: Linha 227:
    result()

The magic happens in the line result = switch[choice]. switch[choice] returns one of our function objects (or raises a KeyError). The we do result(), which calls it. Smile

Caution!

You could save a line or two of code by making the final block :
# call one of the functions
    resultado()
}}}

##
The magic happens in the line result = switch[choice]. switch[choice] returns one of our function objects (or raises a KeyError). The we do result(), which calls it. Smile
A mágica ocorre na linha {{{resultado = switch[escolha]}}}. {{{switch[escolha]}}} retorna uma de nossos objetos do tipo função (ou levanta uma exceção KeyError). :)

##
Caution!  '''Cuidado!'''

##
You could save a line or two of code by making the final block :
Você poderia eliminar uma linha ou duas por fazer o bloco final desta forma:
{{{#!python
# chama uma das funções
Linha 194: Linha 241:
    switch[choice]()     switch[escolha]()
Linha 196: Linha 243:
    print 'I didn\'t understand your choice.'

This directly calls the function returned by switch[choice]. However, if that function raises a KeyError (due to a bug) - it will get trapped by the try...except block. This error can be very hard to track down, because your error handling code is reporting the wrong error.

In general you should have your try...except blocks wrapping as little code as possible.
User Defined Classes

The real trick is that we can create our own blueprints. These are called classes. We can define our own class of object - and from this create as many instances of this class as we want. All the instances will be different - depending on what data they are given when they are created. They will all have the methods (and other properties) from the blueprint - the class.

So lets look at a simple example. We define our own class using the class keyword.

Methods are defined like functions - using the def keyword. They are indented to show that they are inside the class.
class OurClass(object):
    """Class docstring."""
    print 'Eu não entendi a sua escolha.'
}}}

##
This directly calls the function returned by switch[choice]. However, if that function raises a KeyError (due to a bug) - it will get trapped by the try...except block. This error can be very hard to track down, because your error handling code is reporting the wrong error.
Esta forma chama diretamente a função retornada por {{{switch[escolha]}}}. No entanto, se aquela função levanta uma exceção KeyError (devido a um bug) - e exceção será capturada pelo bloco try...except. Esse erro pode ser bem difícil de encontrar, porque o seu código de tratamento de erros está reportando o erro errado.


##
In general you should have your try...except blocks wrapping as little code as possible.
Em geral você deve ter seus blocos try...except encobrindo o mínimo de código possível.

##
User Defined Classes
== Classes Definidas Pelo Usuário ==

##
The real trick is that we can create our own blueprints. These are called classes. We can define our own class of object - and from this create as many instances of this class as we want. All the instances will be different - depending on what data they are given when they are created. They will all have the methods (and other properties) from the blueprint - the class.
O truque real é que nós podemos criar nossos próprios modelos, chamados de classes. Nós podemos definir nosso pŕoprio tipo de objeto - e assim criar quantas instâncias desta classe quanto quisermos. Todas as instâncias serão diferentes - dependendo que dados são guardados nelas quando criadas. Elas terão todos os métodos (e outras propriedades) do modelo - a classe.

##
So lets look at a simple example. We define our own class using the class keyword.
Vamos então ver um exemplo simples. Nós podemos definir nossa própria classe usando a palavra-chave {{{class}}}.

##
Methods are defined like functions - using the def keyword. They are indented to show that they are inside the class.
Métodos são definidos como funções - usando a palavra-chave {{{def}}}. Eles são identados para mostrar que estão dentro da classe.

{{{#!python
class Nossa
Classe(object):
    """Docstring da classe."""
Linha 212: Linha 270:
        """Method docstring."""         """Docstring do método."""
Linha 216: Linha 274:
    def printargs(self):
        """Method docstring."""
    def imprime_args(self):
        """Docstring do método."""
Linha 220: Linha 278:

I guess there are a few things that need explaining here. This will be easier if you see an example of it at work as well.
instance = OurClass('arg1', 'arg2')
}}}

##
I guess there are a few things that need explaining here. This will be easier if you see an example of it at work as well.
Eu acho que existem algumas coisas que precisam ser explicadas aqui. Isto será mais fácil se você ver um exemplo funcionaldo.

{{{#!python
instance = NossaClasse('arg1', 'arg2')
Linha 224: Linha 286:
<class 'OurClass'>
instance.printargs()
<class 'NossaClasse'>
instance.imprime_args()
Linha 228: Linha 290:

In this example we create an instance of OurClass, and call it instance. When we create it, we pass in the arg1 and arg2 as arguments. When we call instance.printargs() these original arguments are printed.
Mentioning Inheritance

The class definition starts with :
class OurClass(object):

The class definition allows for something called inheritance. This means that your class can inherit properties from another class. I'm not going to explain this yet. Smile

All you need to know now is - if you're not inheriting from another class then you ought to inherit from object. Your class definitions should look like :
class ClassName(object):

Old Style Classes

It has only
been possible to inherit from object since Python 2.2. These are called new style classes. You might still see some old style class definitions floating around.
class ClassName:
}}}

##
In this example we create an instance of OurClass, and call it instance. When we create it, we pass in the arg1 and arg2 as arguments. When we call instance.printargs() these original arguments are printed.
Neste exemplo criamos uma instância de NossaClasse, e a chamamos de instance. Quando criamos ela, passamos arg1 e arg2 como argumentos. Quando chamamos instance.printargs() estes argumentos originais são impressos.


##
Mentioning Inheritance
== Mencionando a Herança ==

##
The class definition starts with :
## class OurClass(object):
A definição de Classe começa com:
{{{class NossaClasse(object):}}}


##
The class definition allows for something called inheritance. This means that your class can inherit properties from another class. I'm not going to explain this yet. Smile
A definição de classe permite algo chamado de herança. Isto significa que a sua clase pode herdar propriedades de outra classe. Eu não vou explicar isto ainda. :-)

##
All you need to know now is - if you're not inheriting from another class then you ought to inherit from object. Your class definitions should look like :
## class ClassName(object):
Tudo o que você precisa saber agora é - se você nao está herdando de outra classe então voce deve herdar de object. Suas definições de classe devem se parecer com isto:
{{{class NomeDaClasse(object):}}}

## Old Style Classes
== Classes do Antigo Estilo ('''old-style''') ==

## It has only been possible to inherit from object
since Python 2.2. These are called new style classes. You might still see some old style class definitions floating around.
Só é possível herdar de object desde Python 2.2. Estas classes são chamadas de '''new-style''', o antigo estilo de definição. Você poderá ainda ver algumas definições de classes no antigo estilo por aí.

{{{#!python
class NomeDa
Classe:
Linha 245: Linha 322:
    An old style class that
    isn't using inheritance.
    Uma classe com estilo antigo que
    não está usando herança.
Linha 248: Linha 325:

They still work - but they are deprecated and will probably stop working in Python 3.
The __init__ Method

The __init__ method (init for initialise) is called when the object is instantiated. Instantiation is done by (effectively) calling the class.

From our
example :
instance = OurClass('arg1', 'arg2')

Here a new instance is created. Then it's __init__ method is called and passed the arguments 'arg1' and 'arg2'.

To properly understand the __init__ method you need to understand self.
The self Parameter

The arguments accepted by the __init__ method (known as the method signature) are :
}}}

##
They still work - but they are deprecated and will probably stop working in Python 3.
Elas ainda funcionam - mas elas estão ultrapassadas e provavelmente não vão funcionar em Python 3.

== O
Método __init__ ==

##
The __init__ method (init for initialise) is called when the object is instantiated. Instantiation is done by (effectively) calling the class.
O método __init__ (init de inicializar) é chamado quando o objeto é instanciado. A instanciação é feita (efetivamente) chamando a classe.

Do nosso
exemplo :
{{{#!python
instancia
= NossaClasse('arg1', 'arg2')
}}}

##
Here a new instance is created. Then it's __init__ method is called and passed the arguments 'arg1' and 'arg2'.
Aqui uma nova instância é criada. Então seu método __init__ é chamado e são passados os argumentos 'arg1' e 'arg2'.

##
To properly understand the __init__ method you need to understand self.
Para entender adequadamente o método __init__ você precisa entender o self.

##
The self Parameter
== O Parâmetro self ==

##
The arguments accepted by the __init__ method (known as the method signature) are :
Os argumentos aceitos pelo método __init__ (conhecido como metodo assinatura) são:
{{{#!python
Linha 264: Linha 353:

But we only actually pass it two arguments :
instance = OurClass('arg1', 'arg2')

What's going on, where has the extra argument come from ?

When we access attributes of an object we do it by name (or by reference). Here instance is a reference to our new object. We access the printargs method of the instance object using instance.printargs.

In order to access
object attributes from within the __init__ method we need a reference to the object.

Whenever a method is called, a reference to the main
object is passed as the first argument. By convention you always call this first argument to your methods self.

Is self a Wart ?

Some people regard it as a Python 'wart' that we have to include self. Java (?) includes it automatically and calls it this.

The main argument in favour of self is the Pythonic principle explicit is better than implicit [10]. This way we can see exactly where all our variable names come from.

This means in the __init__ method we can do :
}}}

##
But we only actually pass it two arguments :
Mas na realidade nós passamos somente dois argumentos:
{{{#!python
instancia
= NossaClasse('arg1', 'arg2')
}}}

##
What's going on, where has the extra argument come from ?
O que está acontecendo, de onde está vindo o argumento extra?

##
When we access attributes of an object we do it by name (or by reference). Here instance is a reference to our new object. We access the printargs method of the instance object using instance.printargs.
Quando acessamos atributos de um objeto o fazemos por nome (ou por referência). Aqui a instância é uma referência para nosso novo objeto. Acessamos o método imprime_args da instância do objeto usando instancia.imprime_args.

## In order to access obje
ct attributes from within the __init__ method we need a reference to the object.
Afim de acessar os atributos de dentro do método __init__ precisamos de uma referência ao objeto.

## Whenever a method is called, a reference to the main obje
ct is passed as the first argument. By convention you always call this first argument to your methods self.
Sempre que um método é chamado, uma referência para o objeto principal é passada como o primeiro argumento. Por convenção você sempre chama esse primeiro argumento dos seus métodos de self.

##
Is self a Wart ?
=== Self é um problema da linguagem Python? ===

##
Some people regard it as a Python 'wart' that we have to include self. Java (?) includes it automatically and calls it this.

Algumas pessoas consideram uma deficiência de Python nós termos de incluir o parâmetro self. Java (?) inclui ele automaticamente e o chama '''this'''.

##
The main argument in favour of self is the Pythonic principle explicit is better than implicit [10]. This way we can see exactly where all our variable names come from.

O principal argumento a favor de self é o princípio Pythonico de '''explícito é melhor que implícito'''[10]. Desta forma nós podemos ver exatamente de onde todos os nomes de variáveis vêm.

##
This means in the __init__ method we can do :

Isso significa que podemos fazer assim no método __init__:
{{{#!python
Linha 285: Linha 390:

Here we are setting attributes on the object. You can verify this by doing the following :
instance = OurClass('arg1', 'arg2')
print instance.arg1
}}}

##
Here we are setting attributes on the object. You can verify this by doing the following :

Aqui nós setamos os atributos no objeto. Você pode verificar isso fazendo o seguinte:
{{{#!python
instancia
= NossaClasse('arg1', 'arg2')
print instancia.arg1
Linha 290: Linha 399:

values like this are known as object attributes. Here the __init__ method sets the arg1 and arg2 attribute of the instance.
}}}

##
values like this are known as object attributes. Here the __init__ method sets the arg1 and arg2 attribute of the instance.

Valores assim são conhecidos como atributos de objeto. Aqui o método __init__ configura os atributos arg1 e arg2 da instância.
Linha 294: Linha 407:
We now know enough to understand what is happening in the printargs method.

This method doesn't take any arguments - so when we define it, we only need to specify the self parameter which is always passed to object methods.
##We now know enough to understand what is happening in the printargs method.
Agora já sabemos o bastante para entender o que está acontecendo no método pintargs.

##
This method doesn't take any arguments - so when we define it, we only need to specify the self parameter which is always passed to object methods.
Este método não recebe nenhum argumento - então quando definimos ele, precisamos apenas definir o parâmetro self que sempre é passado para os métodos de objetos.

{{{#!python
Linha 298: Linha 415:

When this method is called it looks up (and prints) the original arguments which were saved as object attributes by __init__.

Hint

Let's get our terminology straight.

The 'functions' that are part of an object are called methods.

The values are called 'attributes'.

You can examine all the methods and attributes that are associated with an object using the dir command :
print dir(some_obj)
The Power of Objects

As you can see objects combind data and the methods used to work with the data. This means it's possible to wrap complex processes - but present a simple interface to them. How these processes are done inside the object becomes a mere implementation detail. Anyone using the object only needs to know about the public methods and attributes. This is the real principle of encapsulation. Other parts of your application (or even other programmers) can use your classes and their public methods - but you can update the object without breaking the interface they use.

You can also pass around objects instead of just data. This is one of the most useful aspects of object oriented programming. Once you have a reference to the object you can access any of the attributes of the object. If you need to perform a complex group of operations as part of a program you could probably implement it with procedures and variables. You might either need to use several global variables for storing state (which are slower to access than local variables and not good if a module needs to be reusable within your application) - or your procedures might need to pass around a lot of variables.

If you implement a single class that has lots of attributes representing the state of your application, you only need to pass around a reference to that object. Any part of your code that has access to the object, can also access its attributes.

The main advantage of objects though is that it is a useful metaphor. It fits in with the way we think. In real life objects have certain properties and interact with each other. The more our programming language fits in with our way of thinking, the easier it is to use it to think creatively.
Advanced Subjects

We've only covered the basics in this tutorial. Hopefully you now understand enough to create and use your own classes.

There is lots more still to learn. Some subjects I could expand this tutorial to cover include :

    * inheritance
    * class attributes
}}}

#
When this method is called it looks up (and prints) the original arguments which were saved as object attributes by __init__.
Quando este método é chamado ele procura (e imprime) os argumentos originais que foram salvos como atributos de objeto pelo __init__.

##
Hint
Dica

##
Let's get our terminology straight.
Vamos colocar nossa terminologia em ordem.

##
The 'functions' that are part of an object are called methods.
As 'funções' que fazem parte de um objeto são chamadas métodos.

##
The values are called 'attributes'.
Os valores são chamados 'atributos'.

##
You can examine all the methods and attributes that are associated with an object using the dir command :
Você pode examinar todos os métodos e atributos que estão associados com um objeto usando o comando dir:
{{{#!python
print dir(algum_objeto)
}}}

##
The Power of Objects
O Poder dos objetos

##
As you can see objects combind data and the methods used to work with the data. This means it's possible to wrap complex processes - but present a simple interface to them. How these processes are done inside the object becomes a mere implementation detail. Anyone using the object only needs to know about the public methods and attributes. This is the real principle of encapsulation. Other parts of your application (or even other programmers) can use your classes and their public methods - but you can update the object without breaking the interface they use.
Como você pode ver, objetos combinam dados e métodos usados pada trabalhar com os dados. Isto significa que é possível empacotar processos complexos - mas apresentar uma interface simples para eles. Como estes processos são feitos dentro do objeto torna-se um mero detalhe de implementação. Qualquer um usando o objeto precisa saber apenas os métodos e atributos públicos. Este é o princípio real da encapsulação. Outras partes da sua aplicação (ou outros programadores) podem usar suas classes e seus métodos públicos - mas você pode atualizar o objeto sem quebrar a inferface que eles usam.

##
You can also pass around objects instead of just data. This is one of the most useful aspects of object oriented programming. Once you have a reference to the object you can access any of the attributes of the object. If you need to perform a complex group of operations as part of a program you could probably implement it with procedures and variables. You might either need to use several global variables for storing state (which are slower to access than local variables and not good if a module needs to be reusable within your application) - or your procedures might need to pass around a lot of variables.
Você também pode passar objetos ao invés de apenas dados. Este é um dos aspectos mais úteis da programação orientada a objetos. Uma vez que você tenha uma referência do objeto você pode acessar qualquer um dos atributos do objeto. Se você precisa performar um grupo complexo de operações como parte de um programa você poderia provavelmente implementar com funções e variáveis. Você pode ainda precisar usar diversas variáveis globais para estado (o que é mais lento do que acessar variáveis locais e mal se um módulo precisa ser reusável em sua aplicação) - ou seus procedimentos podem precisar passar um monte de variáveis.

##
If you implement a single class that has lots of attributes representing the state of your application, you only need to pass around a reference to that object. Any part of your code that has access to the object, can also access its attributes.
Se você implementar uma única classe que possui um monte de atributos representando o estado da sua aplicação, você somente vai precisar passar a referência deste objeto. Qualquer parte do seu código que tenha acesso ao objeto, pode também usar seus atributos.

##
The main advantage of objects though is that it is a useful metaphor. It fits in with the way we think. In real life objects have certain properties and interact with each other. The more our programming language fits in with our way of thinking, the easier it is to use it to think creatively.
A principal vantagem dos objetos no entanto é ser uma metáfora útil. Encaixa-se na forma como pensamos. Na vida real, objetos possuem certas propriedades e interagem uns com outros. Quanto mais nossa linguagem de programação se encaixa no nosso modo de pensar, mais fácil ela será para usar e pensar criativamente.

##Advan
ced Subjects
Assuntos avançados

##
We've only covered the basics in this tutorial. Hopefully you now understand enough to create and use your own classes.

Apenas cobrimos o básico neste tutorial. Espera-se que você agora saiba o suficiente para criar swuas próprias classes.

##
There is lots more still to learn. Some subjects I could expand this tutorial to cover include :

Ainda tem muito para aprender. Alguns assuntos para se expandir neste tutorial incluem:

##
* inheritance
## * class attributes
## * __dict__
## * subclassing built in types
## * __new__
## * __getattr__ and __setattr__
## * private attributes (single and double underscore)
## * classmethods and staticmethods
    * herança
    * atributos de classes
Linha 329: Linha 475:
    * subclassing built in types     * subclasseando tipos built in
Linha 331: Linha 477:
    * __getattr__ and __setattr__
    * private attributes (single and double underscore)
    * classmethods and staticmethods

Footnotes
[1] It was two years in June 2005.... I started learning Python for a project called atlantibots.
[2] It's system of modules and packages as well - these are related to namespaces, and are the envy of other languages.
[3] These are called the basic datatypes - plus lots more things like classes, instances, and methods that we'll meet soon in this introduction.
[4] Like smalltalk - which is sometimes spoken of as the archetypal object oriented language.
[5] The technical difference used to be that a function returns a value but a procedure doesn't. Nowadays they tend to all get called functions. We don't call it functional programming though, that's something else altogether. Very Happy
[6] Or is that to protect the programmer from the code ?
[7] The 'old' object oriented name for this is 'message passing'. These days it's not a helpful metaphor.
[8] You can see a list of string methods at string methods.
[9] Actually type isn't a function - it's a type. It is the type of types (type(type) is type). Very Happy We can use it as a function though.
[10] Try import this at an interactive interpreter prompt. This is called the Zen of Python.
    * __getattr__ e __setattr__
    * atributos privados (underscore simples e duplo)
    * classmethods e staticmethods

Sugestão: Por que não continuamos este artigo escrevendo so
bre estes assuntos? - RodrigoNishino

##
Footnotes
Notas de rodapé

##||
[1]||It was two years in June 2005.... I started learning Python for a project called atlantibots.||

||[1]||Fez 2 anos em Junho de 2005.... Eu comecei a aprener Python para um projeto chamado atlantibots.||

##||
[2]||It's system of modules and packages as well - these are related to namespaces, and are the envy of other languages.||

||[2]||São módulos do sistema e pacotes - estes são relacionados ao namespaces, e são os desafetos de outras linguagens.||

##||
[3]||These are called the basic datatypes - plus lots more things like classes, instances, and methods that we'll meet soon in this introduction.||

||[3]||Estes são os chamados tipos básicos de dados - junte mais coisas como classes, instâncias, e métodos e nós iremos nos encontrar logo, logo nesta introdução.||


||
[4]||Like smalltalk - which is sometimes spoken of as the archetypal object oriented language.||

##||
[5]||The technical difference used to be that a function returns a value but a procedure doesn't. Nowadays they tend to all get called functions. We don't call it functional programming though, that's something else altogether. Very Happy||

||[5]||A diferença técnica costumava ser que uma função retornava um valor mas um procedure não. De agora em diante, todos eles tendem a ser chamado de funções. Nós não chamamos isso de programação funcional mesmo assim, é algo diferente. :D||

##||
[6]||Or is that to protect the programmer from the code ?||
||[6]||Ou isso é para proteger o programador do código ?||

##||
[7]||The 'old' object oriented name for this is 'message passing'. These days it's not a helpful metaphor.||

||[7]||O antigo nome da orientação a objetos para isso era 'message passing'. Estes dias não é lá uma metáfora que ajuda muito.||

##||
[8]||You can see a list of string methods at string methods.||
||[8]||Você pode ver uma lista de métodos string nos métodos do módulo strings..||

##||
[9]||Actually type isn't a function - it's a type. It is the type of types (type(type) is type). Very Happy We can use it as a function though.||
||[9]||Na realidade, type não é uma função - é um tipo. É o tipo dos tipos! (type(type) é type). :D Podemos usar como uma função mesmo assim!.||

##||
[10]||Try import this at an interactive interpreter prompt. This is called the Zen of Python.||
||[10]||Tente 'import this' em um prompt interativo. Isso é chamado "The Zen Of Python".||

<<BR>>
Traduzido por '''FabioCorrea''', '''LuizCarlosGeron''', '''NicholasAmorim'''

Tradução do "Introduction to OOP with Python" do site www.voidspace.org.uk

Introdução

Eu tenho programado com Python por mais de 2 anos [1]. Antes, havia feito alguma programação procedural por cerca de 8 anos - mas eu não estava familiarizado com objetos ou OOP.

A filosofia usada no design da Python encoraja um estilo de programação limpo. Os seus tipos de dados básicos (datatypes) e o sistema de espaço de nomes (namespaces) facilitam a escrita de código elegante e modular [2].

Estes fatores, mais a peculiar regra de estruturação de bloco por indentação, tornam a Python uma linguagem ideal para iniciantes. Apesar disso, eu tive dificuldades em aprender sobre classes e objetos. Foi um grande obstáculo a ser vencido, assim como são todos os novos sistemas.

De fato os princípios básicos da programação orientada a objetos são relativamente fáceis de aprender. Assim como outros aspectos da Python, eles são bem concebidos e implementados. Este tutorial é uma introdução a programação orientada a objetos, que eu gostaria de ter tido quando precisei aprender tais princípios.

Este artigo assume um conhecimento básico da sintaxe da Python. Se você sabe como criar os tipos de dados básicos e chamar funções, mas quer saber mais sobre objetos e classes - então você achará esse artigo extremamente útil.

Objetos e OOP

Objetos e OOP estão no coração do modo como a Python funciona. Você não é forçado a usar o paradigma OOP em seus programas - mas entender os conceitos é essencial para se tornar algo mais que um iniciante. Mesmo porque, você precisará usar as classes e objetos fornecidos pela biblioteca padrão da linguagem.

OOP o Novo Paradigma

A programação de computadores é uma disciplina relativamente nova. Surpreendentemente, a programação orientada a objetos data da longínqua década de 60. Simula é considerada a primeira linguagem de programação orientada a objetos.

A OOP não é um paradigma incontroverso, de fato não é claro o que venha a ser uma definição exata de Programação Orientada a Objetos.

Algumas pessoas acham que a OOP já teve a sua chance, e nós já deveríamos procurar pelo paradigma pós-OOP.

Outros como Paul Graham acham que, em primeiro lugar, a OOP nunca foi necessária.

Então, o quê é um Objeto?

O quê é um Objeto? Bem, estamos falando de programação - portanto um objeto é um conceito. Chamar elementos de nossos programas de objetos é uma metáfora - um modo útil de pensar sobre eles.

Em Python os elementos básicos da programação são coisas como strings, dicionários, inteiros, funções, e assim por diante [3] ... Todos eles são objetos [4]. Isto significa que eles possuem certas coisas em comum.

Antes de olharmos mais de perto o que isto significa, nós iremos rapidamente cobrir alguns conceitos básicos de programação.

Programação Procedural

Se você já programou antes, você deve estar familiarizado com o estilo procedural de programação. Neste estilo, você divide o seu programa em 'pedaços' reutilizáveis chamados procedimentos (procedures) ou funções (functions) [5].

Sempre que possível você tenta manter o seu código nestes pedaços modulares - usando a lógica para decidir qual pedaço é chamado. Este estilo faz com que você não se esforce tanto ao visualizar o que o seu programa está fazendo. Ele também facilita a manutenção do seu código - você pode ver quais partes fazem o quê. Ao melhorar uma função (que é reutilizada) você pode, consequentemente, melhorar a performance em várias partes do seu programa.

Nota

Para um visão interessante do desenvolvimento da programação procedural, leia uma mini história da programação

Separação de Dados

O estilo de programação procedural mantém uma estrita separação entre o seu código e seus dados.

Você tem variáveis, que contém os seus dados, e procedimentos. Você passa suas variáveis para os seus procedimentos - que ajem sobre elas e talvez até as modifiquem.

Se uma função quer modificar o conteúdo de uma variável ao passá-la para outra função, ela necessita acesso a ambas, variável e função chamada. Se você realizar operações complexas isto pode compreender o uso de muitas variáveis e muitas funções.

Entra o Objeto

Elementos Básicos da OOP

Qualquer programador OOP experiente lhe dirá que os elementos essênciais da OOP são encapsulamento e passagem de mensagens.

Os equivalentes destes elementos na Python são namespaces e métodos.

A Python não adota o conceito de proteger (ocultar) o código do programador, [6] assim como a maioria das linguagens BSD. Ela encapsula os objetos em um namespace, mas através de um encapsulamento translúcido. :)

Isso leva a conclusão de que muitas operações são comuns a objetos do mesmo tipo. Por exemplo, a maioria das linguagens possuem modos nativos de criar uma versão somente em minúsculas (caixa baixa) de uma string.

Existem várias operações padrão que estão associadas apenas a strings. Dentre elas temos, por exemplo, retornar uma versão em minúsculas, retornar uma versão em maiúsculas, particionar a string, e assim por diante. Em uma linguagem orientada a objetos nós podemos embutir essas operações como propriedades do objeto string. Em Python nós chamamos estas operações de métodos [7].

Todo objeto string possui um conjunto padrão de métodos - alguns dos quais você provavelmente já usou.

Por exemplo :

   1 string_original = ' algum texto '
   2 
   3 # remove espaços em branco no início e fim da string
   4 string1 = string_original.strip()
   5 
   6 # retorna uma versão em maiúsculas
   7 string2 = string1.upper()
   8 print string2
   9 ALGUM TEXTO
  10 
  11 # retorna uma versão em minúsculas
  12 string2.lower() == string1
  13 True

A Python usa a sintaxe de ponto para acessar os atributos dos objetos. A instrução string2.lower() significa chamar o método lower do objeto string2. Este método retorna uma nova string - o resultado da chamada ao método.

Então toda string é atualmente um objeto string - e tem todos os métodos de um objeto string [8]. Na terminologia da Python nós dizemos que todas as strings são do tipo string.

No modelo de objetos as funções (métodos) e outros atributos que estão associados a um tipo particular de objeto, tornam-se parte do objeto. Os dados, e as funções que lidam com esses dados não estão mais separados - mas empacotados juntos no objeto.

Criando Novos Objetos

Olhemos mais claramente para o que está acontecendo.

Em python existe um objeto de modelo para o tipo string. Seu nome real é str. Ele tem todos os métodos e propriedades associadas com a string.

Toda vez que uma nova string é criada, o modelo é usado para criar um novo objeto com todas as propriedades do modelo.

Todos os tipo de dados nativos têm seu próprio "modelo" - o inteiro (int), o ponto flutante (float), booleanos (bool), listas (list), dicionários (dict), e mais.

Para estes tipo de dados nativos, nós podemos ou usar a sintaxe normal da Python para criá-los - ou nós podemos usar o próprio modelo (o tipo).

   1 # cria um dicionário da forma normal
   2 dicionario = {
   3     'chave' : 'valor',
   4     'chave2' : 'valor2'
   5     }
   6 # usa 'dict' para criá-lo
   7 lista_de_tuplas = [('chave', 'valor'),
   8                  ('chave2', 'valor2')]
   9 outro_dicionario = dict(lista_de_tuplas)
  10 #
  11 print dicionario == outro_dicionario
  12 True
  13 print type(dicionario)
  14 <type 'dict'>
  15 print type(outr_dicionario)
  16 <type 'dict'>

Veja como nós criamos o objeto outro_dicionario por passar uma lista de tuplas para o dicionário. São coisas básicas, mas ilustram que novos objetos são criados a partir de modelos. Estes objetos têm todos os métodos definidos no modelo.

O novo objeto é chamado 'instância' - e o processo de criá-lo é chamado 'instanciação' (isto é, a criação de uma instância). Para os tipos de dados nativos o modelo é conhecido como o tipo do objeto. Você pode testar o tipo de um objeto por usar a função nativa 'type' [9].

Pode parecer muito para digerir - mas isso provavelmente não envolve nada que você já não conheça.

Python como uma Linguagem Orientada a Objeto

Se você fizer uma busca pela internet poderá encontrar algumas discussões inúteis sobre se Python é ou não orientado a objeto. Este debate é particularmente amado pelos programadores Ruby que como reivindicam que sua linguagem é mais orientada a objeto do que Python.

Isso parece vir dos dias pré-Python 2.2 quando existia uma grande diferença entre os tipos nativos e as classes definidas pelo usuário. Desde a 2.2 você pode fazer classes que herdam de tipos nativos. Na Python 3.0 a unificação será completa.

Nós já vimos um exemplo usando alguns métodos de string. Nós fecharemos esta seção usando alguns métodos de dicionário.

   1 um_dicionario = {
   2     'key' : 'value',
   3     'key2' : 'value2'
   4     }
   5 outro_dicionario = um_dicionario.copy()
   6 print um_dicionario == outro_dicionario
   7 True
   8 um_dicionario.clear()
   9 print um_dicionario
  10 {}
  11 print um_dicionario.clear
  12 <built-in method clear of dict object at 0x0012E540>
  13 print type(um_dicionario.clear)
  14 <type 'builtin_function_or_method'>

Acima nós usamos o método 'clear' da variável 'um_dicionario' chamando 'um_dicionario.clear()'. Quando nós imprimos 'clear', em vez de chamá-lo, podemos ver que é apenas outro objeto. É um objeto de método do tipo apropriado.

Funções são Objetos

Apenas para mostrar que funções são objetos, mostrarei um truque elegante com elas.

Você já escreveu código parecido com este ?

   1 if valor == 'um':
   2     # faça alguma coisa
   3     funcao1()
   4 elif valor == 'dois':
   5     # faça outra coisa
   6     funcao2()
   7 elif valor == 'três':
   8     # faça outra coisa
   9     funcao3()

Outras linguagens tem uma construção chamada 'switch' que escreve código como o anterior de uma maneira mais fácil.

Em Python nós podemos conseguir a mesma coisa (em um menor número de linhas de código) usando dicionário de funções.

Como exemplo, suponha que tenhamos três funções. Você quer chamar uma das funções, dependendo do valor na variável chamada 'escolha'.

   1 def funcao1():
   2     print 'Você escolheu um.'
   3 def funcao2():
   4     print 'Você escolheu dois.'
   5 def funcao3():
   6     print 'Você escolheu três.'
   7 #
   8 # 'switch' é nosso dicionário de funções
   9 switch = {
  10     'um': funcao1,
  11     'dois': funcao2,
  12     'três': funcao3,
  13     }
  14 #
  15 # escolha pode ser 'um', 'dois', ou 'três'
  16 escolha = raw_input('Enter um, dois, or três :')
  17 #
  18 # chama uma das funções
  19 try:
  20     resultado = switch[escolha]
  21 except KeyError:
  22     print 'Não entendi sua escolha.'
  23 else:
  24     resultado()

A mágica ocorre na linha resultado = switch[escolha]. switch[escolha] retorna uma de nossos objetos do tipo função (ou levanta uma exceção KeyError). :)

Cuidado!

Você poderia eliminar uma linha ou duas por fazer o bloco final desta forma:

   1 # chama uma das funções
   2 try:
   3     switch[escolha]()
   4 except KeyError:
   5     print 'Eu não entendi a sua escolha.'

Esta forma chama diretamente a função retornada por switch[escolha]. No entanto, se aquela função levanta uma exceção KeyError (devido a um bug) - e exceção será capturada pelo bloco try...except. Esse erro pode ser bem difícil de encontrar, porque o seu código de tratamento de erros está reportando o erro errado.

Em geral você deve ter seus blocos try...except encobrindo o mínimo de código possível.

Classes Definidas Pelo Usuário

O truque real é que nós podemos criar nossos próprios modelos, chamados de classes. Nós podemos definir nosso pŕoprio tipo de objeto - e assim criar quantas instâncias desta classe quanto quisermos. Todas as instâncias serão diferentes - dependendo que dados são guardados nelas quando criadas. Elas terão todos os métodos (e outras propriedades) do modelo - a classe.

Vamos então ver um exemplo simples. Nós podemos definir nossa própria classe usando a palavra-chave class.

Métodos são definidos como funções - usando a palavra-chave def. Eles são identados para mostrar que estão dentro da classe.

   1 class NossaClasse(object):
   2     """Docstring da classe."""
   3 
   4     def __init__(self, arg1, arg2):
   5         """Docstring do método."""
   6         self.arg1 = arg1
   7         self.arg2 = arg2
   8 
   9     def imprime_args(self):
  10         """Docstring do método."""
  11         print self.arg1
  12         print self.arg2

Eu acho que existem algumas coisas que precisam ser explicadas aqui. Isto será mais fácil se você ver um exemplo funcionaldo.

   1 instance = NossaClasse('arg1', 'arg2')
   2 print type(instance)
   3 <class 'NossaClasse'>
   4 instance.imprime_args()
   5 arg1
   6 arg2

Neste exemplo criamos uma instância de NossaClasse, e a chamamos de instance. Quando criamos ela, passamos arg1 e arg2 como argumentos. Quando chamamos instance.printargs() estes argumentos originais são impressos.

Mencionando a Herança

A definição de Classe começa com: class NossaClasse(object):

A definição de classe permite algo chamado de herança. Isto significa que a sua clase pode herdar propriedades de outra classe. Eu não vou explicar isto ainda. :-)

Tudo o que você precisa saber agora é - se você nao está herdando de outra classe então voce deve herdar de object. Suas definições de classe devem se parecer com isto: class NomeDaClasse(object):

Classes do Antigo Estilo ('''old-style''')

Só é possível herdar de object desde Python 2.2. Estas classes são chamadas de new-style, o antigo estilo de definição. Você poderá ainda ver algumas definições de classes no antigo estilo por aí.

   1 class NomeDaClasse:
   2     """
   3     Uma classe com estilo antigo que
   4     não está usando herança.
   5     """

Elas ainda funcionam - mas elas estão ultrapassadas e provavelmente não vão funcionar em Python 3.

O Método __init__

O método init (init de inicializar) é chamado quando o objeto é instanciado. A instanciação é feita (efetivamente) chamando a classe.

Do nosso exemplo :

   1 instancia = NossaClasse('arg1', 'arg2')

Aqui uma nova instância é criada. Então seu método init é chamado e são passados os argumentos 'arg1' e 'arg2'.

Para entender adequadamente o método init você precisa entender o self.

O Parâmetro self

Os argumentos aceitos pelo método init (conhecido como metodo assinatura) são:

   1 def __init__(self, arg1, arg2):

Mas na realidade nós passamos somente dois argumentos:

   1 instancia = NossaClasse('arg1', 'arg2')

O que está acontecendo, de onde está vindo o argumento extra?

Quando acessamos atributos de um objeto o fazemos por nome (ou por referência). Aqui a instância é uma referência para nosso novo objeto. Acessamos o método imprime_args da instância do objeto usando instancia.imprime_args.

Afim de acessar os atributos de dentro do método init precisamos de uma referência ao objeto.

Sempre que um método é chamado, uma referência para o objeto principal é passada como o primeiro argumento. Por convenção você sempre chama esse primeiro argumento dos seus métodos de self.

Self é um problema da linguagem Python?

Algumas pessoas consideram uma deficiência de Python nós termos de incluir o parâmetro self. Java (?) inclui ele automaticamente e o chama this.

O principal argumento a favor de self é o princípio Pythonico de explícito é melhor que implícito[10]. Desta forma nós podemos ver exatamente de onde todos os nomes de variáveis vêm.

Isso significa que podemos fazer assim no método init:

   1 self.arg1 = arg1
   2 self.arg2 = arg2

Aqui nós setamos os atributos no objeto. Você pode verificar isso fazendo o seguinte:

   1 instancia = NossaClasse('arg1', 'arg2')
   2 print instancia.arg1
   3 arg1

Valores assim são conhecidos como atributos de objeto. Aqui o método init configura os atributos arg1 e arg2 da instância.

printargs

Agora já sabemos o bastante para entender o que está acontecendo no método pintargs.

Este método não recebe nenhum argumento - então quando definimos ele, precisamos apenas definir o parâmetro self que sempre é passado para os métodos de objetos.

   1 def printargs(self):

#When this method is called it looks up (and prints) the original arguments which were saved as object attributes by init. Quando este método é chamado ele procura (e imprime) os argumentos originais que foram salvos como atributos de objeto pelo init.

Dica

Vamos colocar nossa terminologia em ordem.

As 'funções' que fazem parte de um objeto são chamadas métodos.

Os valores são chamados 'atributos'.

Você pode examinar todos os métodos e atributos que estão associados com um objeto usando o comando dir:

   1 print dir(algum_objeto)

O Poder dos objetos

Como você pode ver, objetos combinam dados e métodos usados pada trabalhar com os dados. Isto significa que é possível empacotar processos complexos - mas apresentar uma interface simples para eles. Como estes processos são feitos dentro do objeto torna-se um mero detalhe de implementação. Qualquer um usando o objeto precisa saber apenas os métodos e atributos públicos. Este é o princípio real da encapsulação. Outras partes da sua aplicação (ou outros programadores) podem usar suas classes e seus métodos públicos - mas você pode atualizar o objeto sem quebrar a inferface que eles usam.

Você também pode passar objetos ao invés de apenas dados. Este é um dos aspectos mais úteis da programação orientada a objetos. Uma vez que você tenha uma referência do objeto você pode acessar qualquer um dos atributos do objeto. Se você precisa performar um grupo complexo de operações como parte de um programa você poderia provavelmente implementar com funções e variáveis. Você pode ainda precisar usar diversas variáveis globais para estado (o que é mais lento do que acessar variáveis locais e mal se um módulo precisa ser reusável em sua aplicação) - ou seus procedimentos podem precisar passar um monte de variáveis.

Se você implementar uma única classe que possui um monte de atributos representando o estado da sua aplicação, você somente vai precisar passar a referência deste objeto. Qualquer parte do seu código que tenha acesso ao objeto, pode também usar seus atributos.

A principal vantagem dos objetos no entanto é ser uma metáfora útil. Encaixa-se na forma como pensamos. Na vida real, objetos possuem certas propriedades e interagem uns com outros. Quanto mais nossa linguagem de programação se encaixa no nosso modo de pensar, mais fácil ela será para usar e pensar criativamente.

Assuntos avançados

Apenas cobrimos o básico neste tutorial. Espera-se que você agora saiba o suficiente para criar swuas próprias classes.

Ainda tem muito para aprender. Alguns assuntos para se expandir neste tutorial incluem:

  • herança
  • atributos de classes
  • dict

  • subclasseando tipos built in
  • new

  • getattr e setattr

  • atributos privados (underscore simples e duplo)
  • classmethods e staticmethods

Sugestão: Por que não continuamos este artigo escrevendo sobre estes assuntos? - RodrigoNishino

Notas de rodapé

[1]

Fez 2 anos em Junho de 2005.... Eu comecei a aprener Python para um projeto chamado atlantibots.

[2]

São módulos do sistema e pacotes - estes são relacionados ao namespaces, e são os desafetos de outras linguagens.

[3]

Estes são os chamados tipos básicos de dados - junte mais coisas como classes, instâncias, e métodos e nós iremos nos encontrar logo, logo nesta introdução.

[4]

Like smalltalk - which is sometimes spoken of as the archetypal object oriented language.

[5]

A diferença técnica costumava ser que uma função retornava um valor mas um procedure não. De agora em diante, todos eles tendem a ser chamado de funções. Nós não chamamos isso de programação funcional mesmo assim, é algo diferente. :D

[6]

Ou isso é para proteger o programador do código ?

[7]

O antigo nome da orientação a objetos para isso era 'message passing'. Estes dias não é lá uma metáfora que ajuda muito.

[8]

Você pode ver uma lista de métodos string nos métodos do módulo strings..

[9]

Na realidade, type não é uma função - é um tipo. É o tipo dos tipos! (type(type) é type). :D Podemos usar como uma função mesmo assim!.

[10]

Tente 'import this' em um prompt interativo. Isso é chamado "The Zen Of Python".


Traduzido por FabioCorrea, LuizCarlosGeron, NicholasAmorim