2017-07-24 18 views
8
class A(object): 
    def __get(self): 
     pass 

    def _m(self): 
     return self.__get() 


class B(A): 
    def _m(self): 
     return str(self.__get()) 

print(A()._m()) 
print(B()._m()) 

Tại sao print(A()._m()) in None, nhưng print(B()._m()) tăng AttributeError: 'B' object has no attribute '_B__get'?đúp nhấn trong python

Tôi nghĩ rằng dấu gạch dưới kép ngăn chặn phương pháp ghi đè.

CẬP NHẬT

Bạn viết rằng __get là tư nhân.

Sau đó, tại sao công việc sau đây?

class A(object): 
    def __get(self): 
     pass 

    def _m(self): 
     return self.__get() 


class B(A): 
    pass 

print(A()._m()) 
print(B()._m()) 

Tại sao mã này không làm tăng AttributeError và in None hai lần?

+2

[Tên mangling] (https://docs.python.org/3/tutorial/classes.html#private-variables). Gọi 'self .__ get()' trong 'B' thực sự gọi' self._B__get() ', không tồn tại. Trừ khi bạn muốn hành vi này, không sử dụng dấu gạch dưới kép hàng đầu. – kindall

+0

Khám phá [ý nghĩa của dấu gạch dưới đơn và dấu gạch đôi là gì trước tên đối tượng] (https://stackoverflow.com/questions/1301346/what-is-the-meaning-of-a-single-and-a -double-underscore-before-an-object-name? rq = 1) và một số câu hỏi được liên kết vì có một số giải thích chi tiết. – JGreenwell

+0

Cập nhật của bạn: Bởi vì bạn đang gọi __get từ một phương thức được định nghĩa trong lớp A. Điều đó hoàn toàn hợp pháp trong bất kỳ ngôn ngữ nào hỗ trợ khái niệm riêng tư - thực tế đó là trường hợp sử dụng phổ biến nhất của các phương thức riêng tư. –

Trả lời

7

Leading tên gạch dưới đôi đang private (có nghĩa là không có sẵn cho các lớp thừa kế)

Đây không phải là hoàn hảo. Nó được thực hiện bằng cách mangling tên. Python Documentation nói:

Bất kỳ định dạng __spam (ít nhất là hai dấu gạch hàng đầu, nhiều nhất một dấu gạch dưới) được textually thay thế bằng _classname__spam, nơi classname là tên lớp hiện tại với gạch hàng đầu (s) tước . Việc xén này được thực hiện mà không quan tâm đến đến vị trí cú pháp của mã định danh, vì vậy nó có thể được sử dụng để xác định cá thể lớp và biến lớp, phương thức, biến số được lưu trữ trong hình cầu và thậm chí cả các biến được lưu trữ trong trường hợp. riêng tư cho lớp này về các phiên bản của các lớp khác.

Như vậy __get là thực sự đọc sai để _A__get trong lớp A. Khi lớp B cố gắng tham khảo __get, nó được đọc sai để _B__get mà không phù hợp.

Nói cách khác __plugh được định nghĩa trong lớp Xyzzy có nghĩa là "trừ khi bạn đang chạy như lớp Xyzzy, bạn sẽ không chạm vào __plugh".

+1

_ "Các tên gạch dưới kép hàng đầu là' riêng tư '(nghĩa là không có sẵn cho các lớp dẫn xuất) "_ Xin đừng làm điều này. Có chú ý được gọi là riêng tư trong Python, những cái tên đó là (pseudoprivate) và không riêng tư. – direprobs

+0

@direprobs MỤC ĐÍCH của dấu gạch dưới hàng đầu là để ẩn các biểu tượng từ everone ngoại trừ lớp xác định. Trong nhiều ngôn ngữ khác, khái niệm này được gọi là "riêng tư". Do đó tôi đã sử dụng một từ duy nhất cho khái niệm nên được công nhận rõ ràng. Ngoài ra tôi đã giải thích chi tiết thực hiện và đề cập đến việc thiếu tính dễ sử dụng. Bạn đề nghị truyền đạt khái niệm này như thế nào? –

+0

Đó là vấn đề.Từ riêng tư sẽ gợi ý riêng tư như trong Java chẳng hạn, biến không thể được truy cập từ bên ngoài lớp. Bạn nói rằng biến sẽ không có sẵn cho lớp dẫn xuất, điều đó hoàn toàn sai. – direprobs

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