Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
YouTube Security VideosGoogle Cloud Tech: Gemini is coming to your city(24.09.2026 um 15:00 Uhr)
•
AI & KI NachrichtenGoogle’s latest moonshot to put machine learning in space(24.09.2026 um 15:12 Uhr)
•
Windows Tipps & SecurityPoll: What's your favorite Surface of 2026?(24.09.2026 um 14:58 Uhr)
•••
Sichere ProgrammierungStreaming Materialized Views for Live Read Models (2026)(24.09.2026 um 15:02 Uhr)
•
Sichere ProgrammierungA Day Is Not 86400 Seconds: The DST Bug in Your Date Math(24.09.2026 um 15:02 Uhr)
•
Sichere ProgrammierungSetting up Traefik: reverse proxy with automatic HTTPS(24.09.2026 um 15:02 Uhr)
•
Sichere ProgrammierungA 200 OK response does not prove a secret leak(24.09.2026 um 15:02 Uhr)
•
Sichere ProgrammierungHow hot do you like it?(24.09.2026 um 15:05 Uhr)
•
YouTube Security VideosGoogle Cloud Tech: Gemini is coming to your city(24.09.2026 um 15:00 Uhr)
•
AI & KI NachrichtenGoogle’s latest moonshot to put machine learning in space(24.09.2026 um 15:12 Uhr)
•
Windows Tipps & SecurityPoll: What's your favorite Surface of 2026?(24.09.2026 um 14:58 Uhr)
•••
Sichere ProgrammierungStreaming Materialized Views for Live Read Models (2026)(24.09.2026 um 15:02 Uhr)
•
Sichere ProgrammierungA Day Is Not 86400 Seconds: The DST Bug in Your Date Math(24.09.2026 um 15:02 Uhr)
•
Sichere ProgrammierungSetting up Traefik: reverse proxy with automatic HTTPS(24.09.2026 um 15:02 Uhr)
•
Sichere ProgrammierungA 200 OK response does not prove a secret leak(24.09.2026 um 15:02 Uhr)
•
Sichere ProgrammierungHow hot do you like it?(24.09.2026 um 15:05 Uhr)
•
Intelligence View
⚡ tsecurity.de Intelligence

Python's Descriptor Protocol, The Feature Behind Everything You Use Daily

You use descriptors every day. Every time you write @property, every time you call a method, every time you use @staticmethod or @classmethod, you are using the descriptor protocol. Most Python developers have no idea it exists as a…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

You use descriptors every day. Every time you write @property, every time you call a method, every time you use @staticmethod or @classmethod, you are using the descriptor protocol. Most Python developers have no idea it exists as a unified mechanism. Once you see it, you cannot unsee it.






What a Descriptor Is



A descriptor is any object that defines at least one of three methods: __get__, __set__, or __delete__. That is it. When an attribute lookup finds one of these objects sitting in a class's __dict__, Python hands control over to the descriptor instead of returning the object directly.



The minimal descriptor looks like this:




class MyDescriptor:
def __get__(self, obj, objtype=None):
print(f"__get__ called: obj={obj}, objtype={objtype}")
return 42

class MyClass:
attr = MyDescriptor()

instance = MyClass()
instance.attr # prints: __get__ called: obj=<MyClass ...>, objtype=<class 'MyClass'>
MyClass.attr # prints: __get__ called: obj=None, objtype=<class 'MyClass'>






When obj is None, the descriptor is being accessed from the class itself, not an instance. This distinction matters and you will use it constantly when writing real descriptors.






Data Descriptors vs Non-Data Descriptors



This split is the most important thing to understand about how descriptors interact with instance __dict__.



A data descriptor defines both __get__ and __set__ (or __delete__). It takes priority over the instance's own __dict__. You cannot shadow it by doing instance.attr = something because __set__ intercepts the assignment.



A non-data descriptor defines only __get__. The instance's __dict__ takes priority over it. If you assign to instance.attr, Python just stores the value in the instance dictionary and the descriptor is no longer called for that instance.



The lookup order for instance.attr is:




  1. Data descriptors from the class (and its MRO)

  2. Instance __dict__

  3. Non-data descriptors and other class attributes



This ordering is not arbitrary. It is what makes @property work correctly. A property is a data descriptor because it defines __set__ (even if you only define a getter, the setter raises AttributeError), so it cannot be overridden by instance assignment. Functions, on the other hand, are non-data descriptors, which is why you can shadow a method by assigning to an instance attribute of the same name.






How Functions Become Methods



This is the part that clicks everything together. In Python, a plain function is a non-data descriptor. It only defines __get__. When you access a function through an instance, __get__ is called, and it returns a bound method object that already has the instance baked in as the first argument.




def greet(self):
return f"Hello from {self}"

class Person:
greet = greet

p = Person()

# These are equivalent
p.greet()
Person.greet(p)

