Python 2.7局部变量表现得像全局变量
我有两个函数,它们分别在两个不同的文件里。
这两个函数很相似,而且在它们内部使用了相同的局部变量名称。传入每个函数的参数'eachtickerlist'也是一样的。这个eachtickerlist是一个列表,里面包含了多个列表,长得像这样:
[[ticker,price,year,month,day,seconds from epoch],[ticker,price,year.........
但不知为什么,在执行第二个函数时,每个函数内部的局部变量'amlist'却保留了第一个函数的数据。尽管在第二个函数里'amlist'被重新初始化了,而且它是一个局部变量。我知道这一点是因为在第二个函数结束时打印'amlist',结果显示字符串'undefined'、'up'或'down'出现了两次。如果我在主程序中不调用第一个函数,这种情况就不会发生,这证明第一个函数里的事情影响了第二个函数……这让我完全搞不懂。
在我的主程序中,我像下面这样调用每个函数:
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
这是第一个函数:
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)
这是第二个函数:
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)
这是第二个函数中打印语句的输出。注意每个列表中都有两个'undefined'、'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']]
任何帮助都将不胜感激。
-Brandon
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
想要更清楚的解释,可以查看文档,特别是§3.1。