Project Euler - Largest Product In A Grid
Stylistic it is mostly nice, and I would possibly change two things. First of I would put all of the code within a function allowing for reuse, and secondly I would change some of the names, i.e. backward_diag and forward_diag. 

From an algorithmic point of view there are however some more issues with your code:


Use range(x) when you don't care about the value – Usually it is good to do for column_value in row, but as you dereference using indexes, and don't use the column value at all, I would rather using pure indexing, and let the double loop be:

for y in range(len(grid)):
    for x in range(len(grid[y])):

What's the point with used? – I don't understand why you store the starting value of the largest value. In itself this value is not useful, as any value could be found multiple places, and you don't store which direction the largest value was used.

If storing something I would rather store the indices and direction, something similar to (x, y, "left") where you vary the direction accordingly to current search
Don't repeat the value if a &gt; biggest else biggest – Instead of doubling the if ... else I would rather use a full blown if statement. In other words instead of


left = reduce(operator.mul, grid[y][x - 4:x], 1)
used = grid[y][x - 4:x] if left &gt; biggest else used
biggest = left if left &gt; biggest else biggest



I would rather use:

left = reduce(operator.mul, grid[y][x - 4:x], 1)
if left &gt; biggest:
    used = (x, y, "left")
    biggest = left

Don't repeat calculation – As Zack commented upon I wouldn't calculate both the left and right, and similarily the up and down, as these are redundant.
Strange validation of ranges – The only range you check is the x + 4 &lt; 20, but you don't do any validation on other ranges. This means that you calculate the left even though you don't have 4 values to the left of current value, and so on. This is kind of sloppy, and could easily be avoided.