aosabook/500lines · error · AttributeError
fieldname
Error message
fieldname
What it means
Raised by Base.read_attr in the 02-attr-based objmodel when a field is not in the instance's own dict (self._fields) and not found walking the class MRO via cls._read_from_class, and the class result is not a bindable callable. The message is the bare fieldname. This variant has no __getattr__ fallback, so any truly absent attribute lands here.
Source
Thrown at objmodel/code/02-attr-based/objmodel.py:21
class Base(object):
""" The base class that all of the object model classes inherit from. """
def __init__(self, cls, fields):
""" 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
raise AttributeError(fieldname)
def write_attr(self, fieldname, value):
""" write field 'fieldname' into the object """
self._write_dict(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
- Store the field first via write_attr, or pass it in the Class fields dict at construction.
- Confirm the fieldname spelling matches between write and read.
- Add the field/method to the Class (or a base class in the MRO) so _read_from_class resolves it.
- Move to the 03-customizable or 04-maps variant, which support a __getattr__ fallback before raising.
Example fix
// before
obj = Instance(MyClass)
obj.read_attr('color') # AttributeError: color
// after
obj = Instance(MyClass)
obj.write_attr('color', 'red')
obj.read_attr('color') Defensive patterns
Strategy: validation
Validate before calling
MISSING = object()
def has_attr(obj, fieldname):
if obj._read_dict(fieldname) is not MISSING:
return True
return obj.cls._read_from_class(fieldname) is not MISSING
# before reading
if has_attr(obj, 'color'):
obj.read_attr('color') Type guard
def field_exists(obj, name):
MISSING = object() # same sentinel as objmodel
return (obj._fields.get(name, MISSING) is not MISSING
or obj.cls._read_from_class(name) is not MISSING) Try / catch
try:
val = obj.read_attr(fieldname)
except AttributeError:
val = <default> Prevention
- Always write_attr before read_attr on a new field.
- Centralize field access behind a helper that supplies a default.
- Add fields to the Class fields dict so instances inherit them.
When it happens
Trigger: Calling obj.read_attr('foo') (directly, or indirectly via attribute access / callmethod) where 'foo' was never written with write_attr and is not a field/method on the instance's class or any base class. E.g. reading an attribute from a freshly created Instance whose Class has no such field.
Common situations: Forgetting to write_attr before read_attr; referencing a method name never added to the Class fields; a typo in the fieldname; expecting inherited attributes when the base_class chain does not contain them.
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/b604869ab8ba0cca.
Report an issue: GitHub.