Encapsulation là quá trình gộp các thuộc tính và phương thức trong một đơn vị duy nhất. Đây là một trong những trụ cột chính mà object-oriented programming được dựa trên.
Chúng tôi biết rằng một lớp là một nguyên mẫu do người dùng định nghĩa cho một đối tượng. Nó định nghĩa một tập hợp các thành viên dữ liệu và methods , có khả năng xử lý dữ liệu.
Theo nguyên tắc đóng gói dữ liệu, các thành viên dữ liệu mô tả một đối tượng được ẩn khỏi môi trường bên ngoài lớp. Chúng chỉ có thể được truy cập thông qua các phương thức trong cùng một lớp. Các phương thức, mặt khác, có thể được truy cập từ bên ngoài ngữ cảnh lớp. Do đó, dữ liệu của đối tượng được cho là được đóng gói bởi các phương thức. Bằng cách này, đóng gói ngăn chặn việc truy cập trực tiếp vào dữ liệu của đối tượng.
Các ngôn ngữ như C++ và Java sử dụng access modifiers để hạn chế quyền truy cập vào các thành viên của lớp (tức là, biến và phương thức). Những ngôn ngữ này có các từ khóa public, protected và private để chỉ định loại quyền truy cập.
Một thành viên của lớp được gọi là công khai nếu nó có thể được truy cập từ bất kỳ đâu trong chương trình. Các thành viên riêng tư chỉ được phép truy cập từ bên trong lớp. Thông thường, các phương thức được định nghĩa là công khai, và các biến thể hiện là riêng tư. Sự sắp xếp này của các biến thể hiện riêng tư và các phương thức công khai đảm bảo việc thực hiện encapsulation .
Khác với những ngôn ngữ này, Python không có quy định để chỉ định loại quyền truy cập mà một thành viên lớp có thể có. Mặc định, tất cả các biến và phương thức trong một lớp Python đều là công khai, như được minh họa bởi ví dụ sau đây.
Ở đây, chúng ta có một lớp Employee với các biến thể hiện, name và age . Một đối tượng của lớp này có hai attributes . Chúng có thể được truy cập trực tiếp từ bên ngoài lớp, vì chúng là công khai.
class Student: def __init__(self, name="Rajaram", marks=50): self.name = name self.marks = marks s1 = Student() s2 = Student("Bharat", 25) print ("Name: {} marks: {}".format(s1.name, s2.marks)) print ("Name: {} marks: {}".format(s2.name, s2.marks))
Nó sẽ tạo ra output −
Name: Rajaram marks: 50 Name: Bharat marks: 25
Trong ví dụ trên, các biến thể hiện được khởi tạo bên trong lớp. Tuy nhiên, không có hạn chế nào về việc truy cập giá trị của các biến thể hiện từ bên ngoài lớp, điều này đi ngược lại với nguyên tắc đóng gói.
Mặc dù không có từ khóa nào để thực thi tính khả thi, Python có một quy ước về việc đặt tên cho các biến thể hiện theo một cách đặc biệt. Trong Python, việc thêm tiền tố tên của một biến/phương thức bằng một hoặc hai dấu gạch dưới để mô phỏng hành vi của các bộ điều chỉnh quyền truy cập protected và private.
Nếu một biến được tiền tố bởi một dấu gạch dưới đôi (chẳng hạn như " __age "), thì biến thể hiện là riêng tư, tương tự như khi tên biến được tiền tố bằng một dấu gạch dưới đơn (chẳng hạn như " _salary ").
Hãy sửa đổi lớp Student. Thêm một biến thể hiện khác là salary. Đặt tên là private và marks là private bằng cách thêm hai dấu gạch dưới ở trước chúng.
class Student: def __init__(self, name="Rajaram", marks=50): self.__name = name self.__marks = marks def studentdata(self): print ("Name: {} marks: {}".format(self.__name, self.__marks)) s1 = Student() s2 = Student("Bharat", 25) s1.studentdata() s2.studentdata() print ("Name: {} marks: {}".format(s1.__name, s2.__marks)) print ("Name: {} marks: {}".format(s2.__name, __s2.marks))
Khi bạn chạy đoạn mã này, nó sẽ tạo ra output −
Name: Rajaram marks: 50 Name: Bharat marks: 25 Traceback (most recent call last): File "C:\Python311\hello.py", line 14, in <module> print ("Name: {} marks: {}".format(s1.__name, s2.__marks)) AttributeError: 'Student' object has no attribute '__name'
Đầu ra trên cho thấy rằng các biến thể hiện name và age có thể được truy cập bởi một phương thức được khai báo bên trong lớp (phương thức studentdata()), nhưng tiền tố hai dấu gạch dưới làm cho các biến này trở thành riêng tư, do đó, việc truy cập chúng bên ngoài lớp là bị hạn chế, dẫn đến lỗi Attribute.
Python không hoàn toàn chặn quyền truy cập vào dữ liệu riêng tư. Nó chỉ để lại cho sự khôn ngoan của lập trình viên, không viết bất kỳ mã nào truy cập nó từ bên ngoài lớp. Bạn vẫn có thể truy cập các thành viên riêng tư bằng kỹ thuật "name mangling" của Python.
Name mangling là quá trình thay đổi tên của một thành viên có hai dấu gạch dưới thành dạng object._class__variable . Nếu cần, nó vẫn có thể được truy cập từ bên ngoài lớp, nhưng nên tránh thực hành này.
Trong ví dụ của chúng tôi, biến thể hiện riêng tư "__name" được mã hóa bằng cách chuyển đổi nó thành định dạng
obj._class__privatevar
Vì vậy, để truy cập giá trị của biến thể hiện "__marks" của đối tượng "s1", hãy thay đổi nó thành "s1._Student__marks".
Thay đổi câu lệnh print() trong chương trình trên thành -
print (s1._Student__marks)
Bây giờ nó in ra 50, điểm số của s1.
Do đó, chúng ta có thể kết luận rằng Python không thực hiện đóng gói chính xác như theo lý thuyết của lập trình hướng đối tượng. Nó áp dụng một cách tiếp cận trưởng thành hơn bằng cách quy định một quy ước đặt tên và cho phép lập trình viên sử dụng làm méo tên nếu thực sự cần truy cập vào dữ liệu riêng tư trong phạm vi công khai.