Descriptor: __get__, __set__, __delete__
Implementasikan protokol descriptor untuk mengendalikan akses atribut.
Descriptor: __get__, __set__, __delete__ adalah pelajaran Python Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Python Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Python Academy mencakup 4 pelajaran total.
Apa Itu Deskriptor?
Deskriptor adalah objek yang mendefinisikan __get__, __set__, atau __delete__ dan ditetapkan sebagai atribut kelas. Python memanggil metode-metode ini saat atribut diakses.
class Descriptor:
def __get__(self, obj, objtype=None):
print(f"__get__ called, obj={obj}")
return 42
class MyClass:
attr = Descriptor()
print(MyClass().attr) # __get__ called ... 42Deskriptor Data vs Deskriptor Non-Data
Deskriptor data mendefinisikan __set__ atau __delete__ dan memiliki prioritas atas __dict__ instans. Deskriptor non-data yang hanya memiliki __get__ berada di bawah __dict__.
class DataDesc:
def __get__(self, obj, t): return "data"
def __set__(self, obj, val): pass
class NonDataDesc:
def __get__(self, obj, t): return "nondata"
class C:
d = DataDesc()
n = NonDataDesc()
c = C()
c.__dict__["n"] = "instance" # shadows the non-data desc
c.__dict__["d"] = "instance" # does NOT shadow data desc
print(c.n) # instance
print(c.d) # dataSignatur __get__
__get__(self, obj, objtype): obj adalah instans, atau None saat diakses pada kelas; objtype adalah kelas.
class Verbose:
def __get__(self, obj, objtype=None):
if obj is None:
return self # accessed on class
return f"value for {obj!r}"
class Widget:
label = Verbose()
print(Widget.label) # <Verbose object>
print(Widget().label) # value for <Widget object>__set__ dan Validasi
Implementasikan __set__(self, obj, value) untuk memvalidasi atau mengubah nilai sebelum menyimpannya.
class PositiveInt:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, obj, t):
return obj.__dict__.get(self.name)
def __set__(self, obj, val):
if not isinstance(val, int) or val <= 0:
raise ValueError(f"{self.name} must be a positive int")
obj.__dict__[self.name] = val
class Rect:
width = PositiveInt()
height = PositiveInt()
r = Rect()
r.width = 10
# r.width = -1 # ValueError__set_name__
Python 3.6+ memanggil __set_name__(owner, name) pada deskriptor saat deskriptor tersebut ditetapkan ke sebuah kelas, sehingga deskriptor dapat mengakses nama atributnya sendiri.
class Typed:
def __set_name__(self, owner, name):
self.public = name
self.private = "_" + name
def __get__(self, obj, t):
return None if obj is None else getattr(obj, self.private, None)
def __set__(self, obj, val):
setattr(obj, self.private, val)
class User:
name = Typed()
u = User()
u.name = "Alice"
print(u.name) # Alice__delete__ untuk Penghapusan Atribut
Definisikan __delete__(self, obj) untuk mencegat del obj.attr.
class Protected:
def __set_name__(self, owner, name): self.name = name
def __get__(self, obj, t):
return obj.__dict__.get(self.name)
def __set__(self, obj, v): obj.__dict__[self.name] = v
def __delete__(self, obj):
raise AttributeError(f"Cannot delete {self.name}")
class Config:
host = Protected()
c = Config(); c.host = "localhost"
# del c.host # AttributeErrorFungsi adalah Deskriptor Non-Data
Fungsi mengimplementasikan __get__ untuk mengembalikan metode terikat saat diakses pada instans. Inilah cara kerja pengikatan metode Python.
def greet(self):
return f"Hello from {self}"
class C: pass
C.greet = greet
c = C()
print(c.greet()) # Hello from <C object>classmethod dan staticmethod adalah Deskriptor
classmethod dan staticmethod adalah kelas deskriptor bawaan yang membungkus fungsi dan mengubah nilai yang dikembalikan oleh __get__.
class MyClass:
@classmethod
def from_string(cls, s):
return cls()
# classmethod.__get__ returns a bound method with cls
# staticmethod.__get__ returns the plain functionDeskriptor Atribut Evaluasi Tertunda
Buat deskriptor yang menghitung nilai satu kali dan menyimpannya dalam cache untuk setiap instans.
class LazyAttr:
def __init__(self, func): self.func = func
def __set_name__(self, owner, name): self.name = name
def __get__(self, obj, t):
if obj is None: return self
val = self.func(obj)
obj.__dict__[self.name] = val # shadows descriptor
return val
class Report:
@LazyAttr
def summary(self):
print("computing...")
return "done"
r = Report()
print(r.summary) # computing... done
print(r.summary) # done (cached)property adalah Deskriptor
property sendiri adalah deskriptor data yang diimplementasikan dalam C. Memahami deskriptor membantu Anda memahami cara kerja @property, @classmethod, dan @staticmethod.
class Circle:
def __init__(self, r): self._r = r
@property
def radius(self): return self._r
@radius.setter
def radius(self, v):
if v < 0: raise ValueError
self._r = v
# property is: property.__get__ = fget, property.__set__ = fsetUrutan Pencarian Deskriptor
Urutan pencarian atribut Python: 1) deskriptor data dari tipe (MRO), 2) __dict__ instans, 3) deskriptor tanpa data dan variabel kelas.
# Pseudocode for obj.attr:
# 1. Check type(obj).__mro__ for a data descriptor
# 2. Check obj.__dict__
# 3. Check type(obj).__mro__ for non-data descriptor or class var
# 4. Raise AttributeErrorPemeriksaan Singkat
Jenis deskriptor apa yang memiliki prioritas lebih tinggi daripada __dict__ instans?
Ringkasan
Deskriptor mencegat akses atribut melalui __get__, __set__, dan __delete__. Deskriptor data menutupi __dict__ instans, sedangkan deskriptor tanpa data tidak. Gunakan __set_name__ untuk mengetahui nama atribut. property, classmethod, dan staticmethod semuanya merupakan deskriptor.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Descriptor: __get__, __set__, __delete__” gratis?
Ya — teks lengkap “Descriptor: __get__, __set__, __delete__” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Python Academy, upgrade ke CoddyKit PRO. Kursus Python Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Descriptor: __get__, __set__, __delete__”?
Implementasikan protokol descriptor untuk mengendalikan akses atribut. Kamu berlatih Python Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Python Academy?
Tidak diperlukan pengalaman sebelumnya. Python Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Descriptor: __get__, __set__, __delete__” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Python Academy ini?
Ya. Setiap pelajaran Python Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Cara Class Python Dibuat
- Menulis Metaclass Kustom
- Descriptor: __get__, __set__, __delete__
- __slots__ dan Optimasi Memori