In the context of the Descriptor Protocol, what is the primary difference between a data descriptor and a non-data descriptor?
Trap 1: Non-data descriptors can override instance dictionary lookup.
Non-data descriptors implement only __get__, so instance __dict__ entries take precedence over them during attribute lookup. It is tempting because non-data descriptors do participate in lookup, but data descriptors define __set__ or __delete__ and therefore override instance dictionary entries, which is the actual distinction.
Trap 2: Data descriptors only function with class attributes.
Data descriptors are defined by implementing __set__ or __delete__ alongside __get__, so they take precedence over instance dictionaries; the class-attribute placement is irrelevant since both descriptor types normally live on the class. It tempts because descriptors are usually declared as class attributes, but that describes implementation location, not the data versus non-data distinction.
Trap 3: Non-data descriptors are always read-only.
Non-data descriptors implement only __get__, yet they remain writable because instance __dict__ entries shadow them, so read-only behaviour is not guaranteed. It tempts because __get__-only descriptors often expose computed values, but the actual axis is presence of __set__ or __delete__, which data descriptors add to override instance attributes.
- A
Non-data descriptors can override instance dictionary lookup.
Why it fails: Non-data descriptors implement only __get__, so instance __dict__ entries take precedence over them during attribute lookup. It is tempting because non-data descriptors do participate in lookup, but data descriptors define __set__ or __delete__ and therefore override instance dictionary entries, which is the actual distinction.
- B
Data descriptors define __set__ or __delete__, whereas non-data descriptors do not.
Data descriptors implement __set__ or __delete__, giving them control over attribute assignment and deletion. Non-data descriptors define only __get__, so instance dictionaries take precedence over them during attribute lookup, which is the defining behavioural difference.
- C
Data descriptors only function with class attributes.
Why it fails: Data descriptors are defined by implementing __set__ or __delete__ alongside __get__, so they take precedence over instance dictionaries; the class-attribute placement is irrelevant since both descriptor types normally live on the class. It tempts because descriptors are usually declared as class attributes, but that describes implementation location, not the data versus non-data distinction.
- D
Non-data descriptors are always read-only.
Why it fails: Non-data descriptors implement only __get__, yet they remain writable because instance __dict__ entries shadow them, so read-only behaviour is not guaranteed. It tempts because __get__-only descriptors often expose computed values, but the actual axis is presence of __set__ or __delete__, which data descriptors add to override instance attributes.