2010-11-02 1 views
5

Учитывая следующий модуль:Почему python inspect.isclass считает, что экземпляр - это класс?

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

почему foo отображаться на выходе 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 

Я ожидал, что inspect будет возвращать только Dummy, поскольку это единственное определение класса в модуле. Очевидно, однако, junk.foo - это класс в глазах проверяющего модуля. Почему это?

ответ

10

До Python v2.7, inspect.isclass наивно предполагалось, что все с атрибутом __bases__ должно быть классом.

Dummy «S __getattr__ делает Dummy случаи, как представляется, каждый атрибут (со значением None).

Таким образом, для inspect.isclass, foo представляется классом.

Примечание: __getattr__ should raiseAttributeError when asked for an attribute it does not know about. (. Это очень отличается от возвращения None)

+1

В частности, отсутствие 'AttributeError' который вызовет поистине колоссальные ошибки __horrible__. – katrielalex

+0

Спасибо. Ваше объяснение имеет смысл. –

4

Прежде если все большой ответ Джон-Эрик я просто хотел бы добавить некоторые вещи:

если вы в IPython (что большая инструмент):

%psource inspect.isclass 

вы получите:

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

который Джон-Эрик сказал.

, но я предполагаю, что вы используете питона < 2,6 и эта ошибка уже была фиксированной, это код inspect.isclass() в python2.7:

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

Отличная точка! Я * * смотрел на источник v2.6. Я отредактировал свой ответ, указав, что '__bases__' больше не используется в v2.7 +. –

 Смежные вопросы

  • Нет связанных вопросов^_^