diff options
author | Jeffrey Yasskin <jyasskin@gmail.com> | 2008-02-28 04:45:36 (GMT) |
---|---|---|
committer | Jeffrey Yasskin <jyasskin@gmail.com> | 2008-02-28 04:45:36 (GMT) |
commit | 960b9b7a2f6e9b4f0e6b692d604c53b3fd2f5d1c (patch) | |
tree | 9f0cc6bac83e4c2607c6bea64249932fc5353859 /Lib | |
parent | c105289ec4e22f5d53f3e5872ad6a49da8a33b6d (diff) | |
download | cpython-960b9b7a2f6e9b4f0e6b692d604c53b3fd2f5d1c.zip cpython-960b9b7a2f6e9b4f0e6b692d604c53b3fd2f5d1c.tar.gz cpython-960b9b7a2f6e9b4f0e6b692d604c53b3fd2f5d1c.tar.bz2 |
Move abc._Abstract into object by adding a new flag Py_TPFLAGS_IS_ABSTRACT,
which forbids constructing types that have it set. The effect is to speed
./python.exe -m timeit -s 'import abc' -s 'class Foo(object): __metaclass__ = abc.ABCMeta' 'Foo()'
up from 2.5us to 0.201us. This fixes issue 1762.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/abc.py | 49 | ||||
-rw-r--r-- | Lib/test/test_descrtut.py | 1 |
2 files changed, 2 insertions, 48 deletions
@@ -51,52 +51,6 @@ class abstractproperty(property): __isabstractmethod__ = True -class _Abstract(object): - - """Helper class inserted into the bases by ABCMeta (using _fix_bases()). - - You should never need to explicitly subclass this class. - - There should never be a base class between _Abstract and object. - """ - - def __new__(cls, *args, **kwds): - am = cls.__dict__.get("__abstractmethods__") - if am: - raise TypeError("Can't instantiate abstract class %s " - "with abstract methods %s" % - (cls.__name__, ", ".join(sorted(am)))) - if (args or kwds) and cls.__init__ is object.__init__: - raise TypeError("Can't pass arguments to __new__ " - "without overriding __init__") - return super(_Abstract, cls).__new__(cls) - - @classmethod - def __subclasshook__(cls, subclass): - """Abstract classes can override this to customize issubclass(). - - This is invoked early on by __subclasscheck__() below. It - should return True, False or NotImplemented. If it returns - NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached). - """ - return NotImplemented - - -def _fix_bases(bases): - """Helper method that inserts _Abstract in the bases if needed.""" - for base in bases: - if issubclass(base, _Abstract): - # _Abstract is already a base (maybe indirectly) - return bases - if object in bases: - # Replace object with _Abstract - return tuple([_Abstract if base is object else base - for base in bases]) - # Append _Abstract to the end - return bases + (_Abstract,) - - class ABCMeta(type): """Metaclass for defining Abstract Base Classes (ABCs). @@ -119,7 +73,6 @@ class ABCMeta(type): _abc_invalidation_counter = 0 def __new__(mcls, name, bases, namespace): - bases = _fix_bases(bases) cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace) # Compute set of abstract method names abstracts = set(name @@ -130,7 +83,7 @@ class ABCMeta(type): value = getattr(cls, name, None) if getattr(value, "__isabstractmethod__", False): abstracts.add(name) - cls.__abstractmethods__ = abstracts + cls.__abstractmethods__ = frozenset(abstracts) # Set up inheritance registry cls._abc_registry = set() cls._abc_cache = set() diff --git a/Lib/test/test_descrtut.py b/Lib/test/test_descrtut.py index 94e9845..514e398 100644 --- a/Lib/test/test_descrtut.py +++ b/Lib/test/test_descrtut.py @@ -209,6 +209,7 @@ Instead, you can get the same information from the list type: '__setitem__', '__setslice__', '__str__', + '__subclasshook__', 'append', 'count', 'extend', |