2013-12-15 3 views
9

Какова цель проверки self.__class__? Я нашел код, который создает абстрактный класс интерфейса, а затем проверяет, является ли его self.__class__ сам, например.Какова цель проверки self .__ class__? - python

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

Для чего это? Следует ли проверять, является ли класс типом самого себя?

Код от NLTK в http://nltk.googlecode.com/svn/trunk/doc/api/nltk.probability-pysrc.html#ProbDistI

+1

Я думаю, это требует большего контекста. Где вы «нашли» этот код? Это в основном сломан. – Iguananaut

+1

@Iguananaut: Почему это сломано? Он работает * отлично * при использовании по назначению; как абстрактный базовый класс. –

+1

Я уверен, что раньше это было что-то другое? Я не знаю - согласен, что там сейчас не сломано. – Iguananaut

ответ

15

self.__class__ является ссылкой на тип текущего экземпляра.

Для экземпляров abstract1, что был бы abstract1 класс сам, который является то, что вы не хотите с абстрактным классом. Абстрактные классы предназначены только для подклассов, чтобы не создавать экземпляры непосредственно:

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

Для экземпляра подкласса из abstract1, self.__class__ будет ссылка на конкретный подкласс:

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

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

Обратите внимание, что вещий способ проверки типа экземпляра, чтобы использовать type() function вместо этого, вместе с идентичности теста с is оператора:

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

Существует мало смысла используя тест равенства здесь как для пользовательских классов, __eq__ в принципе реализован как тест идентичности.

Python также включает стандартную библиотеку для определения абстрактных базовых классов, называемую abc. Он позволяет отмечать методы и свойства как абстрактные и отказывается создавать экземпляры любого подкласса, который еще не переопределил эти имена.

1

кода, публикуемом нет нет-оп; self.__class__ == c1 не является частью условного выражения, поэтому логическое значение оценивается, но результат не выполняется.

Вы можете попытаться создать абстрактный базовый класс, который проверяет, равен ли self.__class__ абстрактный класс, а не гипотетический ребенок (через оператор if), чтобы предотвратить создание абстрактного базового класса из-за ошибки разработчика.

+1

Хотя для более поздних версий Python нужно просто использовать абстрактный базовый класс, используя 'abc.ABCMeta'. – Iguananaut

+0

ABC все еще может быть создан непосредственно. –

1

Я бы сказал, что некоторые будут делать:

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

Даже когда база является абстрактным, вы не хотели бы, чтобы Базы __init__ бросить NotImplementedError. Эй, может, он даже делает что-то полезное?

+0

Вы говорите, что 'super (Foo, self) .__ init __()' не будет работать? Потому что это неверно; он будет работать * отлично *. База '__init__' будет * только * генерирует исключение, когда self является экземпляром' AbstractBase', а не когда он является экземпляром подкласса типа 'Foo'. –

0

Ключи от имени класса «abstract1» и ошибки. Это предназначено для абстрактного класса, означающего тот, который предназначен для подкласса. Каждый подкласс будет обеспечивать свое собственное поведение. Сам абстрактный класс служит для документирования интерфейса, то есть методов и аргументов, которые, как ожидается, будут иметь классы, реализующие интерфейс. Он не предназначен для создания самого себя, и тест используется, чтобы определить, находимся ли мы в самом классе или подклассе.

См. Раздел «Абстрактные классы» в этом article от Julien Danjou.

1

Какова цель этого? Является ли это проверкой того, является ли класс самим типом?

Да, если вы попытаетесь построить объект типа Abstract1, это будет исключать это исключение, сообщая вам, что вам не разрешено это делать.

Смежные вопросы