Como posso tornar uma classe ou método abstrato em Python?
Tentei redefinir __new__()
assim:
class F:
def __new__(cls):
raise Exception("Unable to create an instance of abstract class %s" %cls)
mas agora se eu criar uma classe G
que herda da seguinte F
maneira:
class G(F):
pass
também não posso instanciar G
, pois chama o __new__
método da sua superclasse .
Existe uma maneira melhor de definir uma classe abstrata?
python
class
inheritance
abstract-class
abstract
Martin Thoma
fonte
fonte
Respostas:
Use o
abc
módulo para criar classes abstratas. Use oabstractmethod
decorador para declarar um resumo do método e declare um resumo da classe usando uma das três maneiras, dependendo da sua versão do Python.No Python 3.4 e superior, você pode herdar de
ABC
. Nas versões anteriores do Python, você precisa especificar a metaclasse da sua classe comoABCMeta
. A especificação da metaclasse possui sintaxe diferente no Python 3 e Python 2. As três possibilidades são mostradas abaixo:Qualquer que seja a maneira que você use, você não poderá instanciar uma classe abstrata que possua métodos abstratos, mas poderá instanciar uma subclasse que fornece definições concretas desses métodos:
fonte
@abstractmethod
faz com que a função decorado deve ser substituído antes que a classe pode ser instanciado. Dos documentos:A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden.
@abstractmethod
para__init__
método, bem como, ver stackoverflow.com/q/44800659/547270A maneira da velha escola (antes do PEP 3119 ) de fazer isso é apenas
raise NotImplementedError
na classe abstrata quando um método abstrato é chamado.Isso não tem as mesmas boas propriedades que o
abc
módulo. Você ainda pode instanciar a própria classe base abstrata e não encontrará seu erro até chamar o método abstrato em tempo de execução.Mas se você está lidando com um pequeno conjunto de classes simples, talvez com apenas alguns métodos abstratos, essa abordagem é um pouco mais fácil do que tentar percorrer a
abc
documentação.fonte
Aqui está uma maneira muito fácil, sem ter que lidar com o módulo ABC.
No
__init__
método da classe que você deseja que seja uma classe abstrata, você pode verificar o "tipo" de si mesmo. Se o tipo de self for a classe base, o chamador está tentando instanciar a classe base, portanto, crie uma exceção. Aqui está um exemplo simples:Quando executado, produz:
Isso mostra que você pode instanciar uma subclasse que herda de uma classe base, mas não pode instanciar a classe base diretamente.
fonte
A maioria das respostas anteriores estava correta, mas aqui está a resposta e o exemplo para o Python 3.7. Sim, você pode criar uma classe e método abstratos. Assim como um lembrete, às vezes, uma classe deve definir um método que pertence logicamente a uma classe, mas essa classe não pode especificar como implementar o método. Por exemplo, nas classes Pais e bebês abaixo, ambos comem, mas a implementação será diferente para cada um deles, porque bebês e pais comem um tipo diferente de comida e o número de vezes que comem é diferente. Portanto, as subclasses de método eat substituem AbstractClass.eat.
RESULTADO:
fonte
import abc
seja inútil.Este estará trabalhando em python 3
fonte
Como explicado em outras respostas, sim, você pode usar classes abstratas em Python utilizando o
abc
módulo . Abaixo eu dar um exemplo real usando abstrato@classmethod
,@property
e@abstractmethod
(usando Python 3.6+). Para mim, geralmente é mais fácil começar com exemplos que eu posso copiar e colar facilmente; Espero que esta resposta também seja útil para outros.Vamos primeiro criar uma classe base chamada
Base
:Nossa
Base
classe sempre terá afrom_dict
classmethod
, aproperty
prop1
(que é somente leitura) e aproperty
prop2
(que também podem ser configuradas), bem como uma função chamadado_stuff
. Qualquer que seja a classe criada agoraBase
, terá que implementar tudo isso para métodos / propriedades. Observe que, para um método ser abstrato, são necessários dois decoradores -classmethod
e abstratoproperty
.Agora poderíamos criar uma classe
A
como esta:Todos os métodos / propriedades necessários são implementados e podemos - é claro - também adicionar funções adicionais que não fazem parte
Base
(aquii_am_not_abstract
:).Agora podemos fazer:
Como desejado, não podemos definir
prop1
:retornará
Também nosso
from_dict
método funciona bem:Se agora definimos uma segunda classe
B
como esta:e tentou instanciar um objeto como este:
receberemos um erro
listando todas as coisas definidas nas
Base
quais não implementamosB
.fonte
também isso funciona e é simples:
fonte
Você também pode aproveitar o método __new__ para sua vantagem. Você acabou de se esquecer de algo. O método __new__ sempre retorna o novo objeto, portanto você deve retornar o novo método da superclasse. Faça o seguinte.
Ao usar o novo método, você deve retornar o objeto, não a palavra-chave None. Foi tudo o que você perdeu.
fonte
Acho a resposta aceita, e todas as outras estranhas, uma vez que passam
self
para uma aula abstrata. Uma classe abstrata não é instanciada, portanto não pode ter aself
.Então tente isso, funciona.
fonte
fonte
No seu snippet de código, você também pode resolver isso fornecendo uma implementação para o
__new__
método na subclasse, da mesma forma:Mas isso é um truque e eu o aconselho a não ser que você saiba o que está fazendo. Em quase todos os casos, recomendo que você use o
abc
módulo, sugerido por outras pessoas antes de mim.Além disso, quando você cria uma nova classe (base), torná-lo subclasse
object
, como este:class MyBaseClass(object):
. Não sei mais se isso é significativo, mas ajuda a manter a consistência do estilo no seu códigofonte
Apenas uma rápida adição à resposta antiga da @ TimGilbert ... você pode fazer com que o método init () da sua classe base abstrata lance uma exceção e isso impediria que ela fosse instanciada, não?
fonte