Non-data descriptor
- Python course
- Expert
- Lesson 9/47
- 5 min
Learn non-data descriptors with only __get__.
What is a non-data descriptor?
A non-data descriptor implements only __get__; there is no __set__. It intercepts reads but not writes.
This has an important consequence: a same-named entry in the instance dict (obj.__dict__) overrides a non-data descriptor. So writing box.label = "new" puts the value in the instance dict and subsequent reads return that value, not the descriptor. classmethod and staticmethod are non-data descriptors. This flexibility is ideal for simple computations that allow overriding.
Priority order
Python follows this priority for attribute access: first data descriptors, then the instance dict (obj.__dict__), then non-data descriptors, finally the class dict.
This explains why property (a data descriptor) overrides an instance value but classmethod (a non-data descriptor) can be overridden. A data descriptor always wins because it implements __set__ and writes go through it. A non-data descriptor only kicks in at read time and steps aside if the instance dict has a value.
Practice Computation with a non-data descriptor
Write a Squared non-data descriptor. Store self.base with __init__(self, base). __get__(self, obj, objtype=None) returns self.base ** 2. In a Math class define area = Squared(5). Create an instance and print area.
Starter code
# Write the Squared descriptor
# use it in the Math class
# print the resultSample solution
# Write the Squared descriptor
class Squared:
def __init__(self, base):
self.base = base
def __get__(self, obj, objtype=None):
return self.base ** 2
class Math:
area = Squared(5)
m = Math()
print(m.area)Expected output
25
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Complete the non-data descriptor definition
class Squared:
def ______(self, obj, objtype=None):
return self.base ** 2
class Squared:
def __get(self, obj, objtype=None):
return self.base ** 2
Explanation: A non-data descriptor implements only __get__.
2 Match non-data descriptor concepts
| Term | Meaning |
|---|---|
__get__ |
Intercepts read |
no __set__ |
Write is free |
instance dict |
Overrides descriptor |
classmethod |
Non-data example |
3 When is a non-data descriptor overridden?
class Desc:
def __get__(self, o, t=None):
return "a"
class C:
x = Desc()
c = C()
c.x = "b"
print(c.x)- Never overridden
- When a value is written to the instance dict Correct answer
- On class access
- Only when __set__ is defined
Explanation: c.x = "b" goes to the instance dict; the non-data descriptor steps aside.