Working on issue #1762: Brought
./python.exe -m timeit -s 'from fractions import Fraction; f = Fraction(3, 2)' 'isinstance(3, Fraction); isinstance(f, Fraction)' from 12.3 usec/loop to 3.44 usec/loop and ./python.exe -m timeit -s 'from fractions import Fraction' 'Fraction(3, 2)' from 48.8 usec to 23.6 usec by avoiding genexps and sets in __instancecheck__ and inlining the common case from __subclasscheck__.
This commit is contained in:
parent
0a40ffb1b3
commit
57bd60b465
16
Lib/abc.py
16
Lib/abc.py
|
@ -163,8 +163,20 @@ class ABCMeta(type):
|
|||
|
||||
def __instancecheck__(cls, instance):
|
||||
"""Override for isinstance(instance, cls)."""
|
||||
return any(cls.__subclasscheck__(c)
|
||||
for c in set([instance.__class__, type(instance)]))
|
||||
# Inline the cache checking for new-style classes.
|
||||
subclass = instance.__class__
|
||||
if subclass in cls._abc_cache:
|
||||
return True
|
||||
subtype = type(instance)
|
||||
if subtype is subclass:
|
||||
if (cls._abc_negative_cache_version ==
|
||||
ABCMeta._abc_invalidation_counter and
|
||||
subclass in cls._abc_negative_cache):
|
||||
return False
|
||||
# Fall back to the subclass check.
|
||||
return cls.__subclasscheck__(subclass)
|
||||
return (cls.__subclasscheck__(subclass) or
|
||||
cls.__subclasscheck__(subtype))
|
||||
|
||||
def __subclasscheck__(cls, subclass):
|
||||
"""Override for issubclass(subclass, cls)."""
|
||||
|
|
|
@ -83,6 +83,16 @@ class TestABC(unittest.TestCase):
|
|||
self.assertEqual(issubclass(C, A), True)
|
||||
self.assertEqual(isinstance(c, A), True)
|
||||
|
||||
def test_isinstance_invalidation(self):
|
||||
class A:
|
||||
__metaclass__ = abc.ABCMeta
|
||||
class B(object):
|
||||
pass
|
||||
b = B()
|
||||
self.assertEqual(isinstance(b, A), False)
|
||||
A.register(B)
|
||||
self.assertEqual(isinstance(b, A), True)
|
||||
|
||||
def test_registration_builtins(self):
|
||||
class A:
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
|
Loading…
Reference in New Issue