2010-11-02 9 views
5

das folgende Modul Gegeben:Warum denkt Python inspect.isclass, dass eine Instanz eine Klasse ist?

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

warum foo in der Ausgabe von inspect.getmembers(..., predicate=inspect.isclass) nicht angezeigt?

$ 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 

Ich erwartete, dass inspect nur Dummy zurückkehren würde, da dies die einzige Klassendefinition im Modul ist. Anscheinend ist junk.foo eine Klasse in den Augen des inspect-Moduls. Warum das?

Antwort

10

Vor Python v2.7, inspect.isclass naiv angenommen, alles mit einem __bases__ Attribut muss eine Klasse sein.

Dummy ‚s __getattr__ macht Dummy Instanzen erscheinen jedes Attribut zu haben (mit einem Wert von None).

Daher scheint inspect.isclass, foo eine Klasse zu sein.

Hinweis: __getattr__ should raiseAttributeError when asked for an attribute it does not know about. (. Dies ist ganz anders als None Rückkehr)

+1

Insbesondere das Fehlen von 'AttributeError' die wird wirklich stupend __horrible__ Bugs verursachen. – katrielalex

+0

Danke. Deine Erklärung ergibt vollkommenen Sinn. –

4

Zuerst, wenn alle große Antwort Jon-Eric Ich wollte nur ein paar Sachen hinzuzufügen:

, wenn Sie in ipython tun (was für ein großes Werkzeug):

%psource inspect.isclass 

Sie erhalten:

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

was Jon-Eric sagte.

aber ich denke, dass Sie verwenden Python < 2.6 und dieser Fehler bereits behoben wurde, ist dies der Code von inspect.isclass() in python2.7:

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

Ausgezeichneter Punkt! Ich * schaute * auf die v2.6-Quelle. Ich habe meine Antwort bearbeitet, um anzuzeigen, dass "__bases__" in v2.7 + nicht mehr verwendet wird. –

Verwandte Themen