max([x for x in something]) vs max(x for x in something):为什么有区别,区别是什么?
max([x for x in something]) vs max(x for x in something): why is there a difference and what is it?
我正在为 class 开发一个项目,我的代码没有产生与参考代码相同的结果。
我将我的代码与参考代码逐行比较,它们看起来几乎完全一样。一切似乎在逻辑上都是等价的。最终我开始更换线路并进行测试,直到找到重要的线路。
原来是这样的(编辑:确切的代码在下面):
# 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))
现在,这让我感到困惑。我尝试了一些使用 Python (2.7) 解释器的实验,运行 测试使用 max
对列表推导式(带和不带方括号)进行测试。结果似乎完全一样。
即使通过 PyCharm 进行调试,我也找不到我的版本没有产生与参考版本完全相同的结果的原因。到目前为止,我认为我对列表理解的工作方式(以及 max()
函数的工作方式)有很好的处理,但现在我不太确定,因为这是一个奇怪的差异。
这是怎么回事?为什么我的代码产生的结果与参考代码(在 2.7 中)不同?传递不带括号的理解与传递带括号的理解有何不同?
编辑 2:确切的代码是这样的:
# 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])
我不认为这应该被标记为重复——是的,另一个问题是关于理解对象和列表对象之间的区别,但不是为什么 max()
在给定 [= 时会提供不同的结果31=],而不是单独的 'X comprehension'。
在列表理解周围使用 []
实际上会生成一个列表到您的变量中,或者在本例中生成到您的 max 函数中。如果没有括号,您将创建一个 generator
对象,该对象将被送入 max 函数。
results1 = (x for x in range(10))
results2 = [x for x in range(10)]
result3 = max(x for x in range(10))
result4 = max([x for x in range(10)])
print(type(results1)) # <class 'generator'>
print(type(results2)) # <class 'list'>
print(result3) # 9
print(result4) # 9
据我所知,它们在 max 函数中的工作原理应该基本相同。
我不知道为什么你的项目中有不同的值,但我可以给你一个活生生的例子,当它发生时。生成器比列表更有效,所以我们会有不同的内存使用。我正在使用 Python 3.
returns 当前内存使用量 Python 的函数:
import os
import psutil
def memory_usage():
"""Get process virtual memory (vms) usage in MB."""
process = psutil.Process(os.getpid())
memory = process.memory_info()[1] / (1024.0 * 1024.0)
return memory
试试这个代码:
# Generator version:
max_q = max(memory_usage() for i in range(100000))
print(max_q) # 7.03125
我测试了几次代码,我在我的机器上得到了一些超过 7 的东西。
用列表版本替换生成器版本:
# List version:
max_q = max([memory_usage() for i in range(100000)])
print(max_q) # 11.44921875
我的机器上 11 有点问题。
如你所见,代码几乎相同,但你会得到不同的输出。
可能在您的项目中,getQValue() 会根据一些已计算的值为您提供不同的值。但是,如果您使用生成器,垃圾收集器可以更快地删除现有值。
您是否泄漏了影响后续代码的局部变量?
# 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!
生成器和字典理解创建一个新的范围,但在 py3 之前,列表理解没有,为了向后兼容
简单的测试方法 - 将您的代码更改为:
max_q = max([self.getQValue(nextState, action) for action in legal_actions])
max_q = max(self.getQValue(nextState, action) for action in legal_actions)
假设 self.getQValue
是纯的,那么第一行唯一持久的副作用就是弄乱了局部变量。如果这打破了它,那么这就是你的问题的原因。
我正在为 class 开发一个项目,我的代码没有产生与参考代码相同的结果。
我将我的代码与参考代码逐行比较,它们看起来几乎完全一样。一切似乎在逻辑上都是等价的。最终我开始更换线路并进行测试,直到找到重要的线路。
原来是这样的(编辑:确切的代码在下面):
# 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))
现在,这让我感到困惑。我尝试了一些使用 Python (2.7) 解释器的实验,运行 测试使用 max
对列表推导式(带和不带方括号)进行测试。结果似乎完全一样。
即使通过 PyCharm 进行调试,我也找不到我的版本没有产生与参考版本完全相同的结果的原因。到目前为止,我认为我对列表理解的工作方式(以及 max()
函数的工作方式)有很好的处理,但现在我不太确定,因为这是一个奇怪的差异。
这是怎么回事?为什么我的代码产生的结果与参考代码(在 2.7 中)不同?传递不带括号的理解与传递带括号的理解有何不同?
编辑 2:确切的代码是这样的:
# 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])
我不认为这应该被标记为重复——是的,另一个问题是关于理解对象和列表对象之间的区别,但不是为什么 max()
在给定 [= 时会提供不同的结果31=],而不是单独的 'X comprehension'。
在列表理解周围使用 []
实际上会生成一个列表到您的变量中,或者在本例中生成到您的 max 函数中。如果没有括号,您将创建一个 generator
对象,该对象将被送入 max 函数。
results1 = (x for x in range(10))
results2 = [x for x in range(10)]
result3 = max(x for x in range(10))
result4 = max([x for x in range(10)])
print(type(results1)) # <class 'generator'>
print(type(results2)) # <class 'list'>
print(result3) # 9
print(result4) # 9
据我所知,它们在 max 函数中的工作原理应该基本相同。
我不知道为什么你的项目中有不同的值,但我可以给你一个活生生的例子,当它发生时。生成器比列表更有效,所以我们会有不同的内存使用。我正在使用 Python 3.
returns 当前内存使用量 Python 的函数:
import os
import psutil
def memory_usage():
"""Get process virtual memory (vms) usage in MB."""
process = psutil.Process(os.getpid())
memory = process.memory_info()[1] / (1024.0 * 1024.0)
return memory
试试这个代码:
# Generator version:
max_q = max(memory_usage() for i in range(100000))
print(max_q) # 7.03125
我测试了几次代码,我在我的机器上得到了一些超过 7 的东西。
用列表版本替换生成器版本:
# List version:
max_q = max([memory_usage() for i in range(100000)])
print(max_q) # 11.44921875
我的机器上 11 有点问题。
如你所见,代码几乎相同,但你会得到不同的输出。
可能在您的项目中,getQValue() 会根据一些已计算的值为您提供不同的值。但是,如果您使用生成器,垃圾收集器可以更快地删除现有值。
您是否泄漏了影响后续代码的局部变量?
# 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!
生成器和字典理解创建一个新的范围,但在 py3 之前,列表理解没有,为了向后兼容
简单的测试方法 - 将您的代码更改为:
max_q = max([self.getQValue(nextState, action) for action in legal_actions])
max_q = max(self.getQValue(nextState, action) for action in legal_actions)
假设 self.getQValue
是纯的,那么第一行唯一持久的副作用就是弄乱了局部变量。如果这打破了它,那么这就是你的问题的原因。