【经验记录】Python的函数中定义的变量,和函数内的Try内部的变量,不是同一个变量
先贴出代码:
<p>def downloadPic(picUrl, picFileToSave) :</p><p> isDownOK = False # 此处函数内,先赋值</p><p> downloading_pic = '' # 位置1</p><p> #---------------------------------------------------------------------------<br /> def reportHook(copiedBlocks, blockSize, totalFileSize) :<br /> global downloading_pic # 此处用global引用改变量,是正常的可以理解的:函数内部使用外部变量,需要用global引用</p><p> print 'downloading_pic=',downloading_pic # 位置3</p><p> return<br /> #---------------------------------------------------------------------------</p><p> try :<br /> <strong><font color="#ff0000">global downloading_pic </font></strong>#此处必须用global引用downloading_pic,否则位置1处的downloading_pic,和此处的变量,就不是同一个变量,这样会导致位置2(下面一行)的变量赋值,变成try内部的函数赋值,而不会改变位置1的downloading_pic的值,从而也就导致无法被位置3所获得<br /> downloading_pic = picUrl # 位置2</p><p> urllib.urlretrieve(picUrl, picFileToSave, reportHook)</p><p> isDownOK = True #此处测试try体内的赋值,看看对于isDownOK不加global的话,是否可以改变其值<br /> except :<br /> logging.warning("Error while downloading %s", picUrl)</p><p> print 'before return isDownOK=',isDownOK #虽然try体内不加global,但是这里的isDownOK结果却又是True</p><p> return </p>
对于上述代码,注释中已经解释了,
try体内的downloading_pic,必须用global,否则是无法改变位置1的函数体内的变量的。
所以,结果证实,try内,这就看起来相当于一个函数,函数内部使用变量,必须要用global引用才行。
如果这个是真的,那么此语言设计的,真的很变态。。。
但是,可以从上面来看,对于isDownOK的结果测试,却又发现,try体内的变量,如果是函数体内的,正常又是可以不加global而使用的。
【结论】
一个函数内包含一个内置函数的话,如果原先函数体内的变量,被内置调用,那么此时,除了正常的内置函数内使用该变量需要加global之外,原先函数内的try体内,想要使用该变量的话,也要加global。
<br />【后记】
很奇怪的是,后来的某次执行脚本,对于上述同样代码来说,又提示一个warning:
D:tmpWordPressOthersto_wphi-baidu-mover_v2hi-baidu-mover_v2011-12-23-office.py:579: SyntaxWarning: name ‘downloading_pic’ is assigned to before global declaration<br /> global downloading_pic |
然后就去注释掉了对应的global:
<p>def downloadPic(picUrl, picFileToSave) :</p><p> downloading_pic = ''</p><p> #---------------------------------------------------------------------------<br /> # note: totalFileSize -> may be -1 on older FTP servers which do not return a file size in response to a retrieval request<br /> def reportHook(copiedBlocks, blockSize, totalFileSize) :<br /> if copiedBlocks == 0 : # 1st call : once on establishment of the network connection<br /> logging.debug('Begin to download %s, total size=%d', downloading_pic, totalFileSize)<br /> else : # rest call : once after each block read thereafter<br /> logging.debug('Downloaded bytes: %d', blockSize * copiedBlocks)<br /> return<br /> #---------------------------------------------------------------------------</p><p> try :<br /> downloading_pic = picUrl</p><p> urllib.urlretrieve(picUrl, picFileToSave, reportHook)<br /> </p>
<br />
结果代码也是可以正常执行的。