2008-10-23 40 views
24

Trong C++, bạn có thể vô hiệu hóa một hàm trong lớp của cha mẹ bằng cách khai báo nó là riêng tư trong lớp con. Làm thế nào điều này có thể được thực hiện bằng Python? I E. Làm cách nào để ẩn chức năng của cha mẹ khỏi giao diện công khai của trẻ?Thừa kế Python - cách vô hiệu hóa chức năng

Trả lời

18

Có thực sự không có bất kỳ sự thật "private" thuộc tính hoặc các phương pháp trong Python . Một điều bạn có thể làm chỉ đơn giản là ghi đè lên các phương pháp mà bạn không muốn trong lớp con, và nâng cao một ngoại lệ: Phương pháp

>>> class Foo(object): 
...  def foo(self): 
...   print 'FOO!' 
...   
>>> class Bar(Foo): 
...  def foo(self): 
...   raise AttributeError("'Bar' object has no attribute 'foo'") 
...  
>>> b = Bar() 
>>> b.foo() 
Traceback (most recent call last): 
    File "<interactive input>", line 1, in <module> 
    File "<interactive input>", line 3, in foo 
AttributeError: 'Bar' object has no attribute 'foo' 
+0

> Thực sự không có bất kỳ thuộc tính hoặc phương thức "riêng tư" thực sự nào trong Python. Đó là lý do tại sao tôi không hỏi cách đặt chúng ở chế độ riêng tư, nhưng cách 'xóa' chúng khỏi giao diện. Hy vọng rằng phiên bản đã chỉnh sửa chính xác hơn –

+2

Tôi đồng ý rằng NotImplementedError có lẽ là cách tốt nhất để sử dụng, nhưng nếu bạn thực sự muốn không phù hợp với phương pháp kế thừa, hãy nâng AttributeError (đó là những gì bạn sẽ nhận được nếu phương thức không tồn tại). –

+1

Điểm tốt về AttributeError. Tôi sẽ cập nhật ví dụ của mình. – kurosch

5
class X(object): 
    def some_function(self): 
     do_some_stuff() 

class Y(object): 
    some_function = None 

Điều này có thể dẫn đến một số khó chịu và khó có thể tìm thấy trường hợp ngoại lệ được ném mặc dù, vì vậy bạn có thể thử này:

class X(object): 
    def some_function(self): 
     do_some_stuff() 

class Y(object): 
    def some_function(self): 
     raise NotImplementedError("function some_function not implemented") 
17

kurosch của việc giải quyết vấn đề không phải là khá đúng, vì bạn vẫn có thể sử dụng mà không cần b.foo nhận được AttributeError. Nếu bạn không gọi hàm, không có lỗi xảy ra. Dưới đây là hai cách mà tôi có thể nghĩ để làm điều này:

import doctest 

class Foo(object): 
    """ 
    >>> Foo().foo() 
    foo 
    """ 
    def foo(self): print 'foo' 
    def fu(self): print 'fu' 

class Bar(object): 
    """ 
    >>> b = Bar() 
    >>> b.foo() 
    Traceback (most recent call last): 
    ... 
    AttributeError 
    >>> hasattr(b, 'foo') 
    False 
    >>> hasattr(b, 'fu') 
    True 
    """ 
    def __init__(self): self._wrapped = Foo() 

    def __getattr__(self, attr_name): 
     if attr_name == 'foo': raise AttributeError 
     return getattr(self._wrapped, attr_name) 

class Baz(Foo): 
    """ 
    >>> b = Baz() 
    >>> b.foo() # doctest: +ELLIPSIS 
    Traceback (most recent call last): 
    ... 
    AttributeError... 
    >>> hasattr(b, 'foo') 
    False 
    >>> hasattr(b, 'fu') 
    True 
    """ 
    foo = property() 

if __name__ == '__main__': 
    doctest.testmod() 

Thanh sử dụng mẫu "bọc" để hạn chế quyền truy cập vào đối tượng được bao bọc. Martelli has a good talk giải quyết vấn đề này. Baz sử dụng the property built-in để triển khai giao thức mô tả cho thuộc tính ghi đè.

+2

Vâng, chắc chắn, trong câu trả lời của tôi nó vẫn còn "nhìn thấy", nhưng bạn không thể "sử dụng" nó cho mỗi người vì nó sẽ làm tăng ngoại lệ. Một điểm hợp lệ, mặc dù. – kurosch

+2

+1, một mẹo thông minh để sử dụng thuộc tính "trống" để "xóa" phương thức foo! : D – MestreLion

+0

Điều này sẽ phá vỡ lớp để sử dụng toán tử được xác định trên cấp độ gốc vì không có lớp con. Ngoài ra '__getattr__' là chậm – JBernardo

0

Đây là cách sạch nhất mà tôi biết để làm điều đó.

Ghi đè các phương thức và yêu cầu mỗi phương thức ghi đè gọi phương thức disabledmethods() của bạn. Như thế này:

class Deck(list): 
... 
@staticmethod 
    def disabledmethods(): 
     raise Exception('Function Disabled') 
    def pop(self): Deck.disabledmethods() 
    def sort(self): Deck.disabledmethods() 
    def reverse(self): Deck.disabledmethods() 
    def __setitem__(self, loc, val): Deck.disabledmethods() 
9

Một biến thể của câu trả lời của kurosch:

class Foo(object): 
    def foo(self): 
     print 'FOO!' 

class Bar(Foo): 
    @property 
    def foo(self): 
     raise AttributeError("'Bar' object has no attribute 'foo'") 

b = Bar() 
b.foo 

Điều này đặt ra một AttributeError trên tài sản thay vì khi phương pháp này được gọi.

Tôi đã đề xuất nó trong nhận xét nhưng tiếc là chưa có danh tiếng cho nó.

+0

Điều này có làm tăng AttributeError nếu bạn gọi 'getattr (b," Foo ")'? Thật không may, tôi không có một thông dịch viên Python ở đây để kiểm tra nó. –

+0

nếu bạn có nghĩa là 'getattr (b, 'foo')' thì có nó sẽ –

+0

Vâng, đó là ý của tôi. Mặc dù 'getattr (b, 'Foo')' cũng sẽ cung cấp cho bạn một lỗi thuộc tính, do đó, không phải lo lắng ở đó! –

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