Qual é a diferença entre o estilo antigo e as novas classes de estilo no Python? Quando devo usar um ou outro?
Das classes clássica e de novo estilo :
Até o Python 2.1, as classes de estilo antigo eram o único sabor disponível para o usuário.
O conceito de classe (de estilo antigo) não tem relação com o conceito de tipo: se
x
é uma instância de uma classe de estilo antigo,x.__class__
designa a classe dex
, mastype(x)
é sempre<type 'instance'>
.Isso reflete o fato de que todas as instâncias do estilo antigo, independentemente de sua classe, são implementadas com um único tipo interno, chamado instância.
As classes de novo estilo foram introduzidas no Python 2.2 para unificar os conceitos de classe e tipo . Uma classe de novo estilo é simplesmente um tipo definido pelo usuário, nem mais nem menos.
Se x é uma instância de uma classe de novo estilo,
type(x)
normalmente é igual ax.__class__
(embora isso não seja garantido - é permitido que uma instância de classe de novo estilo substitua o valor retornadox.__class__
).A principal motivação para a introdução de novas classes de estilo é fornecer um modelo de objeto unificado com um metamodelo completo .
Ele também possui vários benefícios imediatos, como a capacidade de subclassificar a maioria dos tipos internos ou a introdução de "descritores", que habilitam propriedades calculadas.
Por motivos de compatibilidade, as classes ainda são antigas por padrão .
As classes de novo estilo são criadas especificando outra classe de novo estilo (ou seja, um tipo) como uma classe pai ou o objeto "tipo de nível superior" se nenhum outro pai for necessário.
O comportamento das classes de estilo novo difere do das classes de estilo antigo em vários detalhes importantes, além do tipo de retorno.
Algumas dessas mudanças são fundamentais para o novo modelo de objeto, como a maneira como métodos especiais são chamados. Outras são "correções" que antes não podiam ser implementadas por questões de compatibilidade, como a ordem de resolução do método em caso de herança múltipla.
O Python 3 possui apenas classes de novo estilo .
Não importa se você subclassifica
object
ou não, as classes são de novo estilo no Python 3.
type(x)
. Se eu não estou subclassificando um tipo incorporado, não parece haver nenhuma vantagem que eu possa ver nas classes de novo estilo. Há uma desvantagem, que é a digitação extra de(object)
.super()
não funcionam em aulas de estilo antigo. Sem mencionar, como diz o artigo, existem correções fundamentais, como MRO, e métodos especiais, que são mais do que uma boa razão para usá-lo.Em termos de declaração:
As classes de novo estilo herdam do objeto ou de outra classe de novo estilo.
As aulas de estilo antigo não.
Nota do Python 3:
O Python 3 não suporta classes de estilo antigo, portanto, qualquer um dos formulários mencionados acima resulta em uma classe de novo estilo.
fonte
object
.class AnotherOldStyleClass: pass
class A: pass
eclass A(): pass
são estritamente equivalentes. O primeiro significa "A não herda nenhuma classe pai" e o segundo significa "A não herda nenhuma classe pai" . Isso é bem parecido comnot is
eis not
Alterações importantes de comportamento entre classes de estilo antigas e novas
Exception
(exemplo abaixo)__slots__
adicionadoMRO (ordem de resolução do método) alterado
Foi mencionado em outras respostas, mas aqui vai um exemplo concreto da diferença entre MRO clássico e C3 MRO (usado em novas classes de estilo).
A questão é a ordem na qual os atributos (que incluem métodos e variáveis-membro) são pesquisados em herança múltipla.
As aulas clássicas fazem uma pesquisa profunda da esquerda para a direita. Pare na primeira partida. Eles não têm o
__mro__
atributoAs classes de novo estilo MRO são mais complicadas de sintetizar em uma única frase em inglês. É explicado em detalhes aqui . Uma de suas propriedades é que uma classe base é pesquisada apenas uma vez que todas as suas classes derivadas foram. Eles têm o
__mro__
atributo que mostra a ordem de pesquisa.Os novos objetos de classe de estilo não podem ser gerados, a menos que derivados de
Exception
Em torno do Python 2.5 muitas classes poderiam ser geradas e, em torno do Python 2.6, isso foi removido. No Python 2.7.3:
fonte
As classes de estilo antigo ainda são marginalmente mais rápidas para a pesquisa de atributos. Isso geralmente não é importante, mas pode ser útil no código Python 2.x sensível ao desempenho:
fonte
%timeit aobj.a
10000000 loops, best of 3: 66.1 ns per loop
%timeit bobj.a
10000000 loops, best of 3: 53.9 ns per loop
Guido escreveu The Inside Story on New Style Classes , um excelente artigo sobre classes de estilo novo e antigo em Python.
O Python 3 possui apenas classe de novo estilo. Mesmo se você escrever uma 'classe de estilo antigo', ela é derivada implicitamente
object
.As classes de estilo novo têm alguns recursos avançados ausentes nas classes de estilo antigo, como
super
o novo C3 mro , alguns métodos mágicos etc.fonte
Aqui está uma diferença muito prática, verdadeira / falsa. A única diferença entre as duas versões do código a seguir é que, na segunda versão, Person herda de objeto . Fora isso, as duas versões são idênticas, mas com resultados diferentes:
Classes à moda antiga
Classes de novo estilo
fonte
_names_cache
é um dicionário que armazena em cache (armazena para recuperação futura) todos os nomes para os quais você passaPerson.__new__
. O método setdefault (definido em qualquer dicionário) usa dois argumentos: uma chave e um valor. Se a chave estiver no ditado, ela retornará seu valor. Se não estiver no dict, ele o definirá primeiro como o valor passado como segundo argumento e depois o retornará.__new__()
é sempre chamado, e sempre constrói um novo objeto, e depois o lança. Nesse caso, aif
é preferível.setdefault()
.__new__
na verdade não é uma coisa para classes de estilo antigo, não é usado na construção de instância (é apenas um nome aleatório que parece especial, como definição__spam__
). Portanto, a construção da classe de estilo antigo apenas chama__init__
, enquanto a construção de estilo novo chama__new__
(coalescendo para instância singleton por nome) para construir e__init__
inicializá-la.As classes de novo estilo herdam
object
e devem ser escritas como tal no Python 2.2 em diante (ou seja, emclass Classname(object):
vez declass Classname:
). A principal mudança é unificar tipos e classes, e o bom efeito colateral disso é que ele permite herdar dos tipos internos.Leia a descrição para mais detalhes.
fonte
Novas classes de estilo podem usar
super(Foo, self)
whereFoo
é uma classe eself
é a instância.E no Python 3.x você pode simplesmente usar
super()
dentro de uma classe sem nenhum parâmetro.fonte