2015-01-28 19 views
5

Tôi mới dùng python và tôi không chắc mình đang làm gì là chính xác. Tôi có một lớp cơ sở A và một lớp được thừa hưởng B.Thừa kế tài sản Python

class A(object): 

    def __init__(self, name): 
     self.__name = name 

    @property 
    def name(self): 
     return self.__name 

    @name.setter 
    def name(self, name): 
     self.__name = name 

class B(A): 
    def __init__(self, name): 
     super(NominalValue, self).__init__(name) 

    @property 
    def name2(self): 
     return self.__name2 

    @name2.setter 
    def name2(self, n): 
     self.__name2 = n 

    def toString(): 
     print self.__name + self.__name2 

if __name__ == "__main__": 
    instance = B('name'); 
    instance.toString() 

Khi tôi chạy nó than phiền rằng lớp B không có bất kỳ thuộc tính __name.

AttributeError: 'B' object has no attribute '_B__name' 

Tôi rõ ràng không thực hiện kế thừa một cách chính xác. Làm thế nào để bạn xử lý các thuộc tính được thừa kế một cách chính xác và tránh lặp lại các thuộc tính trong lớp được kế thừa?

+3

Dấu gạch dưới kép có [ý nghĩa đặc biệt] (https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references) gây trở ngại cho kế thừa của bạn. Để truy cập thuộc tính '__name' của lớp cha, tôi nghĩ bạn cần tham chiếu đến nó là' self._A__name'. –

+2

Như 6502 đề cập trong câu trả lời của mình, bạn không nhất thiết phải * KẾ HOẠCH * về việc phải viết một tài sản cho lớp học của bạn.Đây là một trong những điểm mạnh của các thuộc tính trong Python: nó rất dễ dàng để chuyển đổi một thuộc tính sang một thuộc tính khi đang bay. Trừ khi có thể hiểu được rằng bạn cần phải có logic tùy chỉnh để nhận, đặt hoặc xóa thuộc tính - không sử dụng thuộc tính để thực hiện. –

Trả lời

7

Thuộc tính bắt đầu bằng hai dấu gạch dưới như __name của bạn được biểu hiện dưới dạng biến riêng tư. Không có thực tế BẢO VỆ được thực hiện cho những điều này (có nghĩa là: nếu bạn có thể tìm thấy nó, bạn có thể truy cập nó), nhưng chúng bị xé tên để dễ truy cập hơn. More information about that can be found on the docs page

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.

Bởi vì điều này, ngay cả khi bạn đang kế thừa A 's __name thuộc tính, bạn không có một thuộc tính __name trong bất kỳ đối tượng kiểu B. Những gì bạn có là thuộc tính _A__name. Đó là cách hoạt động của tên mangling: __attributename trở thành _classname__attributename

Thay vào đó, bạn chỉ có thể sử dụng _name để gắn cờ cho người dùng trong tương lai. Sau đó, toàn bộ mã của bạn sẽ hoạt động.

5

Tên thuộc tính bắt đầu bằng dấu gạch dưới kép được xử lý đặc biệt bởi trình biên dịch và bạn nên tránh chúng cho đến khi bạn hiểu Python tốt hơn.

Hầu hết các lập trình viên Python không biết tại sao chúng lại đặc biệt và chúng vẫn có thể sống một cuộc sống lập trình hạnh phúc và hiệu quả. Họ cũng là khách quan xấu xí ... bạn không nghĩ sao?

Cũng lưu ý rằng trong Python, bạn không bắt đầu sử dụng getter và setter chỉ để giải trí. Đơn giản chỉ cần bắt đầu với một thành viên dữ liệu và chỉ di chuyển đến các thuộc tính khi (và chỉ khi) cần thiết. Viết mã cho một getter mà chỉ đơn giản là trả về các thành viên và cho một setter mà chỉ đơn giản là mutates nó là vô nghĩa. Khi (và nếu), bạn sẽ cần phải thực hiện xử lý đặc biệt khi truy cập thành viên thay đổi chúng thành các thuộc tính, và sẽ không cần phải thay đổi mã bằng cách sử dụng lớp của bạn. Trên khía cạnh giải thích kỹ thuật Python chỉ cần thêm tên lớp vào các thuộc tính bắt đầu bằng dấu gạch dưới kép để tránh các xung đột không mong muốn với các thuộc tính được đặt tên giống nhau trong các lớp khác. Loại vấn đề này tuy nhiên không quá phổ biến và đó là lý do tại sao hầu hết các lập trình viên Python không bao giờ có sự cần thiết của tính năng này.