python0.10-----变量作用域和异常

Posted 一只鱼鱼鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python0.10-----变量作用域和异常相关的知识,希望对你有一定的参考价值。

变量的作用域:也可以称为命名空间,即变量可以使用的范围。程序的变量并不是在所有的位置都能使用的,访问的权限决定于变量在哪里赋值(定义)的。只有当变量在模块,类,函数中定义的时候,才会有作用域的概念。if分支结构,for-else,while,for遍历循环结构,try-except(-else) ry-except-finally等关键字语句块不会产生作用域。

 

局部变量与局部作用域:

#定义函数

def discount(price,rate)

  final_price=price*rate

  return final_price

#调用函数

new_price=discount(price=10,rate=0.5)

print(final_price)

解读:当执行discount(price=10,rate=0.5)这个函数调用语句时,系统就会在栈空间里开辟内存,定以变量price,rate,final_price并给它们赋值。调用结束后,也就是discount(price=10,rate=0.5)语句结束时,变量price,rate,final_price会被自动清除,因此上面print(final_price)这个访问局部变量的语句会引发异常NameError:name ‘final_price’ is not defined。可以把price,rate,final_price变量作用的范围成为局部作用域(local)。

 

全局变量与全局作用域:

 

def func():       

 

  b=2     #当给b赋值时,由于屏蔽机制,在栈空间中创建局部变量b。

 

  print(b)  #在函数中访问局部变量,大小为2。

 

b=1  #这里的b是全局变量 ,大小为1。

 

func()  #调用函数

 

解读:全局变量b的作用范围是整个模块的代码块(称为全局作用域),在局部函数中可以随意访问全局变量b。在函数内试图修改全局变量b时,python使用屏蔽机制,函数会屏蔽全局变量b,在栈区域定义一个名叫b的局部变量,两个变量虽然名字相同,但是它们在内存中的位置不一样,它们不一样!!!

注意:可以使用global关键字在函数内部修改或者创建全局变量。但是建议不要这么做,因为它会使程序可读性变差,程序很难维护,做为函数尽自己的本分就好。例如:

def func():

  global b  #屏蔽机制失效,可以在函数内操纵全局变量

  b=2

print(b)  #在函数中访问全局变量

b=1  #全局变量

print(b)  #此时b的值还是1

func()  #调用函数

print(b)  #此时b的值被func函数改成2了

 

外部变量与嵌套作用域:

在解释这个概念前先引入闭包的概念:

闭包(closure):python中闭包从表现形式上定义为:如果在一个内部函数里,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就会被认为是闭包(closure)。

外部变量和嵌套作用域:

def FunX(x):

  def FunY(y):

    return x*y

  return FunY

解读:对于FunY来说,FunX就是外部作用域,x是外部作用域的变量,FunY是内部函数,并且FunY函数引用了这个变量x。符合这两个条件,那么可称内部函数FunY就是一个闭包。事实上,这里说的外部作用于就是嵌套作用域(enclosing)。全局范围内,不能调用FunY。局部变量作用于外部变量,跟之前局部变量作用于全局变量一样。局部变量可以访问外部变量,但不能直接修改外部变量,若修改,则屏蔽机制生效,在闭包中创建局部变量,并且不影响外部变量。

def FunX(x):  #x为外部变量

  def FunY(y): #y为局部变量,FunY为闭包

    x=1  #当给x赋值时,由于屏蔽机制,在栈空间中创建局部变量x,不影响外部变量x。

    return x*y

  return FunY

 

若执意修改,采用nonlocal的关键字进行修改。但是建议不要这么做,因为它会使程序可读性变差,程序很难维护,做为闭包尽自己的本分就好。

例子:

def FunX(x):  #x为外部变量

  def FunY(y):  #y为局部变量,FunY函数为闭包

    nonlocal x #声明操作的x为外部变量

    x=1  #现在外部变量x的值为1。

    return x*y

  return FunY

 

 

 

异常处理:

一般来说编码错误叫做bug。而不是由于编码错误产生,而是由于用户操作失误,程序运行会报错,这叫做异常。程序可预测的错误,例如存储空间不足,网络错误,也叫做异常。若程序出现问题,希望程序越过错误,不要停止执行。此时可以用异常处理技术。

异常处理的结构有2种:分为try-execpt(-else),try-except-finally

 

try-execpt(-else):

格式:

try:

  语句t

except 异常码1 as e:

  语句1

except 异常码2 as e:

  语句2

………………

except 异常码n as e:

  语句n

else:   #else语句可有可无

  语句e

 

逻辑:

1:系统检测try语句块中的语句t是否有异常,而异常的类型是多种多样的,不同的异常对应不同的异常码,发生异常时,except捕获对应的异常码,执行相应的异常处理语句。

2:若系统检测try语句块中的语句t出现异常,但是没有捕获相应的异常码,那么异常会被提交到上一层的try语句,或者到程序的最上层。