# What actually happens
bound_method = Person.__dict__['greet'].__get__(p, Person)
bound_method()






function.__get__(instance, owner) returns a MethodType object that wraps the function and the instance together. There is no magic beyond this. The entire method binding mechanism in Python is the descriptor protocol applied to plain functions.



You can verify this:




print(type(greet))           # <class 'function'>
print(greet.__get__) # <method-wrapper '__get__' of function object at ...>
print(type(p.greet)) # <class 'method'>









Writing a Real Descriptor: Typed Attributes



Here is where descriptors become practically useful. Suppose you want class attributes that enforce a type at assignment time without cluttering __init__ with validation logic.




class Typed:
def __set_name__(self, owner, name):
self.name = name
self.private_name = f"_{name}"

def __get__(self, obj, objtype=None):
if obj is None:
return self
return getattr(obj, self.private_name, None)

def __set__(self, obj, value):
if not isinstance(value, self.expected_type):
raise TypeError(
f"{self.name} must be {self.expected_type.__name__}, "
f"got {type(value).__name__}"
)
setattr(obj, self.private_name, value)

class Integer(Typed):
expected_type = int

class String(Typed):
expected_type = str

class Person:
name = String()
age = Integer()

def __init__(self, name, age):
self.name = name
self.age = age

p = Person("Alice", 30) # works
p.age = "thirty" # raises TypeError: age must be int, got str






Notice __set_name__. This is a hook Python calls automatically when the class is created, passing the descriptor the owner class and the attribute name it was assigned to. Without it, the descriptor would not know its own name and you would have to pass it manually. It was added in Python 3.6 and makes descriptors significantly cleaner to write.






classmethod and staticmethod Are Just Descriptors



Once you understand the protocol, classmethod and staticmethod stop being mysterious decorators and become straightforward descriptor implementations.



staticmethod wraps a function and its __get__ simply returns the function unchanged, with no binding:




class StaticMethod:
def __init__(self, f):
self.f = f

def __get__(self, obj, objtype=None):
return self.f # no binding, just return the raw function






classmethod wraps a function and its __get__ binds the class instead of the instance:




class ClassMethod:
def __init__(self, f):
self.f = f

def __get__(self, obj, objtype=None):
if objtype is None:
objtype = type(obj)
return self.f.__get__(objtype) # bind the class, not the instance






These are simplified but functionally accurate. The actual CPython implementations are in C for performance, but the logic is identical. You could replace @classmethod with your own descriptor and everything would work the same way.






The Caching Descriptor Pattern



One underused pattern is using descriptors to compute expensive values once and then cache them on the instance, bypassing the descriptor entirely on subsequent access.




class cached_property:
def __init__(self, func):
self.func = func
self.attrname = None

def __set_name__(self, owner, name):
self.attrname = name

def __get__(self, obj, objtype=None):
if obj is None:
return self
val = self.func(obj)
obj.__dict__[self.attrname] = val # store directly on instance
return val






This works because cached_property is a non-data descriptor (it only defines __get__). On first access, it calls the function and stores the result in the instance __dict__ under the same name. On second access, the instance __dict__ lookup wins and the descriptor is never called again.



Python ships functools.cached_property since 3.8 using exactly this technique. It is elegant because the caching mechanism falls directly out of the descriptor lookup order rather than requiring any explicit flag or sentinel.






When to Actually Use This



Descriptors are the right tool in specific situations. If you find yourself writing the same property logic across multiple attributes or classes (validation, unit conversion, access logging), a descriptor lets you define that logic once and attach it declaratively.



ORMs lean on this heavily. Django's Field classes and SQLAlchemy's Column objects are descriptors. When you write user.name, the ORM intercepts it through __get__ and can return a SQL expression rather than a plain value, depending on context.



Frameworks that do attribute access tracking for reactive programming (like Traitlets in Jupyter or any observable pattern) use descriptors to intercept reads and writes and fire callbacks.



If you are not building framework-level infrastructure, plain properties cover most cases. But understanding descriptors tells you exactly what @property is doing and why it behaves the way it does, which makes the edge cases much easier to reason about.






Further Reading



SOC Incident Playbook: Remote Code Execution (RCE) Defense
title: Detect Exploitation - Python's Descriptor Protocol, The Feature Behind Everything You Use Daily
id: 8704219a-ae51-4b5e-bf40-712d7816eecb
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-24
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-24"
        description = "YARA Signature for "
    strings:
        $str = "Python\'s Descriptor Protocol, " ascii wide
    condition:
        any of them
}
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich Python&#039;s Descriptor Protocol, The Featur.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Python's Descriptor Protocol, The Feature Behind Everything You Use Daily

Thematisch verwandte Begriffe: Pythons, Descriptor, Protocol, Feature · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-97152 | Nanomsg versions 0.5-beta through 1.x before 1.2.3 has a remotely exploi…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel • Rechts: nächster Artikel • unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel TTP ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger • Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick