PCAP — orientação a objetos, o bloco de maior peso

TL;DR

O bloco 4 do PCAP-31-03Object-Oriented Programming — sozinho vale 34% da prova (12 dos 40 itens), mais que os três blocos anteriores somados (Modules 12% + Exceptions 14% + Strings 18% = 44% contra os 34% deste bloco isolado — a comparação mostra a concentração: nenhum outro bloco individual chega perto). O syllabus cobre seis frentes — encapsulamento/name mangling, herança (simples e múltipla), polimorfismo, propriedades e métodos de instância vs. classe, introspecção, e construtores — e todas já foram ensinadas em profundidade no Galho 3 (OO e Data Model). Esta nota não reexplica nada: mapeia cada item do syllabus à nota-fonte exata, com ênfase nas pegadinhas que a Python Institute mais testa — MRO em diamante, __init__ que não roda sozinho sob herança sem super(), atributo de classe mutável compartilhado, e a diferença de comportamento entre _nome (convenção) e __nome (name mangling real). Por ser o bloco de maior peso do exame, esta é a nota mais longa do galho.

Como este bloco se encaixa na prova

O PCAP-31-03 tem 40 itens em 5 blocos, nota de corte 70% cumulativo. As três primeiras seções (nota 03) já cobriram Modules and Packages, Exceptions e Strings — 44% da prova, “espalhados” em blocos de peso moderado. Este bloco 4, sozinho, concentra 34% num único tema: orientação a objetos. Depois dele, a nota 05 fecha com Miscellaneous (22%).

flowchart TB
    PCAP["PCAP-31-03 — 40 itens, 5 blocos"] --> B1["Bloco 1: Modules<br/>12% · 6 itens"]
    PCAP --> B2["Bloco 2: Exceptions<br/>14% · 5 itens"]
    PCAP --> B3["Bloco 3: Strings<br/>18% · 8 itens"]
    PCAP --> B4["Bloco 4: OOP<br/>34% · 12 itens<br/>ESTA NOTA — MAIOR PESO"]
    PCAP --> B5["Bloco 5: Miscellaneous<br/>22% · 9 itens"]

    B4 --> I1["Encapsulamento / name mangling"]
    B4 --> I2["Herança simples e múltipla"]
    B4 --> I3["Polimorfismo"]
    B4 --> I4["Propriedades e métodos<br/>de instância vs classe"]
    B4 --> I5["Introspecção"]
    B4 --> I6["Construtores"]

    style PCAP fill:#4A90D9,color:#fff
    style B4 fill:#D0021B,color:#fff
    style B1 fill:#7ED321,color:#000
    style B2 fill:#7ED321,color:#000
    style B3 fill:#7ED321,color:#000
    style B5 fill:#9013FE,color:#fff
    style I1 fill:#F5A623,color:#000
    style I2 fill:#F5A623,color:#000
    style I3 fill:#F5A623,color:#000
    style I4 fill:#F5A623,color:#000
    style I5 fill:#F5A623,color:#000
    style I6 fill:#F5A623,color:#000

Por que este bloco pesa tanto

A Python Institute organiza o PCAP-31-03 assumindo que quem chega até aqui já domina módulos, exceções e strings de nível PCEP — o que sobra de “diferencial associado” é justamente a capacidade de desenhar e ler classes. Não é acidente que OOP seja o bloco isolado de maior peso: é o critério que separa “sabe escrever scripts” de “sabe estruturar um programa Python de tamanho médio”. Na prática de estudo, isso significa que revisar este bloco rende mais pontos por hora investida do que qualquer outro — vale ler as quatro notas-fonte do Galho 3 (01, 02, 03, 04) de novo antes de tentar o simulado no fim desta nota.

Tabela-mestra: os 12 itens do bloco 4

