aosabook/500lines · error · AttributeError
fieldname
Error message
fieldname
What it means
Raised by Base.read_attr in the 03-customizable objmodel. The full lookup order is: instance dict -> class MRO (bindable callables become bound methods) -> a class-level __getattr__. AttributeError(fieldname) is reached only if none resolve the field, meaning the instance lacks the field, the class MRO lacks the attribute/method, AND no __getattr__ is defined on the class (or it re-raised).
Source
Thrown at objmodel/code/03-customizable/objmodel.py:25
""" Every object has a class. """
self.cls = cls
self._fields = fields
def read_attr(self, fieldname):
""" read field 'fieldname' out of the object """
result = self._read_dict(fieldname)
if result is not MISSING:
return result
result = self.cls._read_from_class(fieldname)
if _is_bindable(result):
return _make_boundmethod(result, self)
if result is not MISSING:
return result
meth = self.cls._read_from_class("__getattr__")
if meth is not MISSING:
return meth(self, fieldname)
raise AttributeError(fieldname)
def write_attr(self, fieldname, value):
""" write field 'fieldname' into the object """
meth = self.cls._read_from_class("__setattr__")
return meth(self, fieldname, value)
def isinstance(self, cls):
""" return True if the object is an instance of class cls """
return self.cls.issubclass(cls)
def callmethod(self, methname, *args):
""" call method 'methname' with arguments 'args' on object """
meth = self.read_attr(methname)
return meth(*args)
def _read_dict(self, fieldname):
""" read an field 'fieldname' out of the object's dict """
return self._fields.get(fieldname, MISSING)View on GitHub (pinned to fba689d101)
Solutions
- Define a __getattr__ method on the Class to supply a default or computed value for the missing field.
- Store the field with write_attr or declare it in the Class fields.
- Verify the fieldname and that the MRO includes the expected base classes.
Example fix
// before
obj.read_attr('missing') # AttributeError: missing
// after
# add a class-level __getattr__
MyClass = Class('MyClass', OBJECT, {
'__getattr__': lambda self, name: 'default',
}, TYPE) Defensive patterns
Strategy: fallback
Validate before calling
MISSING = object()
def safe_read(obj, fieldname, default=None):
if obj._read_dict(fieldname) is not MISSING:
return obj._read_dict(fieldname)
if obj.cls._read_from_class(fieldname) is not MISSING:
return obj.cls._read_from_class(fieldname)
return default Type guard
def has_field_or_getattr(obj, name):
MISSING = object()
return (obj._fields.get(name, MISSING) is not MISSING
or obj.cls._read_from_class(name) is not MISSING
or obj.cls._read_from_class('__getattr__') is not MISSING) Try / catch
try:
val = obj.read_attr(fieldname)
except AttributeError:
val = <default> Prevention
- Define a class-level __getattr__ to return a default for unknown names.
- Validate field existence via _read_dict / _read_from_class before read_attr.
- Keep field-name constants to avoid typos.
When it happens
Trigger: Reading an attribute that is absent from the instance dict, absent from the class and base classes, and the class defines no __getattr__ to cover it (or its __getattr__ raises AttributeError itself).
Common situations: Implementing __getattr__ but forgetting to handle certain names; deleting an attribute previously set; typos in fieldname; a __getattr__ that itself raises for unknown names.
Related errors
- fieldname
- fieldname
- name '%s' is not defined
- local variable '%s' referenced before assignment
- global name '%s' is not defined
AI-assisted analysis of aosabook/500lines@fba689d101 (2026-08-13).
Data as JSON: /api/errors/1673c891c81599eb.
Report an issue: GitHub.