Computing the n-th prime
First, you should read the Python style guide it has a lot of info on good practices for code readability.

But as for your code, part of the reason the smarter way is slower is that you're creating the whole list every time. It's not stored at all when you create it and this means that instead you're just taking extra time because it has to go through the effort of building the list every time even though you only need the last value. Also, you're not limiting what primes you test for division, so you've lost the root optimisation you used before.

If you cached this list as part of the function then you actually would have time saved on repeated calls, though it would still be slower initially due to building the initial list. There is a way to set up a cache pretty easily, using default parameters. If you're unfamiliar with them, leave a comment and I can explain more about how they're generally used, though I'm using them in a different way than normal here.

If you change def prime(n) to def prime(n, cache=[2]) then you'll have a list called cache created containing 2, the first prime. Each time you call prime it refers back to the same list, so if you append your primes to it, it will be retained and save you all that work.

First of all, this means you might not need to calculate anything when you start. You can just try to return your prime value immediately:

def prime(n, cache=[2]):
    try:
        return cache[n - 1]
    except IndexError:
        pass


To explain, try except is used to attempt a piece of code that may generate an error. So it tries to return the nth prime (use n-1 because lists are indexed from 0) but if it can't find that value in the list it will throw an IndexError. Our except will catch this and just pass, meaning it goes on to run the rest of the function.

The other benefit is you can start your while loop from the last point in that list. So m (which I'd rename as num) can just be the last prime cached + 1 and i can be set as len(cache), since that's the amount of previous primes we're skipping.

i = len(cache)
num = cache[-1] + 1


Now you can begin your while loop, skipping the previously found values but still having them as your divisor check. Note also, you can collapse this with some other syntax and smarter logic. Python has else syntax for a for loop. If you never call break from a for loop then the else will be run, but otherwise it will be skipped. With this in mind you can remove multiple lines where you had to use flag before. Also if you're calling m = m + 2 in both cases, it should just be at the end for both conditions. And lastly, you can shorten var = var + 1 to var += 1 in Python, so I did that too.

while i &lt; n:
    for prime in cache:
        if num % prime == 0:
            break
    else:
        cache.append(num)
        i += 1
    num += 2


Here's how the fully rewritten code would look:

def prime(n, cache=[2]):

    try:
        return cache[n - 1]
    except IndexError:
        pass

    i = len(cache)
    num = cache[-1] + 1

    while i &lt; n:
        for prime in cache:
            if num % prime == 0:
                break
        else:
            cache.append(num)
            i += 1
        num += 2

    return cache[-1]