Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__abstractmethods__ and AttributeError

I was playing with the dir() builtin function when I noticed this:

>>> dir(type)
['__abstractmethods__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__dir__', '__doc__', '__eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__instancecheck__', '__itemsize__', '__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__prepare__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__', '__subclasses__', '__subclasshook__', '__text_signature__', '__weakrefoffset__', 'mro']
>>> type.__abstractmethods__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: __abstractmethods__
>>> list.__abstractmethods__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: __abstractmethods__

I don't understand, it appears in the list, why am I getting such error?

like image 509
zer0uno Avatar asked Jul 23 '14 15:07

zer0uno


1 Answers

__abstractmethods__ is a descriptor to support Abstract Base Classes; it wraps a slot that is empty by default (so the descriptor raises an attribute error). Most of all, it is an implementation detail of how CPython handles abstract methods.

The attribute is used to track what methods are abstract, so that instances can be blocked from being created if they don't provide concrete implementations:

>>> import abc
>>> class FooABC(metaclass=abc.ABCMeta):
...     @abc.abstractmethod
...     def bar(self):
...         pass
... 
>>> FooABC.__abstractmethods__
frozenset({'bar'})
>>> class Foo(FooABC): pass
... 
>>> Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Foo with abstract methods bar

The abc.ABCMeta implementation sets the __abstractmethods__ attribute, and type() uses it to check for any abstract methods that should have been implemented but are not.

like image 127
Martijn Pieters Avatar answered Sep 24 '22 04:09

Martijn Pieters