Các Python access modifiers được sử dụng để 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) từ bên ngoài lớp. Có ba loại bộ điều chỉnh quyền truy cập, bao gồm public, protected và private.
Public members − Một thành viên của lớp được coi là công khai nếu nó có thể được truy cập từ bất kỳ đâu trong chương trình.
Protected members − Chúng có thể được truy cập từ bên trong lớp cũng như bởi các lớp kế thừa từ lớp đó.
Private members − Chúng chỉ có thể được 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 (public) và các biến thể hiện (instance variable) là riêng tư (private). 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 nguyên tắc đóng gói (encapsulation).
Khác với C++ và Java, Python không sử dụng các từ khóa Public, Protected và Private để chỉ định loại bộ điều chỉnh quyền truy cập. Theo 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 (public).
Ở đây, chúng ta có lớp Employee với các biến thể hiện là name và age. Một đối tượng của lớp này có hai thuộc tính này. 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 Employee: 'Common base class for all employees' def __init__(self, name="Bhavana", age=24): self.name = name self.age = age e1 = Employee() e2 = Employee("Bharat", 25) print ("Name: {}".format(e1.name)) print ("age: {}".format(e1.age)) print ("Name: {}".format(e2.name)) print ("age: {}".format(e2.age))
Nó sẽ tạo ra output −
Name: Bhavana age: 24 Name: Bharat age: 25
Python không áp dụng các hạn chế đối với việc truy cập bất kỳ biến hoặc phương thức thể hiện nào. Tuy nhiên, Python quy định một quy ước là thêm tiền tố là dấu gạch dưới đơn hoặc gạch dưới đôi vào tên biến/phương thức để mô phỏng hành vi của các bộ điều chỉnh quyền truy cập protected và private.
Hãy sửa đổi lớp Employee. Thêm một biến thể hiện khác là salary. Đặt age là private và salary là protected bằng cách thêm hai dấu gạch dưới và một dấu gạch dưới tương ứng.
class Employee: def __init__(self, name, age, salary): self.name = name # public variable self.__age = age # private variable self._salary = salary # protected variable def displayEmployee(self): print ("Name : ", self.name, ", age: ", self.__age, ", salary: ", self._salary) e1=Employee("Bhavana", 24, 10000) print (e1.name) print (e1._salary) print (e1.__age)
Khi bạn chạy đoạn mã này, nó sẽ tạo ra output −
Bhavana 10000 Traceback (most recent call last): File "C:\Users\user\example.py", line 14, in <module> print (e1.__age) ^^^^^^^^ AttributeError: 'Employee' object has no attribute '__age'
Python hiển thị AttributeError vì __age là thuộc tính riêng tư và không có sẵn để sử dụng bên ngoài lớp.
Python không 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 vào 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 đổi tên 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 "__name" được biến đổi bằng cách thay đổi nó thành định dạng −
obj._class__privatevar
Vì vậy, để truy cập giá trị của biến instance "__age" của đối tượng "e1", hãy thay đổi nó thành "e1._Employee__age".
Thay đổi câu lệnh print() trong chương trình trên thành −
print (e1._Employee__age)
Nó bây giờ in ra 24, độ tuổi của e1 .
Thư viện chuẩn của Python có một hàm tích hợp sẵn là property(). Hàm này trả về một đối tượng property. Nó hoạt động như một giao diện cho các biến thể hiện của một lớp Python.
Nguyên tắc đóng gói trong lập trình hướng đối tượng yêu cầu rằng các biến thể hiện (instance variables) nên có quyền truy cập riêng tư hạn chế. Python không có cơ chế hiệu quả cho mục đích này. Hàm property() cung cấp một lựa chọn thay thế.
Hàm property() sử dụng các phương thức getter, setter và delete được định nghĩa trong một lớp để định nghĩa một đối tượng thuộc tính cho lớp đó.
property(fget=None, fset=None, fdel=None, doc=None)
fget − một phương thức thể hiện (instance method) dùng để lấy giá trị của một biến thể hiện (instance variable).
fset − một phương thức thể hiện gán giá trị cho một biến thể hiện.
fdel − một phương thức thể hiện (instance method) loại bỏ một biến thể hiện (instance variable)
fdoc − Chuỗi tài liệu cho thuộc tính.
Hàm này sử dụng các phương thức getter và setter để trả về đối tượng thuộc tính.
Một phương thức getter lấy giá trị của một biến thể hiện, thường được đặt tên là get_varname, trong khi phương thức setter gán giá trị cho một biến thể hiện - được đặt tên là set_varname.
Hãy định nghĩa các phương thức getter get_name() và get_age(), cùng với các phương thức setter set_name() và set_age() trong lớp Employee.
class Employee: def __init__(self, name, age): self.__name = name self.__age = age def get_name(self): return self.__name def get_age(self): return self.__age def set_name(self, name): self.__name = name return def set_age(self, age): self.__age=age e1=Employee("Bhavana", 24) print ("Name:", e1.get_name(), "age:", e1.get_age()) e1.set_name("Archana") e1.set_age(21) print ("Name:", e1.get_name(), "age:", e1.get_age())
Nó sẽ tạo ra output −
Name: Bhavana age: 24 Name: Archana age: 21
Các phương thức getter và setter có thể lấy hoặc gán giá trị cho các biến thể hiện. Hàm property() sử dụng chúng để thêm các đối tượng thuộc tính như là thuộc tính của lớp.
Thuộc tính name được định nghĩa như sau −
name = property(get_name, set_name, "name")
Tương tự, bạn có thể thêm thuộc tính age −
age = property(get_age, set_age, "age")
Lợi thế của đối tượng thuộc tính là bạn có thể sử dụng nó để lấy giá trị của biến thể hiện liên kết, cũng như gán giá trị.
Ví dụ,
print (e1.name) displays value of e1.__name e1.name = "Archana" assigns value to e1.__age
Chương trình hoàn chỉnh với các đối tượng thuộc tính và cách sử dụng của chúng được đưa ra dưới đây −
class Employee: def __init__(self, name, age): self.__name = name self.__age = age def get_name(self): return self.__name def get_age(self): return self.__age def set_name(self, name): self.__name = name return def set_age(self, age): self.__age=age return name = property(get_name, set_name, "name") age = property(get_age, set_age, "age") e1=Employee("Bhavana", 24) print ("Name:", e1.name, "age:", e1.age) e1.name = "Archana" e1.age = 23 print ("Name:", e1.name, "age:", e1.age)
Nó sẽ tạo ra output −
Name: Bhavana age: 24 Name: Archana age: 23