【问题标题】:Python 2.7 Local Variables are acting like global variablesPython 2.7 局部变量的作用类似于全局变量
【发布时间】:2014-09-24 04:13:46
【问题描述】:

我有 2 个函数包含在 2 个单独的文件中。

这些函数是相似的,并且它们中的局部变量使用相同的名称。传递给每个函数的参数“eachtickerlist”也是相同的。 eachtickerlist 是一个看起来像这样的列表的列表

[[ticker,price,year,month,day,seconds from epoch],[ticker,price,year.........

由于某种原因,每个函数“amlist”中的局部变量在执行函数 2 时会保留来自函数 1 的数据,即使它在第二个函数中重新初始化并且即使它是一个局部变量。我知道这一点是因为当我在函数 2 的末尾打印出“amlist”以对其进行测试时,字符串“未定义”、“向上”或“向下”被列出了 2 次。如果我不在主程序中调用函数 1,则不会发生这种情况,这证明函数 1 中发生的事情正在影响函数 2……我完全不明白。

在我的主程序中,我调用每个函数,如下所示:

eachtickerlist=sorted(eachtickerlist,key=operator.itemgetter(6)) #This is the argument to be passed     

upsvsdownsresult=upsvsdowns.upsvsdowns(eachtickerlist) #This sends the argument to the first function and stores the return value for use later

swingsresult=swings.swings(eachtickerlist) #This sends the same argument to the second function and stores the return value for use later

这里是功能1:

def upsvsdowns(eachtickerlist):

amlist=[]
for thing in eachtickerlist:
    if (thing[5]=='8'):
        amlist.append(thing)


    else:
        pass


try:
    amlist[0].append('undefined')
    length=len(amlist)


    for x in range(1,length):
        price=float(amlist[x][1])
        yesterdaysprice=float(amlist[(x-1)][1])

        if ((price-yesterdaysprice)>0):
            amlist[x].append('up')

        else:
            amlist[x].append('down')

    upcount=0
    totalcount=0
    for y in amlist:
        if (y[7]=='up'):
            upcount=upcount+1
            totalcount=totalcount+1

        else:
            totalcount=totalcount+1

    percentage=round(float(upcount)/float(totalcount),3)
    returnlist=[amlist[0][0],str(percentage)]

    return (returnlist)

except (IndexError):
    returnlist=[eachtickerlist[0][0],'No Data']
    return (return list)

这里是功能2:

def swings(eachtickerlist):

amlist=[]
for thing in eachtickerlist:
    if (thing[5]=='8'):
        amlist.append(thing)


    else:
        pass


try:
    amlist[0].append('undefined')
    length=len(amlist)


    for x in range(1,length):
        price=float(amlist[x][1])
        yesterdaysprice=float(amlist[(x-1)][1])

        if ((price-yesterdaysprice)>0):
            amlist[x].append('up')

        else:
            amlist[x].append('down')

    upcount=0
    downcount=0
    ups=[]
    downs=[]

    print amlist

    for y in amlist:
        if (y[7]=='up'):

            if (downcount!=0):
                downs.append(downcount)

            else:
                pass

            downcount=0
            upcount=upcount+1


        elif (y[7]=='down'):

            if (upcount!=0):
                ups.append(upcount)
            else:
                pass
            upcount=0
            downcount=downcount+1

        if (upcount!=0):
            ups.append(upcount)
        elif (downcount!=0):
            downs.append(downcount)
        else:
            pass
    #print ups
    #print downs


    try:
        averageup=round(sum(ups)/float(len(ups)),3)

    except(ZeroDivisionError):
        averageup=round(0.0,3)

    try:
        averagedown=round(sum(downs)/float(len(downs)),3)

    except(ZeroDivisionError):
        averagedown=round(0.0,3)


    returnlist=[amlist[0][0],str(averageup),str(averagedown)]

    return (returnlist)

except (IndexError):
    returnlist=[eachtickerlist[0][0],'No Data']
    return (return list)

这是第二个函数中 print 语句的输出。请注意每个列表中的 2 个未定义的 up 和 down。

['AAIT', '35.09', '2014', '7', '28', '8', '2409480.0', 'undefined', 'undefined'], ['AAIT', '35.21', '2014', '7', '29', '8', '2494662.0', 'up', 'up'], ['AAIT', '40', '2014', '7', '29', '8', '2494662.5', 'up', 'up'], ['AAIT', '42.3', '2014', '7', '29', '8', '2494663.0', 'up', 'up']]

任何帮助将不胜感激。

-布兰登

【问题讨论】:

  • 你说你用upsvsdowns.upsvsdowns 调用方法,但声明说它们是全局函数。这些方法是类还是其他数据结构的成员?
  • 欢迎来到 Stack Overflow!很高兴您包含失败的实际代码(而不是一些伪代码或不准确的描述。)有两件事可以使您的问题更好(并且更有可能引出高质量的答案)。首先,将您的程序缩减为仍然显示错误的最小实际程序。将该简短而完整的程序复制粘贴到您的问题中。其次,要特别注意你的缩进。将您的程序粘贴到 SO 中似乎破坏了它的缩进。再次欢迎!
  • 在主程序中,我导入 upsvsdowns.py 和 swings.py 这两个文件,它们只包含各自的功能。我不确定这是否能回答您的问题?
  • 下次我会少上传一些代码。对缩进感到抱歉。

标签: python variables python-2.7 global local


【解决方案1】:

不,局部变量不在函数之间共享。局部变量完全存在于一个函数中。但与其他编程语言不同,变量不是对象。它们只是已知对象的名称。另一方面,对象可以在被调用函数返回后很长一段时间内持续存在。

让我们考虑一个更简单的程序:

def func1(arg):
    arg.append('Hello from Func1!')
    print arg

def func2(arg):
    arg.append(2)
    print arg


main_list = [9,8,7]

func1(main_list)
func2(main_list)

这个程序的输出是:

[9, 8, 7, 'Hello from Func1!']
[9, 8, 7, 'Hello from Func1!', 2]

如您所见,func2 中的局部变量arg 中包含来自func1 的消息!但是那个只被添加到func1中的局部变量中。那么,这是否意味着名称arg 在一种情况下与名称arg 在另一种情况下存在某种关联?

没有。

在 Python 中,与 C 或 C++ 不同,变量不是按值传递给子例程的。相反,被调用者中的参数绑定到调用者中存在的同一对象。这有点像其他编程语言中的传递引用。

考虑一下:

def func(i):
   print id(i)

a="Some string"
print id(a)
func(a)

在这个例子中,我们打印出一个对象的id()。每个对象都有一个id(),并且没有两个对象同时具有相同的 id。

这个例子在我的电脑上的输出是:

140601888512880
140601888512880

如您所见,调用者中的a 和被调用者中的i 是同一个对象。一个不是另一个的副本,它们是完全相同的对象。

这一切与你的程序有什么关系?

在您的程序中,您修改传入的列表。由于没有复制,您实际上是在修改原始列表。当原始列表传递给下一个函数时,它会收到您修改后的列表。

下面是修改upsvsdowns中传入的列表对象的方法:

amlist.append(thing) # This doesn't modify the original object, but it does
                     # set up the modification. After this line completes,
                     # amlist[i] and eachtickerlist[j] are both references
                     # to the same object (for some value of i and j).

amlist[0].append('undefined') # This statement modifies the object referenced by
                              # amlist[0]. Since that object is also referenced by
                              # eachtickerlist[j] (for some j), you have now
                              # stored the word 'undefined' "inside" the object
                              # referenced by eachtickerlist. Since that object
                              # is also referenced by the caller's eachtickerlist,
                              # the change is permanent and globally visible

如需更清晰的解释,请参阅the docs,尤其是第 3.1 节。

【讨论】:

  • 所以你的意思是我应该做一个传入列表的干净副本,然后将复制的列表用于我在函数中的所有工作?我会试一试。感谢您的帮助。
  • 我刚刚尝试复制到函数顶部的干净列表,结果相同。我仍然不清楚如何断开与传入列表的连接。
  • 我使用 deepcopy() 让它工作,这里讨论过 stackoverflow.com/questions/2322068/…
  • @BPoy - 正如您所发现的,这取决于您如何进行复制。 "a=b" 不会复制 - 它只是创建另一个名称。对于列表 "a=b[:]" 会将 b 的内容复制到 a 中(因此您可以在不更改 b 的情况下更改 a - 尽管这仅适用于非嵌套列表。
  • @BPoy - 不,我不是这么说的。我没有提供任何建议或处方。我只是试图解释你所看到的。
猜你喜欢
  • 2019-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-19
  • 2018-10-26
  • 2022-11-16
  • 2017-11-08
  • 1970-01-01
相关资源
最近更新 更多