0Pricing
Python Academy · Pelajaran

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 ... 42

Deskriptor 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)   # data

Signatur __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   # AttributeError

Fungsi 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 function

Deskriptor 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__ = fset

Urutan 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 AttributeError

Pemeriksaan 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

  1. Cara Class Python Dibuat
  2. Menulis Metaclass Kustom
  3. Descriptor: __get__, __set__, __delete__
  4. __slots__ dan Optimasi Memori
← Kembali ke Python Academy