2011-10-13 31 views
8

Tôi muốn nói với các phương pháp kế thừa ngoài các phương thức quá tải hoặc mới được xác định. Điều đó có thể thực hiện được với Python không?Có cách nào để xác định một phương thức được kế thừa bằng Python không?

Ví dụ:

class A(object): 
    def spam(self): 
    print 'A spam' 
    def ham(self): 
    print 'A ham' 

class B(A): 
    def spam(self): 
    print 'Overloaded spam' 
    def eggs(self): 
    print 'Newly defined eggs' 

mong muốn chức năng:

>>> magicmethod(B.spam) 
'overloaded' 
>>> magicmethod(B.ham) 
'inherited' 
>>> magicmethod(B.eggs) 
'newly defined' 

Có một "phương pháp kỳ diệu" như trong ví dụ này, hoặc một số cách để nói với những loại phương pháp triển khai ngoài? đơn giản

Trả lời

12

Tôi không chắc đó là ý tưởng hay, nhưng bạn có thể làm điều đó bằng cách sử dụng hasattr__dict__.

def magicmethod(clazz, method): 
    if method not in clazz.__dict__: # Not defined in clazz : inherited 
     return 'inherited' 
    elif hasattr(super(clazz), method): # Present in parent : overloaded 
     return 'overloaded' 
    else: # Not present in parent : newly defined 
     return 'newly defined' 
7

Nếu bạn biết tổ tiên, bạn có thể kiểm tra:

>>> B.spam == A.spam 
False 
>>> B.ham == A.ham 
True 

Và để tìm danh sách tất cả các lớp học cơ sở, xem ở đây: List all base classes in a hierarchy of given class?

Tôi cũng sẽ chỉ rằng nếu bạn cần điều này, bạn thiết kế lớp học có lẽ là sai. Bạn không nên quan tâm đến những thứ như vậy trong OOP (trừ khi bạn đang tạo một thanh tra đối tượng hoặc một cái gì đó tương tự).

+0

Gọi tốt rằng đây là một yêu cầu lạ trong OOP – Pengman

+0

Đây là trường hợp đặc biệt, trong đó đối tượng có thể phải được mở rộng mà không bị phân lớp. Tôi phải kiểm tra xem liệu tôi có thể chỉ đơn giản là ghi đè lên một trong các phương pháp hay không hoặc liệu tôi có phải bảo toàn phương thức ghi đè đã tồn tại hay không. Vì vậy, có, nó là một thanh tra đối tượng trong một cách, mặc dù không cho mục đích gỡ lỗi/phân tích. Tôi nhận ra rằng điều này có thể không phải lúc nào cũng là một ý tưởng hay, nhưng tôi nghĩ trong trường hợp này, điều đó là hợp lý. Cảm ơn bạn đã chỉ ra các lỗi thiết kế có thể xảy ra. –

0

Mở rộng câu trả lời của hamstergene; một lớp lưu trữ các lớp cơ sở của nó trong biến lớp __bases__.

Vì vậy:

>>> B.spam == B.__bases__[0].spam 
False 
>>> B.ham == B.__bases__[0].ham 
True 
>>> B.eggs == B.__bases__[0].eggs 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: type object 'A' has no attribute 'eggs' 
>>> hasattr(B,"eggs") 
True 
>>> hasattr(B.__bases__[0],"eggs") 
False 
6

Một cách tổng quát sẽ được (python 2. *):

def _getclass(method): 
    try: 
     return method.im_class 
    except AttributeError: 
     return method.__class__ 

def magicmethod(method): 
    method_cls = _getclass(method) 
    if method.__name__ not in method_cls.__dict__: 
     return 'inherited' 
    for cls in method_cls.__mro__[1:]: 
     if method.__name__ in cls.__dict__: 
      return 'overloaded' 
    return 'newly defined' 


__test__ = {"example": """ 

    >>> class A(object): 
    ...  def spam(self): 
    ...   print 'A spam' 
    ...  def ham(self): 
    ...   print 'A ham' 

    >>> class B(A): 
    ...  def spam(self): 
    ...   print 'Overloaded spam' 
    ...  def eggs(self): 
    ...   print 'Newly defined eggs' 

    >>> magicmethod(B.spam) 
    'overloaded' 
    >>> magicmethod(B.ham) 
    'inherited' 
    >>> magicmethod(B.eggs) 
    'newly defined' 
    >>> magicmethod(B.__init__) 
    'inherited' 
"""} 
0

Đối với các lớp học kiểu mới, bạn có một phương pháp mro(), trở về danh sách phương pháp để resulution . [0] là chính lớp đó.

Vì vậy, bạn có thể làm

>>> any(hasattr(i, 'ham') for i in B.mro()[1:]) 
True 
>>> any(hasattr(i, 'spam') for i in B.mro()[1:]) 
True 
>>> any(hasattr(i, 'eggs') for i in B.mro()[1:]) 
False 

Vì vậy eggs mới được xác định.

>>> any(getattr(B, 'ham') == getattr(i, 'ham', None) for i in B.mro()[1:]) 
True 
>>> any(getattr(B, 'spam') == getattr(i, 'spam', None) for i in B.mro()[1:]) 
False 

Vì vậy, ham được kế thừa.

Với những điều này, bạn có thể tự tạo các phỏng đoán của riêng mình.

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