2016-05-08 8 views
2

私のコードをコンパクト化しようとしていて、Pythonにはとても新しいので、私が欲しいものを正確にカバーする前のトピックがある場合は謝ります。私はほとんど成功せずに検索と読書を試みました。どんな助けでも大変感謝します。ありがとう!Python 3.5 - ジェネレータで生成された名前付きタプルを作成する

(セル・コールは、私が提示ために必要なデータといくつかのランダムなスプレッドシートからあると仮定してください)

import xlrd 
import collections 

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', ['Room_ID', 'Name', 'Type', 'Area', 'Sens_Cooling', 'Lat_Cooling', 'Heating', 
             'Ventilation', 'People', 'Volume']) 

a = (L_ws.cell_value(row, L_col[0]) for row in range(start, end)) 
b = (L_ws.cell_value(row, L_col[1]) for row in range(start, end)) 
c = (L_ws.cell_value(row, L_col[2]) for row in range(start, end)) 
d = (L_ws.cell_value(row, L_col[3]) for row in range(start, end)) 
e = (L_ws.cell_value(row, L_col[4]) for row in range(start, end)) 
f = (L_ws.cell_value(row, L_col[5]) for row in range(start, end)) 
g = (L_ws.cell_value(row, L_col[6]) for row in range(start, end)) 
h = (L_ws.cell_value(row, L_col[7]) for row in range(start, end)) 
i = (L_ws.cell_value(row, L_col[8]) for row in range(start, end)) 
j = (L_ws.cell_value(row, L_col[9]) for row in range(start, end)) 

rs = sp(a, b, c, d, e, f, g, h, i, j) 

答えて

0

あなたは、次の操作を行うことができます:あなたが既に持っているので

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_colに書き込むことができます。すべての列に対して、ジェネレータ式は、前に作成したジェネレータと同じジェネレータを返す別のメソッドを呼び出します。ジェネレータが呼び出されるとcolが評価されるので、closureをここで使用する必要があることに注意してください。最後に結果は*演算子で解凍された後、spに渡されます。

+0

説明のために、ありがとう! – njohnson

+0

私は、rsの各ジェネレータが指定された変数ではなく、「ボリューム」を与えている上記の同じ問題を抱えています。したがって、 'print(list(rs.Name))'と 'print(list(rs.Area))'はどちらもNameまたはAreaではなくVolumeを指定します。 – njohnson

+0

@njohnson:私は、問題を解決するクロージャを使用するように私の例を変更しました。何が起こっていたかの詳細な説明については、https://eev.ee/blog/2011/04/24/gotcha-python-scoping-closures/を参照してください。 – niemmi

2

あなたがすることができるようにそれは私になります

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))) 

このジェネレータstart,endおよび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) 

...それはジェネレータ式を置くことが少し奇妙な感じあなたがなぜでものいずれかにできない理由はありませんが...

+0

よかった。そうですね、私は数百のデータポイントを表現することになります。私は、それらをすべてメモリにロードするのではなく、必要に応じてアクセスしたいと思っています。処理が必要な一連の計算があり、もっと便利だと思いましたか? – njohnson

+0

「print(list(rs.Name))」のチェックをした理由は何ですか?前回と同じようにコードが明示的である場合、同じ結果が得られません。 – njohnson

+0

@njohnson - snap。これは、ジェネレータを使用しているために定義されているときではなく、呼び出されたときに 'i'の値を受け取るためです。つまり、すべてのジェネレーターが_last_列を参照しています。個人的には、リストの組を持つことは、ジェネレータのタプルよりも私には意味があるので、リストの理解に移りました(これは私が答えで行ったことです)。しかし、なぜ私はあなたが最初にジェネレータを使用したのか分かりません。(そしてそれには理由があるかもしれません)... – mgilson

関連する問題