python3代码块

代码块可以使得一段python代码作为一个单元、一个整体执行。以下是 官方手册 的描述。
所以,有以下几种类型的代码块:

  1. 模块文件是一个代码块
  2. 函数体是一个代码块
  3. class的定义是一个代码块
  4. 交互式(python idle)的每一个命令行都是一个独立的代码块
  5. 脚本文件是一个代码块
  6. 脚本命令是一个代码块(python -c “xxx”)
  7. eval()和exec()中的内容也都有各自的代码块

代码块的作用是组织代码,同时意味着退出代码区块范围就退出了作用域范围。例如退出函数区块,就退出了函数的作用域,使得函数内的本地变量无法被函数的外界访问。

此外,python是解释性语言,读一行解释一行,这意味着每读一行就忘记前一行。但实际上更严格的说法是读一个代码块解释一个代码块,这意味着读代码块中的内容时,是暂时记住属于这个代码块中所读内容的,读完整个代码块后再以统筹的形式解释这个代码块。
先说明读一行解释一行的情况,也就是每一行都属于一个代码块,这个只能通过python的交互式工具idle工具来测试:

>>> x=2000
>>> y=2000
>>> x is y
False
>>> x=2000;y=2000
>>> x is y
True

理论上分号是语句的分隔符,并不会影响结果。但为什么第一个x is yFalse,而第二个x is yTrue
首先分析第一个x is y。由于交互式工具idle中每一个命令都是一个单独的语句块,这使得解释完x=2000后立刻就忘记了2000这个数值对象,同时忘记的还有x变量本身。然后再读取解释y=2000,因为不记得刚才解释的x=2000,所以会在内存中重新创建一个数值结构用来保存2000这个数值,然后用y指向它。换句话说,x和y所指向的2000在内存中是不同的数据对象,所以x is y为False
下面的x is y返回True:

>>> x=2000;y=2000
>>> x is y
True

因为python按行解释,一个命令是一个代码块。对于x=2000;y=2000,python首先读取这一整行,发现x和y的数值对象都是2000,于是做个简单优化,等价于x,y=2000,2000,这意味着它们属于一个代码块内,由于都是2000,所以只会在内存中创建一个数据对象,然后x和y都引用这个数据对象。所以,x is y返回True。
idle工具中每个命令都是独立的代码块,但是py文件却是一个完整的代码块,其内还可以嵌套其它代码块(如函数、exec()等)。所以,如果上面的分行赋值语句放在py文件中,得到的结果将是True。
例如:

x = 2000
y = 2000
print(x is y)   # True
def f1():
    z=2000
    z1=2000
    print(x is z)   # False
    print(z is z1)  # True
f1()

python先读取x=2000,并在内存中创建一个属于全局作用域的2000数据对象,再解释y=2000的时候,发现这个全局对象2000已经存在了(因为x和y同处于全局代码块内),所以不会再额外创建新的2000对象。这里反映出来的结果是"同一个代码块内,虽然仍然是读一行解释一行,但在退出这个代码块之前,不会忘记这个代码块中的内容,而且会统筹安排这个代码块"。
同理def f1()内的代码块,因为z是本地作用域的变量,更标准的是处于不同代码块内,所以会在本地作用域内存区创建新的数据对象2000,所以x is z返回False。根据前面的解释,z1 is z返回True。
再回顾python3作用域中例3:

x= 1
def func():
    print x
    x= 2
print func()

报错信息:

UnboundLocalError: local variable 'x' referenced before assignment

当执行到def语句的时候,因为def声明函数,函数体是一个代码块,所以按照代码块的方式读取属于这个代码块中的内容。首先读取print(x),但并不会直接解释,而是会记住它,并继续向下读取,于是读取x=4,这意味着x是一个本地变量。然后统筹安排整个代码块,将print(x)的x认为是本地变量而非全局变量。注意,直到def退出的时候都还没有进行x的赋值,而是记录了本地变量x,赋值操作是在函数调用的时候进行的。当调用函数func()的时候,发现print(x)中的x是本地变量,但因为还没有赋值,所以报错。
但是再看下面的,为什么又返回True?

>>> x=256
>>> y=256
>>> x is y
True

因为Python在启动的时候就在内存中预先为常用的较小整数值(-5到256)创建好了对象,因为它们使用的非常频繁(有些在python的内部已经使用了)。所以,对于这个范围内的整数,都是直接引用,不会再在内存中额外创建新的数值对象,所以x is y总是返回true。甚至,这些小值整数可以跨作用域:

x = 3 
def f1():
    y=3
    print(x is y)   # True
f1()

原文链接:https://www.cnblogs.com/f-ck-need-u/asp/9925021.html#%E4%BB%A3%E7%A0%81%E5%9D%97%E7%BB%86%E8%BF%B0%E5%BF%85%E7%9C%8B

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值