Using range objects might be worthwhile. However, your example code, Terry, won't behave well if you initialize with a generic iterable. You need the check for 'hasattr(seq, "__getitem__")' or something equivalent in the initializer. But if you have that, you need to make a decision of *what* concrete sequence to instantiate the iterable as, with list() being the obvious choice.
E.g. I can do:
lv = ListView(Thing(random()) for _ in range(100000))
But you can't do:
sv = SeqView(Thing(random()) for _ in range(100000))
I think, however, there's no reason at all why I should have my .to_list() method. That's accomplished more naturally within a special method just as:
concrete = list(lv[5:10])