Почему type (classInstance) возвращает экземпляр?

У меня есть метод, который принимает параметр, который может быть нескольких типов, и должен делать что-то в зависимости от типа, но если я проверю тип указанного параметра, я не получаю "реальный", типа, я всегда получаю <type 'instance'>, и это противоречит моим сравнениям.

У меня есть что-то вроде:

from classes import Class1
from classes import Class2
# Both classes are declared in the same file.
# I don't know if that can be a problem         #
# ... #
def foo(parameter)
    if (type(parameter) == type(Class1()):
    # ... #
    elif (type(parameter) == type(Class2()):
    # ... #

И как type(parameter) возвращает <type 'instance'> и type(Class1()) is <type 'instance'>, оказывается, что даже если этот параметр является экземпляром класса 2, он переходит в первое сравнение...

Кстати, str(parameter.__class__) правильно показывает classes.Class1. Наверное, я всегда мог это использовать, но я хотел бы понять, что происходит... Я сделал десятки сравнений, подобных этому, и все они работали правильно...

Спасибо!:)

Ответ 1

Классы старого стиля делают это. Выведите классы из object в свои определения.

Ответ 2

вы действительно должны использовать isinstance:

In [26]: def foo(param):
   ....:     print type(param)
   ....:     print isinstance(param, Class1)
   ....:

In [27]: foo(x)
<type 'instance'>
True

Тип лучше для встроенных типов.

Ответ 3

Тот факт, что type(x) возвращает один и тот же объект типа для всех экземпляров x наследия, aka old-style, classes, является одним из многих бешеных дефектов этих классов - к сожалению, они должны оставаться (и по умолчанию для класса без базы) в Python 2.* по соображениям обратной совместимости.

Тем не менее, не используйте классы старого стиля, если вы не вынуждены поддерживать кучу старого устаревшего кода (без хорошего набора тестов, чтобы дать вам уверенность в том, чтобы попытаться переключить класс o классов). Когда класс не имеет "естественных" баз, подклассируйте его из object, а не из ничего. Кроме того, ваш модуль наверху может установить

__metaclass__ = type

который изменяет значение по умолчанию из жестоких, устаревших классов старого стиля, на блестящие яркие элементы нового стиля, в то время как явно наследуется от object, как правило, предпочтительнее ( "явный лучше, чем неявный" ), глобальная настройка __metaclass__ может показаться "менее инвазивной" для существующих старых модулей, в которых вы переходите от старых к новым классам, поэтому она предлагается как возможность.