Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

max([x for x in something]) vs max(x for x in something): why is there a difference and what is it?

I was working on a project for class where my code wasn't producing the same results as the reference code.

I compared my code with the reference code line by line, they appeared almost exactly the same. Everything seemed to be logically equivalent. Eventually I began replacing lines and testing until I found the line that mattered.

Turned out it was something like this (EDIT: exact code is lower down):

# my version:
max_q = max([x for x in self.getQValues(state)])

# reference version which worked:
max_q = max(x for x in self.getQValues(state))

Now, this baffled me. I tried some experiments with the Python (2.7) interpreter, running tests using max on list comprehensions with and without the square brackets. Results seemed to be exactly the same.

Even by debugging via PyCharm I could find no reason why my version didn't produce the exact same result as the reference version. Up to this point I thought I had a pretty good handle on how list comprehensions worked (and how the max() function worked), but now I'm not so sure, because this is such a weird discrepancy.

What's going on here? Why does my code produce different results than the reference code (in 2.7)? How does passing in a comprehension without brackets differ from passing in a comprehension with brackets?

EDIT 2: the exact code was this:

# works
max_q = max(self.getQValue(nextState, action) for action in legal_actions)

# doesn't work (i.e., provides different results)
max_q = max([self.getQValue(nextState, action) for action in legal_actions])

I don't think this should be marked as duplicate -- yes, the other question regards the difference between comprehension objects and list objects, but not why max() would provide different results when given a 'some list built by X comprehension', rather than 'X comprehension' alone.

like image 945
bob Avatar asked Oct 25 '15 03:10

bob


People also ask

What does Max () with a key do in Python?

The max() function returns the largest item in an iterable. It can also be used to find the largest item between two or more parameters.

How do you set a max value in Python?

max() in a Set The built-in function max() in Python is used to get the maximum of all the elements in a set.

What is the time complexity of Max function in Python?

The time complexity of the python max function is O(n). We can apply it on the string, which is not possible in other languages. These types of built-in functions make python a great language.


1 Answers

Are you leaking a local variable which is affecting later code?

# works
action = 'something important'
max_q = max(self.getQValue(nextState, action) for action in legal_actions)
assert action == 'something important'

# doesn't work (i.e., provides different results)
max_q = max([self.getQValue(nextState, action) for action in legal_actions])
assert action == 'something important'  # fails!

Generator and dictionary comprehensions create a new scope, but before py3, list comprehensions do not, for backwards compatibility

Easy way to test - change your code to:

max_q = max([self.getQValue(nextState, action) for action in legal_actions])
max_q = max(self.getQValue(nextState, action) for action in legal_actions)

Assuming self.getQValue is pure, then the only lasting side effect of the first line will be to mess with local variables. If this breaks it, then that's the cause of your problem.

like image 148
Eric Avatar answered Sep 22 '22 18:09

Eric