Aha, I just noticed in a second read-through that `_slice_to_depth` is also called again after `verified_subclasses` is constructed, which explains why you decided to pull it out as a separate method.

What I would do instead is pull out a method that simply returns the maximum depth (i.e. 1 for Django < 1.6, `None` - as in "no limit" - for Django 1.6+), so that version-checking logic isn't repeated, but then have both `_get_subclasses_recurse` and `_get_models_recurse` (which should be renamed) check and respect the maximum depth independently, so that `_get_subclasses_recurse` at least can take advantage of the efficiency of knowing this upfront. Not sure if `_get_models_recurse` can benefit much from that in terms of efficiency since its going the other direction, but it can still do the limiting just fine.