针对前一篇文章,有一个同事问我说echo server代码中58行变量client_address貌似没有在其作用域中被调用,为此我特新写一篇博客把Python中针对局部变量的这一特性简单说一下。
首先需要澄清的是,在echo server的代码中,在处理select函数的返回值readable时,必定是先接受来自Client的连接,然后才能Receive来自Client的数据,因此socket.accept()所在的逻辑一定会先运行,socket.recv(1024)所在的逻辑一定后运行。
Python中变量作用域和C/C++和Java有一些不同,下面我们通过一个小例子来说明,类似例子我并没有在任何一本书中看到过,希望对于初学者有帮助。
例子分成两小段代码,你可以分别运行,观察if条件内的局部变量
temp.
(1)
data = [2,1,0]
for i in data:
temp = i
if i>0:
print "========="
print 'i=',i
else:
print "---------"
print 'i=',i
print 'temp=',
temp
Output:
=========
i= 2
=========
i= 1
---------
i= 0
temp= 0
(2)
data = [2,1,0]
for i in data:
if i>0:
temp = i
print "========="
print 'i=',i
else:
print "---------"
print 'i=',i
print 'temp=',
temp
Output:
=========
i= 2
=========
i= 1
---------
i= 0
temp= 1
通过运行结果不知道你是否已经明白我要说的意思。对于C/C++这类语言来说,if{...}else{...}中定义的变量只能作用于其对应的逻辑中,并不具有从if的作用域中传递到else的作用域中的特性。
当然,需要特别说明的是temp在else逻辑作用域中有效的前提是必须在进入该逻辑之前必须运行过 temp=i,即必须先运行if的逻辑。否则程序就将crash。因此这种编码风格实际上是不安全的,必须保证变量定义所在的逻辑先被运行。其实我也不清楚为啥Guido Van Rossum这样设计,背后的原因也许和Python独特面向对象属性觉得的吧,具体原因我后续在具体研究,这里仅仅点到为止。
如果你用C/C++写同样的代码:
for(int i =2; i>=0; --i)
{
if(i>0)
{
int temp = i;
cout<<"i="<<i<<endl;
}
else
{
cout<<"temp="<<temp<<endl;
}
}
编译错误一定是:
error: 'temp' : undeclared identifier
因此,在使用Python的时候,很多同学都是根据以往的经验采用C/C++的编码风格编写Python代码,很多时候不但没有有效利用Python的优势特性,而且容易出错。当然针对这一特性,我们最好尽量不要使用,以免引起理解误差。