2010-11-02 29 views
5

Với các module sau:tại sao python inspect.isclass lại nghĩ một cá thể là một lớp?

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

tại sao foo hiện lên trong đầu ra của 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 

tôi mong đợi rằng inspect sẽ chỉ trả lại Dummy vì đó là định nghĩa lớp duy nhất trong mô-đun. Rõ ràng, mặc dù, junk.foo là một lớp trong mắt của mô-đun kiểm tra. Tại sao vậy?

Trả lời

10

Trước Python v2.7, inspect.isclass ngây thơ giả định bất kỳ thứ gì có thuộc tính __bases__ phải là một lớp.

Dummy 's __getattr__ làm Dummy trường hợp xuất hiện để có mỗi thuộc tính (với một giá trị của None).

Do đó, đến inspect.isclass, foo dường như là một lớp học.

Lưu ý: __getattr__ should raiseAttributeError when asked for an attribute it does not know about. (. Điều này rất khác so với trở None)

+1

Đặc biệt thiếu của 'AttributeError' mà sẽ gây ra những lỗi thực sự tuyệt đối __horrible__. – katrielalex

+0

Cảm ơn bạn. Lời giải thích của bạn có ý nghĩa hoàn chỉnh. –

4

Đầu tiên nếu tất cả các câu trả lời tuyệt vời Jon-Eric tôi chỉ muốn thêm một số nội dung:

nếu bạn làm trong ipython (những gì một lớn công cụ):

%psource inspect.isclass 

bạn sẽ nhận được:

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

cái mà Jon-Eric đã nói.

nhưng tôi đoán rằng bạn sử dụng python < 2.6 và lỗi này đã được cố định, đây là mã của inspect.isclass() trong python2.7:

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

Điểm tuyệt vời! Tôi * đang * nhìn vào nguồn v2.6. Tôi đã chỉnh sửa câu trả lời của mình để cho biết rằng '__bases__' không còn được sử dụng trong phiên bản v2.7 + nữa. –

Các vấn đề liên quan