2010-11-02 12 views
5

Biorąc pod uwagę następujący moduł:dlaczego python inspect.isclass uważa, że ​​instancja jest klasą?

class Dummy(dict): 
    def __init__(self, data): 
     for key, value in data.iteritems(): 
      self.__setattr__(key, value) 

    def __getattr__(self, attr): 
     return self.get(attr, None) 
    __setattr__=dict.__setitem__ 
    __delattr__=dict.__delitem__ 


foo=Dummy({"one":1, "two":2}) 

dlaczego foo pokazać się na wyjściu inspect.getmembers(..., predicate=inspect.isclass)?

$ python2.5 
Python 2.5.2 (r252:60911, Aug 28 2008, 13:13:37) 
[GCC 4.1.2 20071124 (Red Hat 4.1.2-42)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import junk 
>>> import inspect 
>>> inspect.getmembers(junk, predicate=inspect.isclass) 
[('Dummy', <class 'junk.Dummy'>), ('foo', {'two': 2, 'one': 1})] 
>>> inspect.isclass(junk.foo) 
True 

Spodziewałem się, że będzie tylko inspect powrócić Dummy ponieważ jest to jedyna definicja klasy w module. Najwyraźniej jednak junk.foo jest klasą w oczach modułu inspekcyjnego. Dlaczego?

Odpowiedz

10

Przed Pythonem v2.7, inspect.isclass naiwnie przyjęto, że wszystko z atrybutem __bases__ musi być klasą.

Dummy „S __getattr__ sprawia Dummy przypadki wydają się mieć każdy atrybut (o wartości None).

Dlatego też, do , foo wydaje się być klasą.

Uwaga: __getattr__ should raiseAttributeError when asked for an attribute it does not know about. (. To jest zupełnie inna niż powrocie None)

+1

W szczególności brak 'AttributeError' który spowoduje naprawdę zdumiewające błędy. – katrielalex

+0

Dziękuję. Twoje wyjaśnienie ma sens. –

4

pierwsze jeśli wszystko wielki odpowiedź Jon-Eric chciałem tylko dodać kilka rzeczy:

jeśli nie w ipython (co wielkie narzędzie):

%psource inspect.isclass 

dostaniesz:

return isinstance(object, types.ClassType) or hasattr(object, '__bases__') 

, co powiedział Jon-Eric.

ale myślę, że używasz Pythona < 2,6 i ten błąd został już ustalony, jest to kod inspect.isclass() w python2.7:

return isinstance(object, (type, types.ClassType)) 
+0

Doskonały punkt! Ja * patrzyłem na źródło v2.6. Edytowałem swoją odpowiedź, aby wskazać, że '__bases__' nie jest już używane w wersji 2.7 +. –

Powiązane problemy