The short answer would be you can't.
Let's explore this a bit through examples.
# Original code
y=list(range(MAX))
for n in range(MAX):
y[n]=[n,n**2,func(n)]
# That took 0.86 seconds
This is the result on my machine so we have a baseline for comparison.
Let us make that a single line and shave off some time.
y = [[n, n ** 2, func(n)] for n in range(MAX)]
# That took 0.74 seconds
We are creating a list of lists and the Python interpreter needs to allocate an empty list MAX times.
In case you don't need to change the number of elements after initialization it might be better to use tuples instead of lists.
y = [(n, n ** 2, func(n)) for n in range(MAX)]
# That took 0.43 seconds
This is twice as fast as the original method.
Let's now assume that we can optimize even more by using some special library and then we just need to parse the result to populate the list. To simulate this we can pickle the list to a binary format and then measure the time it takes to load it.
import pickle
b = pickle.dumps([(n, n ** 2, func(n)) for n in range(MAX)])
starttime = time.time()
y = pickle.loads(b)
print('That took {:.2f} seconds'.format(time.time() - starttime))
# That took 0.23 seconds
This is probably close to what is possible to achieve without coding anything in a lower level language like C and creating Python objects from that language.
Alternative approach
If there is no requirement to create exactly the same object as in the original example and if it is enough that we can read y[10] or y[100:1000] we can do something completely different.
class LazyList():
def __init__(self, size):
self.size = size
def __getitem__(self, key):
if isinstance(key, slice):
r = range(self.size)[key]
return [(n, n ** 2, func(n)) for n in r]
return (key, key ** 2, func(key))
starttime = time.time()
y = LazyList(MAX)
print('That took {:.6f} seconds'.format(time.time() - starttime))
# That took 0.000005 seconds
This is multiple orders of magnitude faster. Of course, this is not a list and the results of the computation are not in memory. We created an object that will in some cases act like a list, but not in other cases (e.g. y[MAX*2] will work, even though it shouldn't). Note that with more work, the object can become even more similar to a list and also use a list as its base class.
If the object we got is converted to a list, the process spends the time that was saved by the alternative approach and the result is the same as in one of the previous examples.
y = y[:]
# That took 0.43 seconds
The longer answer is that it depends on the type of the result that is expected.