2015-09-03 3 views
7

PyCharm предупреждает меня Call to __init__ of super class is missedАбстрактный базовый класс: поднять NotImplementedError() в `__init __. Py`?

class AbstractBase(object): 
    def __init__(self): 
     raise NotImplementedError() 

class RealChild(AbstractBase): 
    def __init__(self): 
     #super(RealChild, self).__init__() #### 
     print('do stuff') 

child=RealChild() 

Но если я это называю, класс AbstractBase поднимет NotImplementedError.

Я овцу и не знаю, как поступить :-)

+6

Связанный: http://stackoverflow.com/questions/14972631/python-abstract-classes-how-to-discourage-instantiation – juanchopanza

ответ

5

Вы можете сделать что-нибудь г добрейшего уродливые и проверить тип self в инициализаторе абстрактного типа, чтобы убедиться, что он был подтипы:

class AbstractBase (object): 
    def __init__ (self): 
     if type(self) is AbstractBase: 
      raise NotImplementedError 

Я думаю, что более «нормальный» подход был бы просто не подвергать абстрактный базовый тип и ожидать, что пользователи не создадут его.

+0

Как я могу «не выставлять абстрактный базовый тип»? Другие разработчики должны подклассифицировать его. – guettli

+0

Разработчики да, но пользователи этого не делают. Поэтому сделайте его доступным только для разработчиков, которые знают, что его не следует создавать самостоятельно. В общем, не заходите слишком далеко, чтобы применять правила, но просто четко документируйте их и ожидайте, что люди сделают это правильно. – poke

+0

Я все еще не понимаю. Мои пользователи знают, как использовать веб-браузер. Не знаю, что Python - это язык программирования. Я думаю, что «не выставлять абстрактный базовый тип» не работает в моем случае. – guettli

0

В абстрактном классе заменить исключение в инициализации функции с

pass 

Это исключение используется для предотвращения вы из инициализации нового экземпляра абстрактного класса (абстрактно, поэтому вы не можете) Так что либо используйте 'pass', либо не слушайте pycharm и не называйте super

+2

Технически исключение не позволяет вам инициализировать новый объект, а не создавать его. 'a = A .__ new __ (A)' отлично работает. – chepner

4

Вы могли бы рассмотреть using the abc Abstract Base Class module отметить __init__ как абстрактные, а затем идти вперед и вызывать суперкласс __init__ из подкласса (и, как DorElias suggested, дают суперкласс __init__ тривиальное реализацию pass):

from abc import ABCMeta, abstractmethod 


class AbstractBase(object, metaclass=ABCMeta): 
    @abstractmethod # This method must be overridden... 
    def __init__(self): 
     print("...but can still be called via super by subclasses have shared construction logic") 
     pass 


class RealChild(AbstractBase): 
    def __init__(self): 
     super().__init__() # Won't do anything, UNTIL the day you decide all subclasses of AbstractBase need shared logic 
     print('do stuff') 


child = RealChild() 

Если вы попытаетесь создать экземпляр через parent = AbstractBase() или parent = AbstractBase.__new__(AbstractBase), вы получите сообщение об ошибке:

TypeError: Can't instantiate abstract class AbstractBase with abstract methods init

Итак, у вас есть ваша необразованная абстрактная безопасность, но в то же время вы все еще хорошо настроены, чтобы изменить всю конструкцию дочернего класса, изменив конструкцию базового класса, как правильно и правильно.

+0

Это должен быть принятый ответ. Если намерение состоит в том, чтобы иметь ABC, будьте откровенны в этом вопросе - создание исключения в конструкторе - это не способ сделать это. – BoltzmannBrain