2013-02-15 28 views
5

Hãy xem xét một lớp học với một phương pháp "private" như:override phương pháp "private" bằng Python

class Foo(object): 
    def __init__(self): 
     self.__method() 
    def __method(self): 
     print('42') 

Khi tôi cố gắng phân lớp Foo và phương pháp ghi đè __method, nó có thể được nhìn thấy rằng Foo.__method vẫn gọi, thay vì MoreFoo.__method.

class MoreFoo(Foo): 
    def __method(self): 
     print('41') 

>>> MoreFoo() 
42 
<__main__.MoreFoo object at 0x7fb726197d90> 

Cách nào để ghi đè phương pháp như vậy?

+0

http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python – tacaswell

+0

Không quan tâm, ở đâu bạn có nhận được ý tưởng rằng điều này tương đương với một biến riêng tư không? Đó là một quan niệm sai lầm thực sự tồi tệ, và tôi thấy nó mọi lúc mà không biết nó đến từ đâu. –

+1

@Lattyware - Tôi nghĩ rằng nó xuất phát từ phần trên các tài liệu có tên là "Biến riêng tư và Tham chiếu lớp địa phương". Nó tiếp tục nói rằng không có biến riêng ... nhưng điều nhấn kép là gần nhất bạn có thể nhận được - "Vì có một trường hợp sử dụng hợp lệ cho các thành viên lớp riêng (cụ thể là để tránh xung đột tên của tên với các tên được xác định bởi các lớp con), có sự hỗ trợ giới hạn cho một cơ chế như vậy, ... " – mgilson

Trả lời

16

điểm sử dụng quy ước tên hai gạch dưới là để ngăn các lớp con từ (vô tình) ghi đè phương pháp.

Nếu bạn để ghi đè lên, người nào đó đã tạo lỗi thiết kế nghiêm trọng. Bạn có thể làm điều đó vẫn còn, bằng cách đặt tên đối tượng của bạn chỉ như vậy:

def _Foo__method(self): 

nơi bạn có tiền tố tên phương pháp với thêm một dấu gạch dưới và classname định (vì vậy trong trường hợp này bắt đầu bằng _Foo). Quá trình đổi tên phương pháp và các thuộc tính có dấu gạch dưới kép được gọi là private name mangling.

Nếu bạn muốn xác định phương thức 'riêng tư' vẫn có thể ghi đè trong lớp con, bạn thường gắn vào tên bằng một dấu gạch dưới thay vì (def _method(self):).

Do tính chất động, hầu như không có gì trong Python thực sự là riêng tư; với một chút nội tâm gần như bất cứ điều gì có thể đạt được.

8

Tiền tố gạch dưới đôi gọi tên mangling, đó là không tương đương với phương pháp riêng tư. Nó được thiết kế đặc biệt để tránh bị ghi đè bởi các lớp con (và trong trường hợp này, tên phương thức trở thành _Foo__method).

Nếu bạn có chi tiết triển khai, hãy thêm tiền tố vào một dấu gạch dưới, đây là dấu hiệu được chấp nhận chung cho các phương thức Python không được sử dụng bên ngoài. Không có thực thi điều này, bởi vì đó không phải là cách Python hoạt động.

+0

Tôi biết nó không thực sự riêng tư, đây là lý do tại sao tôi viết riêng giữa các dấu ngoặc kép. –

+0

@ErnestA Nó không chỉ là nó * không thực sự * riêng tư, nó là không có cách nào tương tự hoặc so sánh - nó điền vào một vai trò hoàn toàn khác nhau. –

+0

Tôi đã được ấn tượng rằng nó đã được OK để gọi phương pháp bắt đầu với 2 dấu gạch dưới "tư nhân". Có lẽ nó không phải. Trong trường hợp này xin lỗi vì sử dụng thuật ngữ sai. –

3

Tôi tin rằng bạn sẽ làm điều gì đó như:

class MoreFoo(Foo): 
    def _Foo__method(self): 
     print('41') 

như documented.

Bất kỳ định dạng __spam (ít nhất là hai dấu gạch hàng đầu, ít nhất một dấu gạch dưới) được thay thế bằng bản văn _classname__spam, nơi classname là tên lớp hiện tại với gạch hàng đầu (s) tước.

Nhưng các nhà thiết kế của lớp ban đầu đã có ý kiến ​​rằng bạn không cần phải làm điều gì đó như thế này là làm cho nó khó khăn để ghi đè lên với subclassing là toàn bộ điểm của dấu gạch dưới đôi để bắt đầu với:

Tên mangling là hữu ích để cho phép các lớp con ghi đè các phương thức mà không vi phạm các cuộc gọi phương thức intraclass.

+0

Về mặt kỹ thuật, điều này sẽ hiệu quả, nhưng nó sẽ che giấu vấn đề nghiêm trọng hơn về việc lạm dụng dấu gạch dưới kép ở vị trí đầu tiên. –

+0

@AndrewGorcester - Chắc chắn rồi. Tôi không nói rằng đây là một ý tưởng hay. – mgilson

+0

Cảm ơn. Tôi không viết lớp gốc. Tôi chỉ muốn ghi đè lên một trong những phương pháp của nó xảy ra để bắt đầu với hai dấu gạch dưới. –