考虑下面的代码,它是我下面问题的一部分:
import functools
N = 3
class Struct:
"""Create an instance with argument=value slots.
This is for making a lightweight object whose class doesn't matter."""
def __init__(self, **entries):
self.__dict__.update(entries)
def __repr__(self):
args = ['%s=%s' % (k, repr(v)) for (k, v) in vars(self).items()]
return '\nStruct(%s)' % ', '.join(args)
def doit( move ):
( rowIn, colIn ) = move
something = rowIn + ( 10 * colIn ) # An involved computation here in real life
return Struct( coord = ( rowIn, colIn ), something = something )
legalStates = [ ( row, col ) for row in xrange( N ) for col in xrange( N ) ] # A more complicated function that generates the list in real life. Call it 'complicatedFunction'
genExpFn = lambda : ( ( s.something, m, s ) for ( m, s ) in ( ( move, doit( move ) ) for move in legalStates ) ) #Q1
successorsSortedGenFn = lambda : ( p for p in sorted( genExpFn(), reverse = True ) )
def bFunc( s, a ):
#print "a * s ->", a * s
return a * s # An involved computation here in real life
def aFunc( ( v, m, s ) ): #Q2
assert( s.something == v )
return bFunc( s.something, 10 )
print "min( successorsSortedGen ) -> " + str( min( successorsSortedGenFn(), key=functools.partial( aFunc )) ) #Q3
print
print "max( successorsSortedGen ) -> " + str( max( successorsSortedGenFn(), key=functools.partial( aFunc )) ) #Q4
我的问题基于标记为“#Q”的陈述:
Q1:很明显,生成器已完全实例化(所有元素都被执行),正如我们调用sorted()
它(它生成所有元素并创建一个临时未排序列表,它排序并作为新列表返回?)。
有没有一种节省空间的方法,可以最大限度地减少临时对象的创建并产生排序列表?
我尝试过,但无法编写一个可以使用就地排序的列表理解list.sort()
这是我在想的那种表达方式:
successorsSorted = [ ( s.something, m, s ) for ( m, s ) in ( ( move, doit( move ) ) for move in legalStates ) ].sort( reverse = True )
Q2:请注意,'aFunc' 只是 'bFunc' 的包装,因为我无法在functools.partial( aFunc )
调用中编写等效表示。
functools.partial( aFunc )
我正在寻找的“aFunc”表达式是什么,可以让我直接调用“bFunc”?
编辑:Q2 的答案是lambda ( v, m, s ): bFunc(s.something, 10)
因此,语句变为:
print "min( successorsSortedGen ) -> " + str( min( successorsSortedGenFn(), key=functools.partial( lambda ( v, m, s ): bFunc(s.something, 10)) ) )
print
print "max( successorsSortedGen ) -> " + str( max( successorsSortedGenFn(), key=functools.partial( lambda ( v, m, s ): bFunc(s.something, 10)) ) )
我知道这似乎有点蹩脚,我之前没有想到这个,但是哦,好吧(感谢 aaronasterling 的温和刺激)。
Q3, Q4:请注意,传递给 min() 和 max() 的元素已经排序。
我是否可以对 min() 和 max() 进行此提示,以便它不会将整个列表作为临时实例实例化,然后遍历整个列表以定位 min 或 max 元素?
如果没有,是否存在不实例化整个列表的模块或自定义函数,但是,鉴于传递给它的列表已排序,在检查最少数量的元素时返回最小或最大元素?