For loop 关于理解循环的一行

For loop 关于理解循环的一行,for-loop,python,loops,apache-spark,pyspark,For Loop,Python,Loops,Apache Spark,Pyspark,在阅读了问题之后,我有了这个Pypark代码: model = KMeansModel(model.Cs[0]) first_split = split_vecs.map(lambda x: x[0]) model.computeCost(first_split) model = KMeansModel(model.Cs[1]) second_split = split_vecs.map(lambda x: x[1]) model.computeCost(second_split) 我能把这个

在阅读了问题之后,我有了这个Pypark代码:

model = KMeansModel(model.Cs[0])
first_split = split_vecs.map(lambda x: x[0])
model.computeCost(first_split)
model = KMeansModel(model.Cs[1])
second_split = split_vecs.map(lambda x: x[1])
model.computeCost(second_split)
我能把这个写进一行循环吗?或者这些循环在它们的体内只有一条线

注意:我不是只寻找代码答案,我想学习,所以请解释。:)


以下是我的悲惨尝试:

model.computeCost(split) for i in range(2): # <- the semicolon here doesn't feel right..Where to put the other lines?

model.computeCost(拆分)范围(2)内的i:#尝试不使用分号。虽然老实说,我不建议在生成器表达式之外的语句中使用一行,但这还没有经过测试,但看起来它可能适合您

computedCost = [KMeansModel(model.Cs[i]).computeCost(x[i]) for i in xrange(2)]

它所做的是在对
KMeansModel()
的结果执行computeCost()之后创建一个结果列表。循环的
xrange
只返回i的值在该示例中所做的列表理解版本为:

[KMeansModel(model.Cs[i]).computeCost(split_vecs.map(lambda x: x[i])) for i in range(2)]
这无异于:

results = []
for i in range(2):
    results.append(KMeansModel(model.Cs[i]).computeCost(split_vecs.map(lambda x: x[i])))

因此,对于每个
i
,它都会将链式表达式的返回值附加到列表中。在本例中,它正好起作用,因为您的三条线可以链接在一起。您正在对使用
KMeansModel(model.Cs[0])
创建的对象调用
computeCost()
方法,该方法的参数是
split\u vecs.map(lambda x:x[0])

您可以将您拥有的三个不同函数(KMeansModel、split\u vec.map和computeCost)封装在另一个函数中,如下所示:

def master_fx(var):
    return fx_C(fx_B(fx_A(var)))
现在它看起来不错了,您可以使用列表理解:

[master_fx(element) for element in range(2)]
或者一个for循环(在一行或多行上——除了可读性方面,它通常没有什么区别。我之所以这样说,是因为当我尝试在同一行上放置另一个控件结构时,会出现错误,如:

for i in range(2): if i%2==0: print(i)
但是,出于可读性的考虑,您可能不会想要上面这一行的内容)

可能最重要的区别在于for循环只是一种控制结构,而列表理解是一种奇特的列表,您可以在其上定义操作。这就是为什么在ipython这样的交互式解释器中,您必须打印for循环的输出(上面示例中的元素和i),而不是列表理解。

您所称的“一行for循环”实际上被称为“列表理解”、“字典理解”或“表达式”。它们比循环的限制更大,工作原理如下:

# List comprehension
result = [expression for name in iterable]
# equivalent to:
result = []
for name in iterable:
    result.append(expression)

# Dictionary comprehension
result = {key_expression: value_expression for name in iterable}
# equivalent to:
result = {}
for name in iterable:
    result[key_expression] = value_expression

# Generator expression
result = (expression for name in iterable)
# equivalent to
def anonymous_generator():
    for name in iterable:
        yield expression
result = anonymous_generator()
您可以嵌套它们,它们实际上不需要是一行。例如(可能没有用),列表理解可用于从列表
listA
中获取所有可能的元素对的列表,以及从dict
dictB
中的列表中获取由
listA
中的内容键入的元素(不需要换行,但有助于可读性):


然而,它们的主要局限性是不能调用任意函数——唯一可以放置表达式的地方是在说出正在使用的可重用项以及要输出到结果中的内容时。不过,您调用的任何函数的副作用都会发生!对于你的特定情况,你不能简单地做任何事情,因为你一直在重新分配模型,在理解的过程中你不能这么做。也许可以将事情扭转到足够大的程度,以获得相同的效果(通过编写其他函数,在返回正确的值之前将赋值作为副作用),但在这种情况下,这并不值得。

但是其他行应该去哪里呢?你看过我的全部评论了吗?嗯,我不太懂Python,所以我试图理解这背后的原理。@gsamaras只做常规for循环?这实际上没有帮助,因为OP使用
split
作为
computeCost
函数的参数,而for循环设置
I
。如果单行循环指的是列表理解,您不能在它们中进行赋值。@gsamaras对于这个特定的问题,我真的不知道,因为我不知道返回值。但这不是台词的问题。您总是可以为范围(2)中的i执行类似于
[KMeansModel(model.Cs[i]).computeCost(split_vecs.map(lambda x:x[i]))的操作
,但它是否适用于该库?我不知道。你们的一轮比普通的for-loop有什么优势?还是你想要理解?@MosesKoledoye检查我的更新。这主要是为了理解他们,这样当我在别人的人代码中遇到他们时,我会感到舒服。我没有经验回答你的第二个问题,即兴发挥!:)我认为“一行换一圈”是关于列表的理解。嗯,可能是@DanielRoseman,这意味着我的问题的答案是否定的,对吗?你看,我真的不知道这就是为什么我要努力学习..并问一些糟糕的问题,我想:/酷,谢谢!!!让我惊讶的是,在一个0分的问题中,我有3.5个答案P非常感谢你的解释,大卫!即使我的问题是0分,看到这样一个好答案的感觉真是太好了!
pairs = [(a, b) for a in listA
                for b in dictB[a]]
# equivalent to:
pairs = []
for a in listA:
    for b in dictB[a]:
        pairs.append(a, b)