2014-07-23 7 views
5

grałem z wbudowanej funkcji dir() kiedy zauważyłem to:__abstractmethods__ i AttributeError

>>> 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__ 

nie rozumiem, to pojawi się na liście, dlaczego otrzymuję taki błąd?

Odpowiedz

4

__abstractmethods__ to descriptor do obsługi Abstract Base Classes; otacza domyślnie pusty szczelinę (więc deskryptor wywołuje błąd atrybutu). Przede wszystkim jest to szczegół implementacji tego, jak CPython obsługuje abstrakcyjne metody.

atrybut jest używany do śledzenia jakie metody są abstrakcyjne, tak że przypadki mogą być zablokowane tworzony jeśli nie zapewniają one konkretne implementacje:

>>> 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 

Realizacja abc.ABCMeta ustawia atrybut __abstractmethods__ i type() używa go do sprawdzenia wszelkich abstrakcyjnych metod, które powinny zostać zaimplementowane, ale nie są.

+0

Czy nie było bardziej spójne, jeśli '__abstractmethods__' zwrócił pusty domyślnie ustawiony zamrożony? – ivanperelivskiy

+0

Dlaczego miałby to zrobić wewnętrzny szczegół wdrożenia? Po co marnować pamięć na 'frozenset()' dla czegoś, z czego korzysta tylko niewielka liczba klas? –

+2

Mógłby być bardziej spójny, gdyby 'dir' nie zwrócił nazwy czegoś, co spowodowałoby' AttributeError' w przypadku dostępu, ale 'dir' jest udokumentowany jako niekoniecznie zgodny. –

Powiązane problemy