2010-11-02 25 views
5

Étant donné le module suivant:pourquoi python inspect.isclass pense qu'une instance est une classe?

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

pourquoi ne foo apparaître dans la sortie de 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 

Je m'y attendais inspect ne reviendrait Dummy puisque c'est la seule définition de classe dans le module. Apparemment, cependant, junk.foo est une classe aux yeux du module d'inspection. Pourquoi donc?

Répondre

10

Avant Python v2.7, inspect.isclass supposé naïvement n'importe quoi avec un attribut __bases__ doit être une classe.

Dummy__getattr__ rend les instances Dummy s » semblent avoir tous les attributs (avec une valeur de None). Par conséquent, à inspect.isclass, foo semble être une classe.

Note: __getattr__ should raiseAttributeError when asked for an attribute it does not know about. (. Ceci est très différent de retour None)

+1

En particulier, le manque de 'AttributeError' qui causera vraiment bugs __horrible__ vraiment stupéfiant. – katrielalex

+0

Merci. Votre explication prend tout son sens. –

4

Tout d'abord si tout grande réponse Jon-Eric je voulais juste ajouter quelques trucs:

si vous le faites dans ipython (quel grand outil):

%psource inspect.isclass 

vous obtiendrez:

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

ce que Jon-Eric a dit.

mais je suppose que vous utilisez python < 2.6 et ce bug a déjà été fixé, c'est le code de inspect.isclass() dans python2.7:

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

Excellent point! Je * regardais * la source v2.6. J'ai édité ma réponse pour indiquer que '__bases__' n'est plus utilisé dans v2.7 +. –