Thành viên public, protected, private
Thuộc phần Lập trình hướng đối tượng trong hành trình Python của Coddy. Bài học 28 trên 64.
Python có ba mức kiểm soát quyền truy cập đối với các thành viên của lớp: công khai, được bảo vệ và riêng tư. Các mức này kiểm soát cách truy cập thuộc tính và phương thức.
Đây là ví dụ về một lớp có cả ba mức truy cập:
class BankAccount:
def __init__(self, owner, balance, account_id):
self.owner = owner # Công khai: có thể truy cập từ mọi nơi
self._balance = balance # Được bảo vệ: dùng trong nội bộ
self.__account_id = account_id # Riêng tư: chỉ dùng trong lớp
def deposit(self, amount): # Phương thức (method) công khai
self._balance += amount
def _calculate_interest(self): # Phương thức được bảo vệ
return self._balance * 0.02
def __validate_transaction(self, amount): # Phương thức riêng tư
return amount > 0 and amount <= self._balanceTruy cập các thành viên công khai từ bất kỳ đâu:
account = BankAccount("Alice", 1000, "12345")
print(account.owner) # Alice
account.deposit(500) # Hoạt động bình thườngTruy cập các thành viên được bảo vệ (một dấu gạch dưới, chỉ là quy ước):
print(account._balance) # 1500, chạy được nhưng không nên dùng
result = account._calculate_interest() # Chạy được nhưng không nên dùng
print(result) # 30.0Thử truy cập các thành viên riêng tư (hai dấu gạch dưới, biến đổi tên):
# Cách này không chạy:
# print(account.__account_id) # AttributeError
# Nhưng cách này chạy được (biến đổi tên):
print(account._BankAccount__account_id) # 12345Tạo một lớp con để minh họa sự khác nhau giữa quyền truy cập protected và private:
class SavingsAccount(BankAccount):
def show_balance(self):
return self._balance # Được bảo vệ, có thể truy cập trong lớp con
def show_id(self):
# return self.__account_id # Cách này không hoạt động vì đây là thuộc tính riêng tư
return "Cannot access private member"savings = SavingsAccount("Bob", 2000, "67890")
print(savings.show_balance()) # 2000
print(savings.show_id()) # Không thể truy cập thành viên riêng tưĐầu ra:
Alice
30.0
12345
2000
Cannot access private memberĐiểm chính: Các thành viên công khai không có tiền tố và có thể được truy cập ở bất kỳ đâu. Các thành viên được bảo vệ dùng một dấu gạch dưới (_) và chỉ nên được dùng trong hệ thống phân cấp lớp. Các thành viên riêng tư dùng hai dấu gạch dưới (__), tên của chúng được biến đổi để tăng cường tính riêng tư. Quyền truy cập trong Python dựa trên quy ước, không được thực thi nghiêm ngặt.
Thử thách
Trung bìnhTrong thử thách này, bạn sẽ triển khai lớp BankAccount để minh họa cách sử dụng đúng các mức truy cập công khai, được bảo vệ và riêng tư trong Python.
bankaccount.py- Chứa định nghĩa lớp với các chú thích TODO hướng dẫn bạn triển khai
- Làm theo các chú thích TODO trong
bankaccount.pyđể triển khai chức năng cần thiết - Triển khai đúng các mức truy cập (công khai, được bảo vệ, riêng tư) theo yêu cầu
- Đảm bảo mọi phương thức xử lý các trường hợp ngoại lệ phù hợp (tiền gửi âm, v.v.)
Tự làm thử
from bank_account import BankAccount
# Xử lý toàn diện các test case
test_case = input()
if test_case == "basic_test":
# Kiểm tra chức năng cơ bản
account = BankAccount("John Doe", "12345")
print(account.account_holder) # Thuộc tính (attribute) công khai
print(account.deposit(100)) # Phương thức (method) công khai
print(account.get_balance()) # Phương thức (method) công khai
elif test_case == "transaction_count":
# Kiểm tra thuộc tính được bảo vệ
account = BankAccount("Jane Smith", "67890")
account.deposit(50)
account.deposit(100)
account.deposit(200)
print(account._transaction_count) # Thuộc tính được bảo vệ
print(account.get_balance())
elif test_case == "invalid_deposit":
# Kiểm tra việc xác thực trong phương thức deposit
account = BankAccount("Bob Johnson", "54321")
print(account.deposit(-50)) # Trả về None
print(account.deposit(0)) # Trả về None
print(account.deposit(75)) # Trả về 75
print(account.get_balance())
elif test_case == "private_access":
# Kiểm tra quyền truy cập thuộc tính riêng tư
account = BankAccount("Alice Brown", "98765")
try:
print(account.__balance) # Thao tác này sẽ gây ra AttributeError
except AttributeError:
pass
try:
print(account.__account_number) # Thao tác này sẽ gây ra AttributeError
except AttributeError:
pass
print("Private attributes are not directly accessible")
account.deposit(500)
print(account.get_balance()) # Truy cập qua phương thức công khai
elif test_case == "name_mangling":
# Minh họa cách biến đổi tên của các thuộc tính (attributes) riêng tư
account = BankAccount("Charlie Green", "13579")
print(account._BankAccount__balance) # Truy cập thuộc tính riêng tư qua tên đã biến đổi
print(account._BankAccount__account_number) # Truy cập thuộc tính riêng tư qua tên đã biến đổi
account.deposit(300)
print(account._BankAccount__balance) # Sẽ hiển thị số dư đã cập nhật
elif test_case == "multiple_accounts":
# Kiểm tra nhiều tài khoản
account1 = BankAccount("David White", "24680")
account2 = BankAccount("Eva Black", "86420")
account3 = BankAccount("Frank Red", "97531")
account1.deposit(150)
account2.deposit(250)
account2.deposit(50)
account3.deposit(500)
account3.deposit(300)
account3.deposit(200)
print(f"{account1.account_holder}: {account1.get_balance()}")
print(f"{account2.account_holder}: {account2.get_balance()}")
print(f"{account3.account_holder}: {account3.get_balance()}")
print(f"Account 1 transactions: {account1._transaction_count}")
print(f"Account 2 transactions: {account2._transaction_count}")
print(f"Account 3 transactions: {account3._transaction_count}")
elif test_case == "stress_test":
# Kiểm tra hiệu năng với nhiều giao dịch
account = BankAccount("Stress Tester", "11111")
for _ in range(1000):
account.deposit(1)
print(f"Final balance: {account.get_balance()}")
print(f"Transaction count: {account._transaction_count}")
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTham số selfPhương thứcThuộc tínhPhương thức khởi tạo (__init__)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnHàm super()Ghi đè phương thứcKế thừa đa lớpThứ tự phân giải phương thứcÔn tập: hệ thống phân cấp nhân viên2Decorator
Giới thiệu về decoratorDecorator thuộc tínhDecorator phương thức tĩnhDecorator phương thức lớp5Tính đa hình
Xem lại cách ghi đè phương thứcKiểu gõ vịtLớp và phương thức trừu tượngThiết kế giao diệnÔn tập: máy tính hình học8Các khái niệm OOP nâng cao
Kết hợp và kế thừaMixinPhương thức tĩnh và phương thức lớpDecorator lớpTrình quản lý ngữ cảnh3Thuộc tính của lớp
Biến của instance và biến của lớpDecorator thuộc tínhThuộc tính riêng tưÔn tập: trình quản lý tài khoản ngân hàng6Đóng gói
Thành viên public, protected, privateBộ điều chỉnh quyền truy cậpẨn thông tinDecorator thuộc tính nâng caoÔn tập: Hệ thống hồ sơ học sinhTự luyện tập: Trình biên dịch Python online