Todas as classes Python devem estender o objeto?

129

Eu descobri que os dois trabalhos a seguir:

class Foo():
    def a(self):
        print "hello"

class Foo(object):
    def a(self):
        print "hello"

Todas as classes Python devem estender o objeto? Existem problemas em potencial com a não extensão do objeto?

Kara
fonte
2
Existe uma diferença entre class Foo():e class Foo:? Quando observo, tanto o trabalho em Python 3.
Lobo
Está bem respondido nesta pergunta: stackoverflow.com/questions/4015417/…
nngeek 18/06/19

Respostas:

117

No Python 2, não herdar de objectcriará uma classe de estilo antigo que, entre outros efeitos, causa typeresultados diferentes:

>>> class Foo: pass
... 
>>> type(Foo())
<type 'instance'>

vs.

>>> class Bar(object): pass
... 
>>> type(Bar())
<class '__main__.Bar'>

Além disso, as regras para herança múltipla são diferentes de maneiras que nem tentarei resumir aqui. Toda a boa documentação que eu vi sobre o MI descreve novas classes de estilo.

Finalmente, as classes de estilo antigo desapareceram no Python 3 e a herança de objecttornou-se implícita. Portanto, sempre prefira novas classes de estilo, a menos que você precise de uma compatibilidade com o software antigo.

Fred Foo
fonte
68

No Python 3, as classes se estendem objectimplicitamente, independentemente de você dizer ou não.

No Python 2, existem classes de estilo antigo e novo . Para sinalizar que uma classe é de novo estilo, você deve herdar explicitamente de object. Caso contrário, a implementação de estilo antigo é usada.

Você geralmente deseja uma classe de novo estilo. Herdar de objectexplicitamente. Observe que isso também se aplica ao código Python 3 que visa ser compatível com o Python 2.

slezica
fonte
Sim, a diferença que Free Foo apontou foi: BTW: os parênteses vazios são opcionais?
Wolf
4
Há muitos códigos python 3 que usam foo (object) :. Isso é apenas uma convenção então?
RFV5s
2
@RFVenter Pode ser um código que é suposto para ser executado em ambos Python 2 e 3, caso em que você precisa objeto de subclasse explicitamente, a fim de tornar a se comportar classe em grande parte o mesmo sob Python 2.
blubberdiblub
@blubberdiblub Isso é o que eu suspeitava, MAS nosso projeto está sendo executado exclusivamente no python 3.5 virtualenv. Eu acho que o código deve ter sido copiado de um projeto python 2.
RFV5s
@RFVenter sim, isso pode ser outra explicação. E, é claro, se agora é o Python 3.x, não há problema em se livrar das referências a objetos.
precisa saber é o seguinte
17

No python 3, você pode criar uma classe de três maneiras diferentes e internamente todas são iguais (veja exemplos). Não importa como você cria uma classe, todas as classes no python 3 herdam da classe especial chamada object . O objeto de classe é uma classe fundamental em python e fornece muitas funcionalidades, como métodos de sublinhado duplo, descritores, método super (), método property () etc.

Exemplo 1.

class MyClass:
 pass

Exemplo 2

class MyClass():
 pass

Exemplo 3

class MyClass(object):
  pass
N Randhawa
fonte
1
Esta não é rigorosamente verdade ... stackoverflow.com/questions/1238606/...
Philip Adler
Não tenho certeza de segui-lo. E sim, provavelmente não é relevante para a maioria das pessoas até que seja relevante.
Philip Adler
@PhilipAdler Supõe-se geralmente que objectfaz referência ao built-in object. Se precisarmos levar em consideração que qualquer identificador interno do CPython pode ser substituído, mal podemos fazer alguma afirmação sobre o modelo de dados. Pode-se argumentar seriamente que strnem sempre aceita uma string como argumento porque se pode atribuir builtins.str = None?
Nuno André
Continuo vendo essa afirmação de que isso é "amplamente aceito" e aceito que é uma suposição que toda implementação atual faz (não é um requisito da linguagem); não foi minha experiência que a maioria dos programadores de python que eu cumpriram assumir isso, saber sobre isso, ou até consideraram. Independentemente de qual, a afirmação de que é comumente assumida, mesmo que verdadeira, não invalida minha afirmação de que a equivalência não é estritamente verdadeira.
Philip Adler
1

Sim, todas as classes Python devem estender (ou melhor, subclasse, aqui é Python aqui) o objeto. Embora normalmente não ocorram problemas sérios, em alguns casos (como em várias árvores de herança), isso será importante. Isso também garante uma melhor compatibilidade com o Python 3.

pydsigner
fonte
1
exatamente, tecnicamente, caso contrário, você obterá uma classe clássica, mas não há vantagens reais nisso e, de qualquer forma, não é suportado pelo python 3
max k.
Estou curioso sobre o porquê de melhorar a compatibilidade com python3. No meu entendimento, python3 fará com que ele estenda o objeto automaticamente, mesmo que você não o especifique, certo?
Paul Lo
2
@PaulLo Certo, mas se você herdar explicitamente do objeto, obterá o mesmo comportamento (novo estilo) no Python 2 e no Python 3. Não é uma questão de mudar o funcionamento do Python 3, é uma questão de usar o forward -compatibility no Python 2.
pydsigner 23/05
Essa sugestão não parece muito elegante, mas, se você abordar Python2 e Python3, parece eficaz. Mas qual é a relevância disso na prática?
Wolf
@ Wolf Depende do que você está fazendo. Se você tem árvores de herança complexas, isso importa bastante. Se você deseja que sua classe seja um descritor, use um novo estilo. Você pode seguir os links de stackoverflow.com/questions/54867/… se desejar obter informações mais detalhadas.
pydsigner
1

Como outras respostas abordaram, a herança do Python 3 do objeto é implícita. Mas eles não afirmam o que você deve fazer e o que é convenção.

Todos os exemplos de documentação do Python 3 usam o estilo a seguir, que é convencional, então sugiro que você siga isso para qualquer código futuro no Python 3.

class Foo:
    pass

Fonte: https://docs.python.org/3/tutorial/classes.html#class-objects

Exemplo de citação:

Os objetos de classe suportam dois tipos de operações: referências de atributo e instanciação.

As referências de atributo usam a sintaxe padrão usada para todas as referências de atributo em Python: obj.name. Nomes de atributos válidos são todos os nomes que estavam no espaço de nomes da classe quando o objeto da classe foi criado. Portanto, se a definição de classe fosse assim:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

Outra citação:

De um modo geral, as variáveis ​​de instância são para dados exclusivos de cada instância e as variáveis ​​de classe são para atributos e métodos compartilhados por todas as instâncias da classe:

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance
jmoz
fonte
0

em python3 não há diferença, mas em python2 não estender objectfornece classes de estilo antigo; você gostaria de usar uma classe de novo estilo em vez de uma classe de estilo antigo.

thkang
fonte
2
Essa resposta é razoável, mas outros respondentes chegaram mais rápido e / ou com mais detalhes; esta resposta não está agregando valor à página como está.
Mark Amery