Python 3.5-创建用生成器填充的命名元组

Python 3.5-创建用生成器填充的命名元组,python,iterator,generator,list-comprehension,namedtuple,Python,Iterator,Generator,List Comprehension,Namedtuple,尝试压缩我的代码,我对Python非常陌生,因此如果前面有一个主题完全涵盖了我想要的内容,我很抱歉。我尝试了很多搜索和阅读,但收效甚微。任何帮助都将不胜感激,谢谢 (请假设手机呼叫来自随机电子表格,其中包含我所需的数据,顺序如下。) 您可以执行以下操作: import xlrd import collections def create_gen(column, start, end): return (L_ws.cell_value(row, column) for row in ra

尝试压缩我的代码,我对Python非常陌生,因此如果前面有一个主题完全涵盖了我想要的内容,我很抱歉。我尝试了很多搜索和阅读,但收效甚微。任何帮助都将不胜感激,谢谢

(请假设手机呼叫来自随机电子表格,其中包含我所需的数据,顺序如下。)


您可以执行以下操作:

import xlrd
import collections

def create_gen(column, start, end):
    return (L_ws.cell_value(row, column) for row in range(start, end))

L_col = (21, 0, 27, 24, 3, 4, 11, 35, 18, 26)
L_label = ('Room_ID', 'Name', 'Type', 'Area', 'Sens_Cooling', 'Lat_Cooling', 'Heating', 'Ventilation', 'People', 'Volume')
sp = collections.namedtuple('Space', L_label)
rs = sp(*(create_gen(col, start, end) for col in L_col))
由于您在
L_label
中已经有字段名,因此可以将其传递给
namedtuple
,而不是创建另一个列表


对于生成器,您可以编写在
L\u col
中的列上迭代的生成器表达式。对于每一列,生成器表达式都调用一个单独的方法,该方法返回一个生成器,就像您之前创建的生成器一样。请注意,您需要在此处使用,因为调用生成器时会计算
col
。最后,在将结果传递给
sp

之前,使用
*
运算符对结果进行解压缩。在我看来,您可以执行以下操作:

items = [
    [L_ws.cell_value(row, L_col[i]) for row in range(start, end)]
    for i in range(10)]
rs = sp(*items)
如果您的物品中需要发电机,我建议您使用发电机功能:

def gen_item(column_number):
    for row_number in range(start, end):
        yield L_ws.cell_value(row_number, L_col[column_number])

rs = sp(*(gen_item(i) for i in range(10)))
此生成器假定通过闭包拾取
开始
结束
L_col
。如果愿意,可以将它们作为参数传递

此外,上面还有一些重复:

L_label = ('Room_ID', 'Name', 'Type', 'Area', 'Sens_Cooling', 'Lat_Cooling', 'Heating', 'Ventilation', 'People', 'Volume')
sp = collections.namedtuple('Space', ['Room_ID', 'Name', 'Type', 'Area', 'Sens_Cooling', 'Lat_Cooling', 'Heating',
                                      'Ventilation', 'People', 'Volume'])
可能只是:

L_label = ('Room_ID', 'Name', 'Type', 'Area', 'Sens_Cooling', 'Lat_Cooling', 'Heating', 'Ventilation', 'People', 'Volume')
sp = collections.namedtuple('Space', L_label)

话虽如此。。。将生成器表达式放入一个命名的元组中感觉有点奇怪(尽管也没有很好的理由说明您不能这样做)…

好的,非常感谢。是的,我将有数百个潜在的数据点表示,我宁愿在需要时访问每个值,而不是将它们全部加载到内存中,这是我的推理。有一系列的计算需要处理,我认为这会更方便?无论出于什么原因,当我通过“print(list(rs.Name))”进行检查时,当代码像以前一样更显式时,我得到的结果并不相同。@njohnson--snap。这是因为您使用的是生成器,它将在调用时获取
i
的值,而不是在定义时。换句话说,所有生成器都将引用最后一列。就我个人而言,我只是将其转换为列表理解(这是我在回答中所做的),因为对我来说,列表的元组比生成器的元组更有意义。但是,我不知道你为什么首先使用生成器(你可能有一个很好的理由)…是的,我正在尝试使用生成器,这样我就不必在内存中不必要地保存列表,通过在必要时使用它们生成列表或获取计算值,我希望垃圾收集等可以保持精简。现在我没有太多的数据,但最终会有,如果我“正确地”使用生成器(希望我是),从长远来看,这应该会让事情变得更快。不过,我对python、生成器等都是新手。多年来我一直在使用MATLAB,我对python中的生成器和理解非常着迷:)@njohnson——当然。发电机很棒。生成器表达式很棒。理解力很强:-)。在这种情况下,如果您确实使用函数(如公认答案中所建议的),我可能只编写生成器函数,而不是返回生成器的函数。用法应该是难以区分的,但我认为生成器的功能稍微清晰一些。我在我的答案中添加了一个例子。我在上面遇到了同样的问题,rs中的每个生成器都给了我“音量”,而不是指定的变量。所以,“print(list(rs.Name))”和“print(list(rs.Area))”都给出了卷,而不是名称或区域。@njohnson:太棒了,我改变了我的示例,使用闭包解决了这个问题。关于正在发生的事情的详细解释,请参见。现在完全可以了,我会仔细阅读,看看是否可以让我的大脑思考正在发生的事情,谢谢!
L_label = ('Room_ID', 'Name', 'Type', 'Area', 'Sens_Cooling', 'Lat_Cooling', 'Heating', 'Ventilation', 'People', 'Volume')
sp = collections.namedtuple('Space', L_label)