2010-11-04 25 views
5

Tôi muốn có thể lặp qua tất cả các lớp cơ sở, cả trực tiếp và gián tiếp, của một lớp nhất định, bao gồm cả chính lớp đó. Điều này rất hữu ích trong trường hợp bạn có một metaclass kiểm tra lớp Tùy chọn bên trong của tất cả các cơ sở của nó.Có chức năng tiêu chuẩn nào để lặp qua các lớp cơ sở không?

Để làm điều này, tôi đã viết như sau:

def bases(cls): 
    yield cls 
    for direct_base in cls.__bases__: 
     for base in bases(direct_base): 
      yield base 

Có một chức năng tiêu chuẩn để làm việc này cho tôi?

Trả lời

12

Có một phương pháp có thể trả lại tất cả, theo Thứ tự phân giải phương pháp (MRO): inspect.getmro. Xem ở đây:

http://docs.python.org/library/inspect.html#inspect.getmro

Nó trả về họ như là một tuple, mà sau đó bạn có thể duyệt qua trong một vòng lặp đơn tự hỏi:

import inspect 
for base_class in inspect.getmro(foo): 
    # do something 

này có lợi ích phụ của chỉ năng suất mỗi lớp cơ sở một lần , ngay cả khi bạn có thừa kế kiểu kim cương.

0

Tôi không biết chính xác nếu nó là những gì bạn đang tìm kiếm, nhưng có một cái nhìn tại someclass.__mro__, MRO là Phương pháp Nghị quyết thứ tự

http://docs.python.org/library/stdtypes.html?highlight=mro#class.__mro__

+1

Điều này có nhược điểm (có thể tranh cãi) khi không làm việc với các lớp kiểu cũ. 'inspect.getmro' trả về' cls .__ mro__' nếu nó hiện diện (nó nằm trong các lớp kiểu mới) và thực hiện tìm kiếm tùy chỉnh nếu không. (Thực tế thú vị: Bạn có thể tạo lỗi đệ quy bằng cách tạo phân cấp lớp kiểu cũ với nhiều lớp hơn độ sâu đệ quy tối đa và gọi 'getmro' trên đó) – aaronasterling

1

Amber đã câu trả lời đúng cho thế giới thực, nhưng tôi sẽ chỉ ra một cách chính xác để làm điều này. Giải pháp của bạn sẽ bao gồm một số lớp hai lần nếu hai lớp cơ sở tự kế thừa từ cùng một lớp cơ sở.

def bases(cls): 
    classes = [cls] 
    i = 0 
    while 1: 
     try: 
      cls = classes[i] 
     except IndexError: 
      return classes 
     i += 1 
     classes[i:i] = [base for base in cls.__bases__ if base not in classes] 

Phần hơi khó duy nhất là nơi chúng tôi sử dụng lát. Đó là cần thiết để thực hiện loại tìm kiếm đầu tiên chiều sâu này mà không sử dụng đệ quy. Tất cả những gì nó làm là lấy các lớp cơ sở của lớp đang được kiểm tra và chèn chúng ngay sau nó để lớp cơ sở đầu tiên là lớp kế tiếp được kiểm tra. Một giải pháp rất dễ đọc (có sự xấu xí của chính nó) có sẵn trong việc thực hiện inspect.getmro trong thư viện chuẩn.

+0

Cảm ơn. Tôi nhận ra sau khi tôi đăng rằng tôi có thể trúng cùng một lớp hai lần nhưng trong trường hợp của tôi nó không quan trọng. –

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