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

  1. Store the field first via write_attr, or pass it in the Class fields dict at construction.
  2. Confirm the fieldname spelling matches between write and read.
  3. Add the field/method to the Class (or a base class in the MRO) so _read_from_class resolves it.
  4. 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

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


AI-assisted analysis of aosabook/500lines@fba689d101 (2026-08-13). Data as JSON: /api/errors/b604869ab8ba0cca. Report an issue: GitHub.