Item do syllabusNota-fonte (Galho 3)Cobertura nesta nota
Encapsulamento — o que é, _nome como convenção[[03-Dominios/Tecnologia/Python/OO e Data Model/04 - Properties e encapsulamento#_nome convenção social não imposição|04 — _nome]][[#Encapsulamento — _nome convenção __nome mecanismo real]]
Name mangling (__nome_Classe__nome)[[03-Dominios/Tecnologia/Python/OO e Data Model/04 - Properties e encapsulamento#__nome name mangling é mecanismo real, mas não é sobre privacidade|04 — name mangling]][[#Encapsulamento — _nome convenção __nome mecanismo real]]
Herança — sintaxe, class Filha(Mae)02 — O que é
Herança única vs. herança múltipla02 — Herança múltipla
MRO e o diamond problem02 — C3 linearization
super() e encadeamento cooperativo[[03-Dominios/Tecnologia/Python/OO e Data Model/02 - Herança e MRO#super() o que ele realmente faz|02 — super()]][[#Construtores __init__ e encadeamento via super]]
Polimorfismo — override e Data Model02 + 03 — Data Model
Propriedades de instância vs. de classe01 — Atributos
Métodos de instância, @classmethod, @staticmethod01 — Três tipos de método
Introspecção — isinstance(), issubclass(), type(), __class__[[03-Dominios/Tecnologia/Python/OO e Data Model/02 - Herança e MRO#isinstance() e issubclass() por que preferir a checagem de hierarquia|02 — isinstance/issubclass]][[#Introspecção isinstance issubclass type e __class__]]
Construtores — __init__[[03-Dominios/Tecnologia/Python/OO e Data Model/01 - Classes — definição, atributos e métodos#__init__ inicializa __new__ constrói introdução|01 — init vs new]][[#Construtores __init__ e encadeamento via super]]
Encadeamento de construtores em herança[[03-Dominios/Tecnologia/Python/OO e Data Model/02 - Herança e MRO#super() o que ele realmente faz|02 — super() em init]][[#Construtores __init__ e encadeamento via super]]

Encapsulamento — _nome convenção, __nome mecanismo real

O syllabus testa duas coisas distintas sob “encapsulamento”, e a prova adora explorar exatamente a diferença entre elas. _nome (um underscore) é pura convenção social — o interpretador não faz absolutamente nada com esse nome além de tratá-lo como um atributo comum; obj._nome funciona de fora da classe sem erro nenhum, sem aviso, sem restrição. __nome (dois underscores iniciais, no máximo um final) aciona name mangling: o interpretador reescreve textualmente __nome para _Classe__nome durante a compilação do corpo da classe — um mecanismo real, mas cujo propósito documentado é evitar colisão de nomes em herança, não impor privacidade.

class Conta:
    def __init__(self, saldo):
        self._saldo = saldo      # convenção — nada impede acesso externo
        self.__pin = "1234"       # vira self._Conta__pin
 
    def mostrar_pin(self):
        return self.__pin          # resolve para self._Conta__pin, funciona normal
 
 
c = Conta(100)
print(c._saldo)              # 100 — funciona, Python não reclama
print(c.mostrar_pin())        # 1234 — funciona de dentro da classe
print(c.__pin)                 # AttributeError! __pin não existe com esse nome exato
print(c._Conta__pin)            # 1234 — o nome mangled continua acessível

Name mangling não é privacidade — é proteção contra colisão em herança

A prova costuma testar isso com uma pergunta do tipo “o que este código imprime” envolvendo obj.__atributo acessado de fora da classe — a resposta certa é AttributeError, não o valor. Mas a pergunta seguinte, mais traiçoeira, costuma pedir o valor via obj._Classe__atributo (o nome mangled), testando se o candidato entende que o mecanismo reescreve o nome, não bloqueia o acesso. Ver detalhamento completo, com o exemplo canônico Mapeamento/SubMapeamento da documentação oficial, em 04 — name mangling.

Herança simples, herança múltipla e a MRO

Herança simples (class Cachorro(Animal)) funciona como em qualquer linguagem OO — a subclasse herda atributos e métodos, e pode sobrescrever (override) qualquer um deles. A diferença estrutural que a prova cobra pesado é a herança múltipla real: Python permite class C(A, B) com A e B sendo duas classes concretas, com estado e implementação — algo que Java/C# proíbem (só permitem múltipla herança de interfaces). Isso reabre o diamond problem: duas classes-mãe com um ancestral comum, ambas sobrescrevendo o mesmo método.

flowchart TB
    A["Animal<br/>define emitir_som()"]
    B["Nadador<br/>sobrescreve emitir_som()"]
    C["Voador<br/>sobrescreve emitir_som()"]
    D["Pato(Nadador, Voador)<br/>qual emitir_som() roda?"]

    A --> B
    A --> C
    B --> D
    C --> D

    style A fill:#4A90D9,color:#fff
    style B fill:#F5A623,color:#000
    style C fill:#F5A623,color:#000
    style D fill:#D0021B,color:#fff

Python resolve a ambiguidade de forma determinística com o algoritmo C3 linearization, que produz a MRO (Method Resolution Order) — consultável via Classe.__mro__ ou Classe.mro(). A regra prática mais testável: a ordem declarada das classes-mãe é o primeiro critério que a MRO respeita.

class A:
    def cumprimentar(self):
        return "Olá de A"
 
 
class B:
    def cumprimentar(self):
        return "Olá de B"
 
 
class C(A, B):
    pass
 
 
print(C().cumprimentar())     # "Olá de A" — A vem primeiro na declaração
print(C.__mro__)
# (<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>)

TypeError: Cannot create a consistent MRO — quando a prova testa hierarquias inválidas

Se duas bases declaram ordens conflitantes entre si (class A(X, Y) e class B(Y, X), seguido de class Z(A, B)), o C3 linearization falha explicitamente em tempo de definição da classe — não em tempo de chamada de método. A prova pode apresentar esse cenário perguntando “o que acontece ao executar este código” — a resposta certa é a exceção no momento em que class Z(A, B): é processado, não um comportamento silenciosamente arbitrário.

Polimorfismo — override e a forma idiomática via dunders

O syllabus trata polimorfismo de forma ampla, e a prova cobra duas manifestações dele que a trilha já ensinou separadamente:

  1. Override clássico via herança — uma subclasse redefine um método já existente na superclasse, e o objeto “certo” responde de acordo com seu tipo real em tempo de execução, não com o tipo declarado da variável que o referencia.
  2. Polimorfismo via Data Model — a forma mais idiomática e mais “pythônica” de polimorfismo: qualquer classe que implemente os dunders certos (__len__, __eq__, __iter__, __add__…) participa das mesmas operações de linguagem (len(), ==, for, +) que os tipos nativos, sem herdar de uma interface comum — é o oposto de Java, onde polimorfismo depende de implements/extends declarados explicitamente.
class Forma:
    def area(self):
        raise NotImplementedError
 
 
class Quadrado(Forma):
    def __init__(self, lado):
        self.lado = lado
 
    def area(self):
        return self.lado ** 2
 
 
class Circulo(Forma):
    def __init__(self, raio):
        self.raio = raio
 
    def area(self):
        return 3.14159 * self.raio ** 2
 
 
formas = [Quadrado(4), Circulo(3)]
for forma in formas:
    print(forma.area())      # 16, depois 28.27... — mesmo código, comportamento por tipo real
# Polimorfismo via Data Model: nenhuma das duas classes herda de nada em comum,
# mas ambas participam de len() porque implementam __len__
class Fila:
    def __init__(self):
        self._itens = []
 
    def __len__(self):
        return len(self._itens)
 
 
class Pilha:
    def __init__(self):
        self._itens = []
 
    def __len__(self):
        return len(self._itens)
 
 
for estrutura in [Fila(), Pilha()]:
    print(len(estrutura))     # 0, 0 — len() funciona igual, sem hierarquia comum

Como a prova formula "polimorfismo" — e como reconhecer a pergunta

A Python Institute costuma apresentar polimorfismo com um laço for percorrendo uma lista de instâncias de subclasses diferentes, todas chamando o mesmo método sobrescrito — pedindo pra prever a sequência de saídas na ordem certa. É essencialmente o mesmo formato do exemplo Forma/Quadrado/Circulo acima. Menos comum, mas também testável, é reconhecer polimorfismo via dunder — por exemplo, perguntar “por que len(fila) funciona mesmo sem Fila herdar de list” — a resposta correta aponta para o Data Model, não para herança. Ver o tratamento completo do Data Model, incluindo o exemplo canônico FrenchDeck de Python Fluente, em 03 — Data Model.

Atributos e métodos de instância vs. de classe

Essa distinção é uma das mais testadas do bloco inteiro, porque tem um caso de borda genuinamente perigoso: atributo de classe mutável compartilhado.

DeclaradoAcessoCompartilhamento
Atributo de instânciaself.x = valor dentro de __init__ (ou outro método)objeto.xum valor por instância
Atributo de classex = valor no corpo da classe, fora de qualquer métodoClasse.x ou objeto.x (busca sobe)um único valor, compartilhado por todas as instâncias
Método de instânciadef metodo(self, ...)objeto.metodo()opera nos dados daquela instância
Método de classe@classmethod + def metodo(cls, ...)Classe.metodo() ou objeto.metodo()opera na classe; usado para factory methods alternativos
Método estático@staticmethod + def metodo(...)Classe.metodo() ou objeto.metodo()nem self nem cls; função agrupada por namespace
class Carrinho:
    itens = []  # ATRIBUTO DE CLASSE — um único objeto lista, compartilhado
 
    def adicionar(self, produto):
        self.itens.append(produto)
 
 
carrinho_ana = Carrinho()
carrinho_bia = Carrinho()
 
carrinho_ana.adicionar("Livro")
carrinho_bia.adicionar("Caneta")
 
print(carrinho_ana.itens)   # ['Livro', 'Caneta'] — Bia "vazou" pro carrinho da Ana!
print(carrinho_bia.itens)   # ['Livro', 'Caneta'] — mesmo objeto lista dos dois

Atributo de classe mutável declarado no corpo da classe é a pegadinha mais citada deste sub-item

itens = [] no corpo da classe (fora de __init__) cria um único objeto lista, no momento em que a classe é definida — não um valor inicial por instância. Toda instância que não tem itens próprio sobe a busca de atributo, encontra a lista da classe, e faz append naquela mesma lista. A correção é mover a criação do objeto mutável para dentro de __init__, atribuído a self: self.itens = []. A prova costuma apresentar duas ou três instâncias mutando um atributo de classe mutável em sequência, pedindo o estado final de cada uma — quem não reconhece o padrão de compartilhamento erra a contagem. Detalhamento completo, incluindo o paralelo com o argumento default mutável do Core, em 01 — Atributos de instância vs de classe.

class Usuario:
    total_criados = 0   # atributo de classe imutável — seguro, uso intencional
 
    def __init__(self, nome):
        self.nome = nome
        Usuario.total_criados += 1   # nome da CLASSE, não self
 
 
Usuario("Ana")
Usuario("Bia")
print(Usuario.total_criados)   # 2

Sobre @classmethod vs @staticmethod, a distinção que a prova testa em código curto é: @classmethod recebe cls e é usado sobretudo para factory methods alternativos (respeitando herança, porque cls aponta para a subclasse que efetivamente chamou); @staticmethod não recebe nada implícito, é só uma função agrupada dentro do namespace da classe.

class Pizza:
    def __init__(self, ingredientes):
        self.ingredientes = ingredientes
 
    @classmethod
    def margherita(cls):
        return cls(["muçarela", "tomate", "manjericão"])
 
    @staticmethod
    def eh_vegetariana(ingredientes):
        return "bacon" not in ingredientes and "presunto" not in ingredientes
 
 
p = Pizza.margherita()
print(p.ingredientes)                          # ['muçarela', 'tomate', 'manjericão']
print(Pizza.eh_vegetariana(p.ingredientes))    # True

Ver a comparação completa dos três tipos de método, com a tabela e o diagrama de decisão, em 01 — Comparando os três tipos de método.

Introspecção: isinstance(), issubclass(), type() e __class__

Quatro ferramentas de introspecção que a prova testa isoladamente e em combinação:

class Animal:
    pass
 
 
class Cachorro(Animal):
    pass
 
 
rex = Cachorro()
 
print(isinstance(rex, Animal))       # True — Cachorro é subclasse de Animal
print(isinstance(rex, Cachorro))      # True
print(type(rex) == Animal)             # False — tipo EXATO de rex é Cachorro, não Animal
print(type(rex) == Cachorro)            # True
print(rex.__class__)                     # <class '__main__.Cachorro'>
print(rex.__class__ is type(rex))         # True — __class__ e type() concordam pra instâncias comuns
print(issubclass(Cachorro, Animal))         # True
print(issubclass(Animal, Cachorro))          # False — a relação não é simétrica

isinstance() respeita hierarquia; type(x) == Y não

isinstance(objeto, Classe) percorre toda a MRO do objeto, aceitando qualquer subclasse. type(objeto) == Classe checa o tipo exato, ignorando herança — quebra silenciosamente assim que uma subclasse legítima é introduzida no código. A prova costuma apresentar as duas checagens lado a lado sobre a mesma instância de uma hierarquia com pelo menos um nível de herança, pedindo pra identificar qual delas retorna True e qual retorna False — a resposta correta é sempre que isinstance() “enxerga mais” que type() ==. Ver detalhamento completo, incluindo o comportamento com herança múltipla, em 02 — isinstance() e issubclass().

isinstance() também aceita uma tupla de tipos, testável em uma linha:

print(isinstance(3.0, (int, float)))   # True — é float, um dos dois tipos da tupla
print(isinstance("3", (int, float)))    # False — string não é nem int nem float

Construtores: __init__ e encadeamento via super()

O syllabus chama __init__ de “construtor” — a nomenclatura comum, ainda que tecnicamente imprecisa (o construtor real é __new__, que cria o objeto antes de __init__ configurá-lo; ver [[03-Dominios/Tecnologia/Python/OO e Data Model/01 - Classes — definição, atributos e métodos#init-inicializa-new-constrói-introdução|01 — init vs new]]). Para os fins da prova, o ponto mais testado é o encadeamento de __init__ em herança.

class Animal:
    def __init__(self, nome):
        self.nome = nome
        print(f"Animal.__init__ rodou para {nome}")
 
 
class Cachorro(Animal):
    def __init__(self, nome, raca):
        self.raca = raca
        print(f"Cachorro.__init__ rodou para {nome}")
 
 
c = Cachorro("Rex", "Labrador")
print(c.nome)

Esse código quebra: AttributeError: 'Cachorro' object has no attribute 'nome'. Cachorro.__init__ sobrescreve completamente Animal.__init__ — Python não chama o __init__ da superclasse automaticamente quando a subclasse define o seu próprio. self.nome = nome nunca roda, porque só existe dentro de Animal.__init__, que nunca é invocado.

class Cachorro(Animal):
    def __init__(self, nome, raca):
        super().__init__(nome)   # encadeia explicitamente — só assim Animal.__init__ roda
        self.raca = raca
        print(f"Cachorro.__init__ rodou para {nome}")
 
 
c = Cachorro("Rex", "Labrador")
# Animal.__init__ rodou para Rex
# Cachorro.__init__ rodou para Rex
print(c.nome)   # Rex — agora existe

__init__ de uma subclasse NÃO chama automaticamente o __init__ da superclasse

Esta é, isoladamente, uma das pegadinhas mais citadas de todo o bloco 4. Diferente de linguagens onde o construtor da superclasse roda implicitamente antes do corpo do construtor da subclasse (Java chama o construtor sem argumentos da superclasse automaticamente, a menos que super(...) seja chamado explicitamente com outros argumentos), Python não tem esse comportamento implícito de forma alguma: se Cachorro define __init__ e não chama super().__init__(...) (ou Animal.__init__(self, ...) explicitamente), o __init__ de Animal simplesmente nunca roda. Qualquer atributo que só seria criado ali (self.nome, no exemplo) não existe na instância de Cachorro, e acessá-lo levanta AttributeError. A prova formula isso quase sempre como “o que este código imprime” ou “que exceção este código levanta”, com uma subclasse que sobrescreve __init__ sem chamar super().

super().__init__(...) é preferível a Animal.__init__(self, ...) explícito pelos mesmos motivos já detalhados em 02 — super(): super() segue a MRO calculada dinamicamente (correto sob refatoração e herança múltipla), enquanto o nome hardcoded da superclasse quebra assim que a hierarquia muda.

# Encadeamento em herança múltipla cooperativa — cada __init__ chama super().__init__()
class A:
    def __init__(self):
        print("A")
        super().__init__()
 
 
class B:
    def __init__(self):
        print("B")
        super().__init__()
 
 
class C(A, B):
    def __init__(self):
        print("C")
        super().__init__()
 
 
C()
# C
# A
# B

Simulado rápido: 8 questões no estilo PCAP

O bloco de maior peso da prova merece mais questões de treino que os blocos anteriores. Oito questões curtas, cobrindo cada sub-item do syllabus, no estilo single-choice característico da Python Institute.

1. (Encapsulamento) O que este código imprime?

class Cofre:
    def __init__(self, senha):
        self.__senha = senha
 
 
c = Cofre("1234")
print(c.__senha)
Resposta

AttributeError: 'Cofre' object has no attribute '__senha' — name mangling reescreveu o atributo para _Cofre__senha durante a definição da classe; c.__senha (sem o nome mangled) não existe. c._Cofre__senha funcionaria. Ver 04 — name mangling.

2. (Herança múltipla / MRO) Qual a MRO de D?

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
Resposta

D → B → C → A → object. C3 linearization preserva a ordem declarada (B, C) e só insere A depois que ambas B e C já apareceram. Ver 02 — C3 linearization.

3. (Polimorfismo) O que este código imprime?

class Ave:
    def voar(self):
        return "voo genérico"
 
class Pinguim(Ave):
    def voar(self):
        return "pinguins não voam"
 
aves = [Ave(), Pinguim()]
for a in aves:
    print(a.voar())
Resposta
voo genérico
pinguins não voam

Cada elemento da lista chama voar() de acordo com seu tipo real em tempo de execução (override clássico) — polimorfismo por herança, o formato mais comum de questão sobre este item.

4. (Propriedades e métodos de instância vs classe) O que este código imprime?

class Contador:
    total = 0
 
    def __init__(self):
        Contador.total += 1
 
Contador()
Contador()
Contador()
print(Contador.total)
Resposta

3Contador.total += 1 usa o nome da classe explicitamente, incrementando de fato o atributo de classe compartilhado. Se o código usasse self.total += 1, o resultado seria 0 (cada instância criaria seu próprio atributo sombreando o de classe, sem nunca incrementar o original). Ver 01 — Atributos de instância vs classe.

5. (Introspecção) O que estas três expressões devolvem, em ordem?

class Veiculo: pass
class Carro(Veiculo): pass
 
c = Carro()
print(isinstance(c, Veiculo))
print(type(c) == Veiculo)
print(issubclass(Carro, Veiculo))
Resposta

True, False, Trueisinstance() percorre a MRO e aceita a superclasse; type(c) == Veiculo checa o tipo exato (Carro, não Veiculo) e falha; issubclass() confirma a relação de herança entre as classes. Ver issubclass.

6. (Construtores) Que exceção, se alguma, este código levanta?

class Base:
    def __init__(self, x):
        self.x = x
 
class Derivada(Base):
    def __init__(self, x, y):
        self.y = y
 
d = Derivada(1, 2)
print(d.x)
Resposta

AttributeError: 'Derivada' object has no attribute 'x'Derivada.__init__ sobrescreve Base.__init__ sem chamar super().__init__(x), então self.x nunca é criado. A pegadinha mais citada do item “construtores” do syllabus.

7. (Herança múltipla cooperativa) O que este código imprime?

class Registrador:
    def __init__(self):
        print("Registrador")
        super().__init__()
 
class Validador:
    def __init__(self):
        print("Validador")
        super().__init__()
 
class Formulario(Registrador, Validador):
    def __init__(self):
        print("Formulario")
        super().__init__()
 
Formulario()
Resposta
Formulario
Registrador
Validador

Segue a MRO de Formulario: Formulario → Registrador → Validador → object. Cada __init__ delega cooperativamente via super(), então os três rodam na ordem da MRO — nenhum precisa saber explicitamente da existência do próximo.

8. (Encapsulamento) Qual o valor impresso?

class A:
    def __init__(self):
        self.__valor = 10
 
class B(A):
    def __init__(self):
        super().__init__()
        self.__valor = 20   # NÃO sobrescreve o __valor de A
 
    def mostrar(self):
        return self.__valor
 
b = B()
print(b.mostrar())
print(b._A__valor)
Resposta

20, depois 10b.mostrar() roda dentro de B, onde self.__valor foi reescrito para _B__valor (name mangling usa o nome da classe onde o código está escrito, não da instância) — então devolve o 20 atribuído em B.__init__. b._A__valor acessa o atributo mangled criado por A.__init__, que continua existindo separadamente com valor 10. Este é o exemplo mais avançado da nota — mostra exatamente por que name mangling existe: evitar que B acidentalmente sobrescreva o __valor interno de A, mesmo usando o mesmo nome de atributo nas duas classes.

Como usar este simulado de verdade

Assim como no simulado da nota anterior, resolva mentalmente antes de abrir a resposta — a prova real não dá acesso a um interpretador. Errar a questão 8 não é motivo de alarme: é o item mais avançado de todo o bloco, combinando name mangling com herança, e mesmo desenvolvedores experientes hesitam nele na primeira leitura. Releia 04 — name mangling se ela confundiu.

Vocabulário PT/EN

Termo PTTermo EN
encapsulamentoencapsulation
ofuscação de nomename mangling
herança simplessingle inheritance
herança múltiplamultiple inheritance
ordem de resolução de métodosMethod Resolution Order (MRO)
problema do diamantediamond problem
polimorfismopolymorphism
sobrescrever (um método)to override (a method)
atributo de instânciainstance attribute
atributo de classeclass attribute
método de instânciainstance method
método de classeclass method
método estáticostatic method
introspecçãointrospection
construtorconstructor
inicializadorinitializer
encadeamento cooperativocooperative chaining

O que vem a seguir

Com o bloco de maior peso da prova mapeado — OOP, 34%, o item isolado mais cobrado do PCAP-31-03 — a nota 05 fecha o mapeamento de blocos oficiais com Miscellaneous (22%): list comprehensions, lambdas, closures e uma introdução a file I/O, território parcialmente novo que os Galhos 2 e 4 não cobrem em profundidade suficiente para a prova.

Veja também

Fontes