self.__class__
is a reference to the type of the current instance.
For instances of abstract1
, that'd be the abstract1
class itself, which is what you don't want with an abstract class. Abstract classes are only meant to be subclassed, not to create instances directly:
>>> abstract1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
NotImplementedError: Interfaces can't be instantiated
For an instance of a subclass of abstract1
, self.__class__
would be a reference to the specific subclass:
>>> class Foo(abstract1): pass
...
>>> f = Foo()
>>> f.__class__
<class '__main__.Foo'>
>>> f.__class__ is Foo
True
Throwing an exception here is like using an assert
statement elsewhere in your code, it protects you from making silly mistakes.
Note that the pythonic way to test for the type of an instance is to use the type()
function instead, together with an identity test with the is
operator:
class abstract1(object):
def __init__(self):
if type(self) is abstract1:
raise NotImplementedError("Interfaces can't be instantiated")
type()
should be preferred over self.__class__
because the latter can be shadowed by a class attribute.
There is little point in using an equality test here as for custom classes, __eq__
is basically implemented as an identity test anyway.
Python also includes a standard library to define abstract base classes, called abc
. It lets you mark methods and properties as abstract and will refuse to create instances of any subclass that has not yet re-defined those names.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…