Atribut privat
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Python di Coddy. Pelajaran 15 dari 64.
Atribut privat menggunakan garis bawah untuk menunjukkan bahwa data tertentu tidak boleh diakses langsung dari luar class.
Mengapa kita membutuhkan atribut privat? Bayangkan kamu memiliki rekening bank. Kamu tidak ingin siapa pun mengubah saldomu secara langsung, mereka harus melalui jalur yang tepat (method deposit/withdraw) agar bank dapat memvalidasi transaksi, memeriksa penipuan, menyimpan catatan, dan sebagainya. Atribut privat bekerja dengan cara yang sama, atribut ini melindungi datamu agar tidak diubah secara keliru.
Berikut contoh yang menggunakan satu garis bawah (konvensi untuk "penggunaan internal"):
class Person:
def __init__(self, name, age):
self._name = name # "protected" untuk penggunaan internal
self._age = age # "protected" untuk penggunaan internalAtribut dengan satu garis bawah masih bisa diakses, tetapi ini merupakan tanda bahwa sebaiknya kamu tidak mengaksesnya:
person = Person("Alice", 30)
print(person._name) # Bisa digunakan, tetapi tidak disarankanGunakan garis bawah ganda untuk privasi yang lebih kuat (pengubahan nama):
class Person:
def __init__(self, name, age):
self.__name = name # "private", namanya diubah oleh Python
self.__age = age # "private", namanya diubah oleh Python
def get_name(self):
return self.__name
def set_age(self, age):
if age >= 0:
self.__age = age
else:
print("Age must be positive!")Mengapa menggunakan method getter dan setter? Keduanya seperti penjaga gerbang. Daripada membiarkan siapa pun mengubah __age secara langsung, yang bisa menghasilkan usia negatif atau data lain yang tidak valid, kita mewajibkan mereka menggunakan set_age() yang memvalidasi input terlebih dahulu. Ini mencegah bug dan memastikan integritas data.
"Kode tambahan" ini memiliki tujuan:
get_name()- Akses terkontrol untuk membaca namaset_age(age)- Memvalidasi usia sebelum mengizinkan perubahan (tidak boleh ada usia negatif!)- Tanpa method ini, seseorang dapat menetapkan
age = -100dan merusak programmu
Gunakan method accessor untuk berinteraksi dengan atribut privat:
person = Person("Bob", 25)
print(person.get_name()) # Bob
person.set_age(30) # Valid: age menjadi 30
person.set_age(-5) # Tidak valid: Age harus positif! (age tetap 30)Lihat manfaatnya? Method set_age() mencegah data yang tidak valid. Tanpanya, kamu bisa saja membuat seseorang dengan usia -5, yang tidak masuk akal!
Atribut dengan garis bawah ganda mengalami "name mangling", tetapi tetap dapat diakses:
person = Person("Charlie", 35)
# Ini tidak berhasil:
# print(person.__name) # AttributeError
# Tapi ini berhasil (tidak disarankan):
print(person._Person__name) # CharlieContoh di dunia nyata: Mengapa perlu semua kode ini?
class BankAccount:
def __init__(self, balance):
self.__balance = balance # Privat: tidak bisa diubah secara langsung
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return True
return False
def get_balance(self):
return self.__balance
# Tanpa atribut privat:
# account.__balance = -1000000 # Bencana! Saldo negatif diperbolehkan
# Dengan atribut privat:
account = BankAccount(100)
account.deposit(50) # Aman: sudah divalidasi
print(account.get_balance()) # 150"Kode tambahan" (method) melindungi datamu dari perubahan yang tidak valid. Ini seperti memiliki penjaga keamanan, alih-alih membiarkan barang berhargamu tanpa perlindungan.
Output:
Alice
Bob
Age must be positive!
Charlie
150Satu garis bawah _attribute berarti "hanya untuk penggunaan internal" berdasarkan konvensi. Garis bawah ganda __attribute memicu name mangling untuk privasi yang lebih kuat. Gunakan method getter/setter (method accessor) untuk berinteraksi dengan data privat dengan benar dan menambahkan validasi. "Kode tambahan" mencegah bug dengan memastikan data selalu valid.
Tantangan
MudahLengkapi class User di user.py dengan fungsionalitas kata sandi privat, lalu gunakan class tersebut di driver.py. Ikuti komentar TODO untuk menerapkan method pemeriksaan dan penggantian kata sandi.
Coba sendiri
# TODO: Impor class User dari module user
# TODO: Ambil kasus uji dari input
test_case = input()
if test_case == "constructor_test":
# TODO: Buat object User dengan kata sandi awal "secure123"
user = User("secure123")
print("User created successfully")
print("Initial password set")
elif test_case == "correct_password_test":
# TODO: Buat object User dengan kata sandi awal "secure123"
user = User("secure123")
# TODO: Uji method check_password dengan kata sandi yang benar
# Cetak "Password check successful!" jika hasilnya True
# Cetak "Password check failed!" jika hasilnya False
result = user.check_password("secure123")
if result:
print("Password check successful!")
else:
print("Password check failed!")
elif test_case == "incorrect_password_test":
# TODO: Buat object User dengan kata sandi awal "secure123"
user = User("secure123")
# TODO: Uji method check_password dengan kata sandi yang salah "wrong"
# Cetak "Incorrect password rejected!" jika hasilnya False
# Cetak "Security issue: incorrect password accepted!" jika hasilnya True
result = user.check_password("wrong")
if not result:
print("Incorrect password rejected!")
else:
print("Security issue: incorrect password accepted!")
elif test_case == "change_password_test":
# TODO: Buat object User dengan kata sandi awal "secure123"
user = User("secure123")
# TODO: Uji perubahan kata sandi dari "secure123" menjadi "newpass456"
# Cetak "Password changed successfully!" jika hasilnya True
# Cetak "Password change failed!" jika hasilnya False
result = user.change_password("secure123", "newpass456")
if result:
print("Password changed successfully!")
else:
print("Password change failed!")
# TODO: Pastikan kata sandi baru berfungsi dengan memeriksa "newpass456"
# Cetak "New password works!" jika hasilnya True
# Cetak "New password doesn't work!" jika hasilnya False
if user.check_password("newpass456"):
print("New password works!")
else:
print("New password doesn't work!")
elif test_case == "change_password_wrong_old_test":
# TODO: Buat object User dengan kata sandi awal "secure123"
user = User("secure123")
# TODO: Coba ubah kata sandi dengan kata sandi lama yang salah
# Cetak "Security working: incorrect old password rejected!" jika hasilnya False
# Cetak "Security issue: password changed with wrong old password!" jika hasilnya True
result = user.change_password("wrong", "hackerpw")
if not result:
print("Security working: incorrect old password rejected!")
else:
print("Security issue: password changed with wrong old password!")
elif test_case == "comprehensive_test":
# TODO: Buat object User dengan kata sandi awal "secure123"
user = User("secure123")
print("User created with initial password")
# TODO: Uji method check_password dengan kata sandi yang benar
if user.check_password("secure123"):
print("Initial password verification successful")
# TODO: Uji method check_password dengan kata sandi yang salah
if not user.check_password("wrongpass"):
print("Incorrect password properly rejected")
# TODO: Uji perubahan kata sandi dari "secure123" menjadi "newpass456"
if user.change_password("secure123", "newpass456"):
print("Password successfully changed")
# TODO: Pastikan kata sandi lama tidak lagi berfungsi
if not user.check_password("secure123"):
print("Old password no longer works")
# TODO: Pastikan kata sandi baru berfungsi
if user.check_password("newpass456"):
print("New password works correctly")
# TODO: Coba ubah kata sandi dengan kata sandi lama yang salah
if not user.change_password("wrongold", "hackerpw"):
print("Security maintained: wrong old password rejected")
# TODO: Pastikan kata sandi tetap aman setelah percobaan perubahan gagal
if user.check_password("newpass456"):
print("Password remains secure after failed change attempt")
else:
print("Unknown test case")Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP
File EksternalPengantar OOPclass vs objectParameter selfmethodAtributMethod Konstruktor (__init__)Rangkuman: Kalkulator Sederhana4Pewarisan
Pewarisan DasarFungsi super()Penimpaan MethodPewarisan BergandaUrutan Resolusi MethodRingkasan: Hierarki Karyawan5Polimorfisme
Meninjau Ulang Method OverridingDuck Typingclass dan method AbstrakDesain InterfaceRingkasan: Kalkulator Bentuk8Konsep OOP Lanjutan
Komposisi vs PewarisanMixinsMetode Statis dan Metode ClassDecorator ClassPengelola Konteks11Pola Desain Bagian 2
Pola PerintahPola AdapterPola DecoratorPola Template MethodPola StatePola Composite3Property class
Variabel instance vs variabel classDekorator propertyAtribut privatRangkuman: Pengelola Rekening Bank6Enkapsulasi
Anggota Public, Protected, PrivateModifier AksesPenyembunyian InformasiDecorator Property Tingkat LanjutUlasan: Sistem Catatan Siswa12Proyek: Manajemen Perpustakaan
Ikhtisar Proyekclass Buku dan PenggunaSistem PeminjamanFitur PencarianAntarmuka AdminPengujian dan IntegrasiLatihan sendiri: Compiler Python online