-2

编辑:为什么人们不赞成这篇文章?Python 开发者真的这么无能吗?这是一个合理的问题,而不是在其他地方得到回答的问题。我寻找解决方案。我不是白痴。一个参数有一个值,另一个是未定义的,但如果你真的阅读了这篇文章,你会发现它们的范围似乎是相同的。

首先,我向您保证,这个问题与其他涉及错误消息的问题不同:

UnboundLocalError: local variable referenced before assignment closure method

当我查看这段代码时,似乎uuidString顶级方法的参数 ,getStockDataSaverFactory当方法返回其内部方法时,实际上应该在范围内saveData,作为一等函数对象......因为令我惊讶的是,参数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确实有价值,我将这个截图包括在内:

带断点的 PyCharm 屏幕截图

请注意,在变量监视窗口中,uuidString未定义,但ticker具有字符串值“A”。

Python(或 Python 3)是否有一些独特的东西导致了这种行为?

4

1 回答 1

3

问题是您在self.getMethodThatProvidesFullFilePathNameForPricesCsvFromUUIDAndTickerName分配给它之前在调用中引用了 uuidString。赋值使其在最内层函数的范围内是本地的,因此,当您引用它时,它是未赋值的。

范围规则的完整描述由:https ://stackoverflow.com/a/292502/7517724 提供

这个更简单的示例重现了您的错误以使问题更加清晰:

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)

in的赋值inner()导致. uuidString_inner()print(uuidString)UnboundLocalError

您可以通过使用默认参数将变量传递给您的函数来修复错误。更改要作为默认参数saveData传递的定义,如下所示:uuidString

def saveData(uuidString=uuidString):

将使其按您的预期工作。

于 2017-12-31T03:51:30.787 回答