[英]Mutability of Python Generator Expressions versus List and Dictionary Comprehension: Nested Dictionary Weirdness
我正在使用Python 3.5創建一組生成器來解析一組打開的文件,以便從這些文件中挑選數據以構建我計划稍后導出的對象。 在進行任何分析之前,我最初解析了每個文件的整體並創建了一個字典對象列表,但這個過程有時需要30秒,因為我只需要處理每個文件的每一行一次,認為這是一個使用發電機的好機會。 但是,我覺得我在概念上遺漏了生成器,也許是生成器中對象的可變性。
我制作字典列表的原始代碼如下:
parsers = {}
# iterate over files in the file_name file to get their attributes
for dataset, data_file in files.items():
# Store each dataset as a list of dictionaries with keys that
# correspond to the attributes of that dataset
parsers[dataset] = [{attributes[dataset][i]: value.strip('~')
for i, value in enumerate(line.strip().split('^'))}
for line
in data_file]
我通過調用以下方式訪問列表:
>>>parsers['definitions']
它按預期工作,返回一個字典列表。 但是,當我將此列表轉換為生成器時,會發生各種奇怪現象。
parsers = {}
# iterate over files in the file_name file to get their attributes
for dataset, data_file in files.items():
# Store each dataset as a list of dictionaries with keys that
# correspond to the attributes of that dataset
parsers[dataset] = ({attributes[dataset][i]: value.strip('~')
for i, value in enumerate(line.strip().split('^'))}
for line
in data_file)
我用它來稱呼它:
>>> next(parsers['definitions'])
運行此代碼會返回索引超出范圍錯誤。
我可以在兩個代碼段之間看到的主要區別在於,在列表推導版本中,python從文件構造列表並繼續運行而無需存儲解析變量供以后使用。
相反,在生成器表達式中,生成器中定義的變量需要與生成器一起存儲,因為它們稍后在我的代碼中影響生成器的每次連續調用。 我想也許生成器中的變量可能與我的代碼創建的其他生成器共享一個命名空間,因此每個生成器都基於最后運行的生成器表達式而具有不穩定的行為,因此最后設置變量的值。
我很欣賞這個問題的原因!
我認為問題出在你構建字典時。
attributes[dataset][i]
請注意,對於列表版本, dataset
是for
循環的特定轉彎處的dataset
。 但是,使用生成器,直到for循環完成后才會計算該表達式,因此dataset
將具有files.items()
循環中最后一個數據集的值...
這是一個超級簡單的演示,有希望詳細說明問題:
results = []
for a in [1, 2, 3]:
results.append(a for _ in range(3))
for r in results:
print(list(r))
請注意,我們總是得到[3, 3, 3]
因為當我們從生成器中獲取值時, a
值為3
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.