исправление обезьяны для печати утки - PullRequest
1 голос
/ 12 марта 2019
# python3.7
Python 3.7.2 (default, Feb 15 2019, 16:54:46) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from collections.abc import *
>>> from _collections_abc import _check_methods
>>> class A:
...     pass
... 
>>> a = A()
>>> isinstance(a, Iterable)
False
>>> A.__iter__ = 100
>>> isinstance(a, Iterable)             # why this not working?
False
>>> _check_methods(A, "__iter__")
True
>>> class B:
...     def __iter__(self):
...             pass
... 
>>> isinstance(B(), Iterable)
True

Я пропатчил A с помощью __iter__, поэтому isinstance(a, Iterable) должен вернуть True, поскольку теперь он выглядит как итеративный для определения __iter__.Исходя из источника , Iterable определяет только на основе того, реализован ли класс __iter__.

Так почему же этот патч обезьяны не работает, как я ожидал?

Ответы [ 2 ]

3 голосов
/ 12 марта 2019

Динамическая реализация (или не реализация) абстрактных методов не поддерживается.Механизм abc выполняет много операций кэширования для ускорения проверок isinstance и issubclass, и нет возможности вручную сбросить кэш.Тот факт, что A не является подклассом Iterable, кэшируется после первого вызова isinstance, вызывая результат False для второго вызова.

Ближайший документ Приступим к описанию поведения кэширования в следующей строке:

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

1 голос
/ 12 марта 2019

вы добавляете переменную __iter__ к a.Вы должны добавить его как метод, подобный этому :

 class A:
     pass

 def foo(self):
     pass

 A.__iter__ = foo
 a = A()
 isinstance(a, Iterable)
 # True

ОБНОВЛЕНИЕ : этот ответ случайно возвращает True.это просто возвращает True, потому что я установил iter и затем вызвал isinstance.Если я сначала вызываю isinstance, а затем устанавливаю iter , он всегда возвращает значение False из-за системы кэширования на python (прочитайте ответ user2357112)

...