Почему __instancecheck__ не всегда вызывается в зависимости от аргумента?

Существует этот код:

class Meta(type): def __instancecheck__(self, instance): print("__instancecheck__") return True class A(metaclass=Meta): pass a = A() isinstance(a, A) # __instancecheck__ not called isinstance([], A) # __instancecheck__ called 

Почему __instancecheck__ вызывается для аргумента [] но не для аргумента?

2 Solutions collect form web for “Почему __instancecheck__ не всегда вызывается в зависимости от аргумента?”

PyObject_IsInstance делает быстрый тест для точного соответствия.

Objects/abstract.c :

 int PyObject_IsInstance(PyObject *inst, PyObject *cls) { static PyObject *name = NULL; /* Quick test for an exact match */ if (Py_TYPE(inst) == (PyTypeObject *)cls) return 1; // ... 

не нравится быстрый путь? вы можете попробовать это (на свой страх и риск):

 >>> import __builtin__ >>> def isinstance(a, b): ... class tmp(type(a)): ... pass ... return __builtin__.isinstance(tmp(), b) ... >>> __builtin__.isinstance(a, A) True >>> isinstance(a, A) __instancecheck__ True 

Я думаю, что PEP, описывающий __instancecheck__() , неисправен. PEP 3119 говорит:

Основной механизм, предлагаемый здесь, заключается в том, чтобы разрешить перегрузку встроенных функций isinstance () и issubclass (). Перегрузка работает следующим образом: вызов isinstance (x, C) сначала проверяет, существует ли C.__instancecheck__ , и если это так, вызывает C.__instancecheck__(x) вместо обычной реализации.

Ты можешь написать:

 class C: def do_stuff(self): print('hello') C.do_stuff(C()) 

Поэтому, основываясь на приведенной выше цитате из PEP, вы должны уметь писать

 class C: @classmethod def __instancecheck__(cls, x): print('hello') C.__instancecheck__(C()) --output:-- hello 

Но isinstance () не вызывает этот метод:

 class C: @classmethod def __instancecheck__(cls, y): print('hello') x = C() isinstance(x, C) --output:-- <nothing> 

Затем PEP продолжает:

Эти методы предназначены для вызова классов, чей метакласс (полученный из) ABCMeta …

Хорошо, давайте попробуем:

 import abc class MyMeta(abc.ABCMeta): #A metaclass derived from ABCMeta def __instancecheck__(cls, inst): print('hello') return True class C(metaclass=MyMeta): #A class whose metaclass is derived from ABCMeta pass x = C() C.__instancecheck__(x) --output:-- hello 

Но еще раз isststance () не вызывает этот метод:

 isinstance(x, C) --output:-- <nothing> 

Вывод: PEP 3119 необходимо переписать вместе с документами Data Model.

  • Конвенция для печати объекта в python
  • к какой группе относится обратная ссылка, когда используется операция sub ()?
  • Распаковывание обобщений
  • Ошибка при установке PyMVPA2
  • Вычисление энтропии Шеннона HTTP-заголовка с использованием Python. Как это сделать?
  • Разница между zip (list) и zip (* list)
  • Openshift: приложение не запускается после нажатия из-за OSError: Адрес уже используется
  • Отправка команд с помощью python3 подпроцессом
  • Создание живого графика CSV-данных с помощью Matplotlib
  • почему эта игра не начнется, это зацикливание
  • pythonw.exe или python.exe?
  • Python - лучший язык программирования в мире.