Python inner/nested 方法关闭的 3 个参数超出范围并触发 UnboundLocalError
Python 3 parameter closed upon by inner/nested method falls out of scope and triggers UnboundLocalError
编辑:为什么人们反对这个post? Python 开发人员真的这么无能吗?这是一个合理的问题,在其他地方没有得到回答。我搜索了一个解决方案。我不是白痴。一个参数有一个值,另一个未定义,但如果您实际阅读 post,您会发现它们的范围似乎相同。
首先,我向你保证,这个问题不同于其他涉及错误信息的问题:
UnboundLocalError: local variable referenced before assignment closure method
当我查看这段代码时,似乎顶级方法 getStockDataSaverFactory
的参数 uuidString
实际上应该在方法 returns 它的内部方法 saveData
作为第一个 class 函数对象...因为令我惊讶的是,参数 tickerName
在范围内并且确实具有值 'GOOG' 当 saveData()
方法被调用时(例如通过测试方法 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
确实有价值,我附上了这张截图:
注意变量 watch window 中,uuidString
未定义,但 ticker
的字符串值为 "A".
Python(或 Python 3)有什么独特之处导致了这种行为吗?
问题是您在分配给它之前在对 self.getMethodThatProvidesFullFilePathNameForPricesCsvFromUUIDAndTickerName
的调用中引用了 uuidString。该赋值使其在最内层函数的范围内成为局部,因此,当您引用它时,它是未赋值的。
范围规则的完整描述由:
提供
这个更简单的例子重现了你的错误,使问题更清楚:
class aclass():
def outer(self, uuidString):
def inner():
print(uuidString)
uuidString = 'new value'
return uuidString
return inner
a = aclass()
func = a.outer('a uuid')
val = func()
print(val)
inner()
中的赋值导致 uuidString
是 inner()
的局部变量,因此在 print(uuidString)
被调用时未赋值,这导致 Python 提高 UnboundLocalError
.
您可以通过将变量传递给带有默认参数的函数来修复错误。更改 saveData
的定义以将 uuidString
作为默认参数传递,如:
def saveData(uuidString=uuidString):
将使它如您所愿地工作。
编辑:为什么人们反对这个post? Python 开发人员真的这么无能吗?这是一个合理的问题,在其他地方没有得到回答。我搜索了一个解决方案。我不是白痴。一个参数有一个值,另一个未定义,但如果您实际阅读 post,您会发现它们的范围似乎相同。
首先,我向你保证,这个问题不同于其他涉及错误信息的问题:
UnboundLocalError: local variable referenced before assignment closure method
当我查看这段代码时,似乎顶级方法 getStockDataSaverFactory
的参数 uuidString
实际上应该在方法 returns 它的内部方法 saveData
作为第一个 class 函数对象...因为令我惊讶的是,参数 tickerName
在范围内并且确实具有值 'GOOG' 当 saveData()
方法被调用时(例如通过测试方法 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
确实有价值,我附上了这张截图:
注意变量 watch window 中,uuidString
未定义,但 ticker
的字符串值为 "A".
Python(或 Python 3)有什么独特之处导致了这种行为吗?
问题是您在分配给它之前在对 self.getMethodThatProvidesFullFilePathNameForPricesCsvFromUUIDAndTickerName
的调用中引用了 uuidString。该赋值使其在最内层函数的范围内成为局部,因此,当您引用它时,它是未赋值的。
范围规则的完整描述由:
提供这个更简单的例子重现了你的错误,使问题更清楚:
class aclass():
def outer(self, uuidString):
def inner():
print(uuidString)
uuidString = 'new value'
return uuidString
return inner
a = aclass()
func = a.outer('a uuid')
val = func()
print(val)
inner()
中的赋值导致 uuidString
是 inner()
的局部变量,因此在 print(uuidString)
被调用时未赋值,这导致 Python 提高 UnboundLocalError
.
您可以通过将变量传递给带有默认参数的函数来修复错误。更改 saveData
的定义以将 uuidString
作为默认参数传递,如:
def saveData(uuidString=uuidString):
将使它如您所愿地工作。