Почему __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.

  • Выражение генератора должно быть заключено в скобки, если не единственным аргументом
  • Выход из сопрограммы против выхода из задачи
  • Errbot: получение ошибки yapsy при попытке настроить плагины через интерфейс командной строки
  • Заменить строку в списке списков
  • Python Pandas - возвращает результаты функции groupby обратно в родительскую таблицу
  • IndexError: индекс индекса вне диапазона - файл CSV
  • Попытка разобрать `request.body` из POST в Django
  • Как написать Python 2.x как можно более совместимым с Python 3.x?
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.