【发布时间】:2018-06-10 21:43:51
【问题描述】:
编辑:为什么人们不赞成这篇文章? Python 开发者真的这么无能吗?这是一个合理的问题,而不是在其他地方得到回答的问题。我寻找解决方案。我不是白痴。一个参数有一个值,另一个是未定义的,但如果你真的阅读这篇文章,你会发现它们的范围似乎是相同的。
首先,我向你保证,这个问题不同于其他涉及错误信息的问题:
UnboundLocalError: local variable referenced before assignment closure method
当我查看这段代码时,似乎顶级方法getStockDataSaverFactory 的参数uuidString 在方法返回其内部方法saveData 时实际上应该在范围内,作为一流的函数对象...因为令我惊讶的是,参数tickerName 在范围内并且在调用saveData() 方法时确实具有值'GOOG'(例如通过测试方法testDataProcessing_getSaverMethodFactory ),所以我们实际上可以看到它在调用 getDataMethodFactory(..)
方法时有一个实际值,这与 uuidString 不同。
为了让事情更明显,我添加了以下几行:
localUuidString = uuidString
和
experimentUuidString = localUuidString
在断点检查方法时显示参数uuidString具有可用值。
def getStockDataSaverFactory(self, tickerName, uuidString, methodToGetData, columnList):
# This method expects that methodToGetData returns a pandas dataframe, such as the method returned by: self.getDataFactory(..)
localUuidString = uuidString
def saveData():
(data, meta_data) = methodToGetData()
experimentUuidString = localUuidString
methodToNameFile = self.getDataMethodFactory(tickerName, uuidString)
(full_filepathname, full_filename, uuidString) = methodToNameFile()
methodToSaveData = self.getDataFrameSaverFactory(methodToGetData, columnList, full_filepathname)
# We might want try/catch here:
methodToSaveData()
# A parameterless method that has immutable state (from a closure) is often easier to design around than one that expects parameters when we want to pass it with a list of similar methods
return (full_filepathname, full_filename, uuidString)
return saveData
def testDataProcessing_getSaverMethodFactory(self):
dataProcessing = DataProcessing()
getSymbols = dataProcessing.getSymbolFactory(
dataProcessing.getNasdaqSymbols(dataProcessing.getListOfNASDAQStockTickers))
tickers = getSymbols()
uuidString = 'FAKEUUID'
columnList = ['low', 'high']
tickerSubset = tickers[0:2]
methodsToPullData = map(lambda ticker: dataProcessing.getStockDataSaverFactory(ticker,
uuidString,
dataProcessing.getDataFactory(
ticker),
columnList), tickerSubset)
savedPathTuples = [f() for f in methodsToPullData]
savedFileNames = [pathTuple[0] for pathTuple in savedPathTuples]
for fileName in savedFileNames:
self.assertTrue(os.path.isfile(fileName))
os.remove(fileName)
为了清楚说明 uuidString 没有价值,但 ticker 确实有价值,我将这个屏幕截图包括在内:
请注意,在变量监视窗口中,uuidString 未定义,但ticker 的字符串值为“A”。
Python(或 Python 3)是否有什么独特之处导致了这种行为?
【问题讨论】:
-
你能发布完整的堆栈跟踪吗?这里没有加起来。在实际应用中,您所展示的内容没有任何错误。请参阅此repl.it - 定义并返回的函数维护对其定义的范围的访问 - 除非发生其他未显示的事情。
-
这是一种有趣的创建对象
dataProcessing = DataProcessing.DataProcessing()的方法?为什么它不仅仅是dataProcessing = DataProcessing(),有什么特别的原因吗? -
看在上帝的份上,请缩短函数名称....!为什么函数会返回其他函数?您调用这些函数,然后立即调用它们返回的函数。这似乎真的过于复杂了。
-
@NedBatchelder 你有没有在函数式编程中使用过柯里化,或者在 Javascript/node.js 中使用过 promise?还是 C# 中的通用 lambda?实际上,我在这里为 S.O. 保持简单。例子。在实践中,我会获取一个字符串列表,然后我可以将一组方法生成器函数流水线化,这些函数的功能类似于装饰器(作为方法组合的一种形式)。想想 string -> methodThatGetsData -> methodThatSavesRetrievedData -> methodThatTransformsSavedData -> methodThatSortsTransformedData -> 等。在实施时,您只需要提供方法生产者列表即可设置管道。
-
好吧,你做到了:)
标签: python python-3.x lambda closures first-class-functions