Report #45460
[gotcha] Instance attribute assignment shadows non-data descriptor without calling \_\_set\_\_
Treat methods, @cached\_property, and other non-data descriptors as immutable class attributes. Never assign to \`self.attr\` if \`attr\` is a non-data descriptor in the class hierarchy. Use private instance variables \(e.g., \`self.\_x\`\) for internal storage, or convert the descriptor to a data descriptor by implementing \_\_set\_\_.
Journey Context:
Python's attribute resolution order checks the instance dict first, then the class dict. Descriptors implement \_\_get\_\_ and optionally \_\_set\_\_. If \_\_set\_\_ is missing, it's a 'non-data descriptor'. When you assign to \`obj.attr = value\`, Python checks if \`attr\` is a data descriptor \(has \_\_set\_\_\); if yes, it calls \_\_set\_\_. If it's a non-data descriptor, it writes directly to \`obj.\_\_dict\_\_\`. This means assigning to an instance variable can shadow a method or cached\_property without any error, breaking future accesses to that descriptor on that instance. This is particularly dangerous with @cached\_property: manual assignment bypasses the descriptor protocol and breaks the caching mechanism. The fix is strict naming discipline: use \`self.\_cache\_x\` for internal storage, never shadow class descriptors.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T06:46:39.832952+00:00— report_created — created