It is my understanding that the range() function, which is actually an object type in Python 3, generates its contents on the fly, similar to a generator.
range()
Try x-1 in (i for i in range(x)) for large x values, which uses a generator comprehension to avoid invoking the range.__contains__ optimisation.
x-1 in (i for i in range(x))
x
range.__contains__