¿Cuál es el propósito de verificar si mismo .__ clase__? – python

¿Cuál es el propósito de verificar si self.__class__ ? He encontrado algún código que crea una clase de interfaz abstracta y luego verifica si su self.__class__ es, por ejemplo,

 class abstract1 (object): def __init__(self): if self.__class__ == abstract1: raise NotImplementedError("Interfaces can't be instantiated") 

Cuál es el propósito de eso? ¿Es para comprobar si la clase es un tipo de sí misma?

El código es de http://nltk.googlecode.com/svn/trunk/doc/api/nltk.probability-pysrc.html#ProbDistI de NLTK

self.__class__ es una referencia al tipo de la instancia actual.

Para instancias de abstract1 , esa sería la clase abstract1 sí misma , que es lo que no quiere con una clase abstracta. Las clases abstractas solo están destinadas a ser subclasificadas, no para crear instancias directamente:

 >>> abstract1() Traceback (most recent call last): File "", line 1, in  File "", line 4, in __init__ NotImplementedError: Interfaces can't be instantiated 

Para una instancia de una subclase de abstract1 , self.__class__ sería una referencia a la subclase específica:

 >>> class Foo(abstract1): pass ... >>> f = Foo() >>> f.__class__  >>> f.__class__ is Foo True 

Lanzar una excepción aquí es como usar una statement de afirmación en otra parte de su código, lo protege de cometer errores tontos.

Tenga en cuenta que la forma pythonica de probar el tipo de una instancia es utilizar la función type() lugar, junto con una prueba de identidad con el operador is :

 class abstract1(object): def __init__(self): if type(self) is abstract1: raise NotImplementedError("Interfaces can't be instantiated") 

type() debe preferirse a self.__class__ porque este último puede ser seguido por un atributo de clase .

No tiene mucho sentido usar una prueba de igualdad aquí, ya que para las clases personalizadas, __eq__ se implementa básicamente como una prueba de identidad de todos modos.

Python también incluye una biblioteca estándar para definir clases base abstractas, llamadas abc . Le permite marcar métodos y propiedades como abstractos y se negará a crear instancias de cualquier subclase que aún no haya redefinido esos nombres.

El código que publicaste allí es un no-op; self.__class__ == c1 no es parte de un condicional, por lo que se evalúa el booleano pero no se hace nada con el resultado.

Podría intentar crear una clase base abstracta que verifique si self.__class__ es igual a la clase abstracta en lugar de un hijo hipotético (a través de una instrucción if), para evitar la creación de instancias de la propia clase base abstracta debido a error del desarrollador.

Yo diría que algunos harían:

 class Foo(AbstractBase): def __init__(self): super(Foo, self).__init__() # ... 

Incluso cuando la base es abstracta, no querría que el __init__ la base lance NotImplementedError . Hey, tal vez incluso hace algo útil?

Cuál es el propósito de eso? ¿Es para comprobar si la clase es un tipo de sí misma?

Sí, si intentas construir un objeto de tipo Abstract1 se lanzará esa excepción que te indica que no puedes hacerlo.

Las pistas están en el nombre de la clase, “abstract1”, y en el error. Se pretende que esta sea una clase abstracta, es decir, una clase destinada a ser subclasificada. Cada subclase proporcionará su propio comportamiento. La clase abstracta en sí misma sirve para documentar la interfaz, es decir, los métodos y argumentos que se espera que tengan las clases que implementan la interfaz. No está diseñado para ser instanciado, y la prueba se utiliza para determinar si estamos en la clase en sí o en una subclase.

Vea la sección sobre clases abstractas en este artículo de Julien Danjou.