Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
内部/嵌套方法关闭的Python3参数超出范围并触发UnboundLocalError_Python_Python 3.x_Lambda_Closures_First Class Functions - Fatal编程技术网

内部/嵌套方法关闭的Python3参数超出范围并触发UnboundLocalError

内部/嵌套方法关闭的Python3参数超出范围并触发UnboundLocalError,python,python-3.x,lambda,closures,first-class-functions,Python,Python 3.x,Lambda,Closures,First Class Functions,编辑:为什么人们对这篇文章投反对票?Python开发人员真的如此无能吗?这是一个合理的问题,在其他地方没有得到回答。我在寻找解决办法。我不是白痴。一个参数有一个值,另一个参数没有定义,但是如果你真的读了这篇文章,你会发现这两个参数的作用域是相等的 首先,我向您保证,此问题与涉及错误消息的其他问题不同: UnboundLocalError:赋值结束方法之前引用的局部变量 在我查看这段代码时,顶级方法的参数getStockDataSaverFactory作为一级函数对象返回其内部方法saveData

编辑:为什么人们对这篇文章投反对票?Python开发人员真的如此无能吗?这是一个合理的问题,在其他地方没有得到回答。我在寻找解决办法。我不是白痴。一个参数有一个值,另一个参数没有定义,但是如果你真的读了这篇文章,你会发现这两个参数的作用域是相等的

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

UnboundLocalError:赋值结束方法之前引用的局部变量

在我查看这段代码时,顶级方法的参数
getStockDataSaverFactory
作为一级函数对象返回其内部方法
saveData
时,它的参数
uuidString
,实际上应该在范围内。。。因为令我惊讶的是,参数
tickerName
在范围内,并且在调用
saveData()
方法时(例如,通过测试方法
testDataProcessing\u getSaverMethodFactory
),参数确实具有值'GOOG',因此我们实际上可以看到,当调用方法
getDataMethodFactory(…)时,它具有实际值
与
uuiString
不同,调用了

为了让事情变得更加明显,我添加了以下几行:

localUuidString=uuidString

experimentUuidString=localUuidString

当方法被断点检查时,显示参数
uuistring
具有可用值

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)
为了明确说明
uuistring
没有值,但是
ticker
确实有值,我添加了以下屏幕截图:

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


Python(或Python 3)是否有独特之处导致了这种行为?

问题在于,在分配给它之前,在调用
self.getMethod时引用了UUIString,该方法为PricescsvFromUUIDANDtickerName
提供完整的文件路径名。赋值使它位于最内层函数的作用域的局部,因此,在引用它时它是未赋值的

范围界定规则的完整说明如下:

这个简单的例子再现了您的错误,使问题更加清楚:

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()
中的赋值会导致
uuiString
inner()
的本地赋值,因此在调用
print(uuiString)
时会取消赋值,这会导致Python引发
unbundLocalError

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

def saveData(uuidString=uuidString):

将使其按预期工作。

您可以发布完整的堆栈跟踪吗?这里有点不对劲。在实际应用中,您所展示的并没有什么问题。请参见此-定义并返回的函数保持对其定义的作用域的访问-除非发生了其他未显示的情况。这是创建对象的有趣方法
dataProcessing=dataProcessing.dataProcessing()
?为什么它不仅仅是
dataProcessing=dataProcessing()
?看在上帝的份上,缩短函数名吧。。。。!为什么函数返回其他函数?调用这些函数,然后立即调用它们返回的函数。这看起来真的太复杂了。@NedBatchelder您有没有在函数式编程中使用过curry,或者在Javascript/node.js中使用过promises?还是C#中的通用lambdas?对于S.O.的例子,我实际上保持了简单。在实践中,我将获取一个字符串列表,然后我可以管道化一组方法生成器函数,这些函数的功能类似于decorator(作为方法组合的一种形式)。想想string->methodThatGetsData->methodThatSavesRetrievedData->methodThatTransformsSavedData->MethodThatThatSortsTransformedData->等等。在实现时,您只需要提供一个方法生产者列表来设置管道。好的,您是:)我发现第二个答案也非常有用。它显示了问题所在的确切场景。第7点和第8点。为什么这不是tickerName的问题?@devinbost-这不是问题,因为您没有在嵌套函数中为
tickerName
赋值。正如我在回答中所解释的,赋值使其成为内部函数作用域的局部。如果不赋值,它将在外部作用域中搜索变量。@devinbost-可能您假设Python一次只解释一行代码,因此它不应该知道赋值。运行脚本时,Python读取整个脚本并将其编译成字节码,然后执行。在编译阶段,它看到
uuidString
的赋值,并确定变量是本地变量。