3:若系统检测try语句块中的语句t没有出现异常,则执行else分支下的语句e。

4:详细的错误原因会放到e中,e为字符串类型。

 

善变的try-execpt(-else)之一:

#使用except而不使用任何的异常类型,这个很常用。因为查异常类型很麻烦,而且也很难处理。

try:

  语句t

except :

  语句e

 

善变的try-execpt(-else)之二:

#使用except带着多种异常

try:

  语句t

except (NameError,ZeroDivisionError):

  语句e

解释:若出现了NameError,ZeroDivisionError,都会在except里面处理。

 

 

try-except-finally:

格式:

try:

  语句t

except 异常码1 as e:

  语句1

except 异常码2 as e:

  语句2

………………

except 异常码n as e:

  语句n

finally:

  语句e

#不管语句t有没有出错,语句e必定执行。

用处:在文件处理中,应该使用finally,因为文件读写的过程中,不管读写过程是否出错,文件的关闭必须要执行,因此这里非常适合finally来使用。

 

异常机制还需注意:

#1 .异常其实是class类,所有的错误都继承自BaseExeception。所以在捕获的时候,它捕获了该类型的异常,还把子类的异常一网打尽。

#2.若内存存满了,需要在异常处理里面释放一部分内存。

#3.跨多层调用,main()调用func2,func2调用func1,只要调用main()时补获了异常,就可以处理,程序可以不停止运行。

例如:
#定义

def func1(num):

  print(1/num)

def func2(num):

  func1(num)

def main():

  func2(0)

 

try:

  main()   #调用

except ZeroDivision as e:

  语句e

 

断言(assert):

格式:

assert 表达式,’异常提示’ 

解释:当表达式为真时,不会出现异常提示。当表达式为假时,会抛出assert异常,异常类型后面可以跟随自己编写的‘异常提示’,‘异常提示’可要可不要。当然assert抛出的异常也是可以捕获的。但是assert一定要在try里面使用,并且表达式的格式一定要正确,异常提示会赋值给e。

例如:

try:

  assert 2==1,‘我好快乐‘

except BaseException as e:

  print(‘发生错误‘,e)

else:

  print(‘没有发生错误‘)

#输出:

发生错误 我好快乐

 

 

标准异常名称 描述

BaseException 所有异常的基类

SystemExit 解释器请求退出

KeyboardInterrupt 用户中断执行(通常是输入^C)

Exception 常规错误的基类

StopIteration 迭代器没有更多的值

GeneratorExit 生成器(generator)发生异常来通知退出

SystemExit Python 解释器请求退出

StandardError 所有的内建标准异常的基类

ArithmeticError 所有数值计算错误的基类

FloatingPointError 浮点计算错误

OverflowError 数值运算超出最大限制

ZeroDivisionError 除(或取模)零 (所有数据类型)

AssertionError 断言语句失败

AttributeError 对象没有这个属性

EOFError 没有内建输入,到达EOF 标记

EnvironmentError 操作系统错误的基类

IOError 输入/输出操作失败

OSError 操作系统错误

WindowsError 系统调用失败

ImportError 导入模块/对象失败

KeyboardInterrupt 用户中断执行(通常是输入^C)

LookupError 无效数据查询的基类

IndexError 序列中没有没有此索引(index)

KeyError 映射中没有这个键

MemoryError 内存溢出错误(对于Python 解释器不是致命的)

NameError 未声明/初始化对象 (没有属性)

UnboundLocalError 访问未初始化的本地变量

ReferenceError 弱引用(Weak reference)试图访问已经垃圾回收了的对象

RuntimeError 一般的运行时错误

NotImplementedError 尚未实现的方法

SyntaxError Python 语法错误

IndentationError 缩进错误

TabError Tab 和空格混用

SystemError 一般的解释器系统错误

TypeError 对类型无效的操作

ValueError 传入无效的参数

UnicodeError Unicode 相关的错误

UnicodeDecodeError Unicode 解码时的错误

UnicodeEncodeError Unicode 编码时错误

UnicodeTranslateError Unicode 转换时错误

Warning 警告的基类

DeprecationWarning 关于被弃用的特征的警告

FutureWarning 关于构造将来语义会有改变的警告

OverflowWarning 旧的关于自动提升为长整型(long)的警告

PendingDeprecationWarning 关于特性将会被废弃的警告

RuntimeWarning 可疑的运行时行为(runtime behavior)的警告

SyntaxWarning 可疑的语法的警告

UserWarning 用户代码生成的警告


以上是关于python0.10-----变量作用域和异常的主要内容,如果未能解决你的问题,请参考以下文章

C语言变量的作用域和生存期问题

JS块级作用域和私有变量实例分析

python 变量作用域和列表

js 静态作用域和动态作用域

名称域和共享变量

php变量的作用域和生存期