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

变量的作用域:也可以称为命名空间,即变量可以使用的范围。程序的变量并不是在所有的位置都能使用的,访问的权限决定于变量在哪里赋值(定义)的。只有当变量在模块,类,函数中定义的时候,才会有作用域的概念。if分支结构,for-else,while,for遍历循环结构,try-except(-else)\try-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 用户代码生成的警告

原文地址:https://www.cnblogs.com/yulianggo/p/9201681.html

时间: 2024-11-09 03:13:36

python0.10-----变量作用域和异常的相关文章

2015/9/19 Python基础(15):变量作用域及生成器

变量作用域标识符的作用域是定义为其声明的可应用范围,或者即是我们所说的变量可见性.也就是,我们可以在程序的那个部分去访问一个制定的标识符.全局变量与局部变量定义在函数内的变量有局部作用域,在一个模块中最高级别的变量有全局作用域.全局变量的一个特征是除非被删除掉,否则它们将存活到脚本运行结束,且对于所有的函数,他们的值都是可以被访问的,然而局部变量,就像它们存放的栈,暂时地存在,仅仅只依赖于定义它们的函数现阶段是否处于活动.当一个函数调用出现时,其局部变量就进入声明它们的作用域.在那一刻,一个新的

2015/9/19 Python基础(14):变量作用域及生成器

变量作用域标识符的作用域是定义为其声明的可应用范围,或者即是我们所说的变量可见性.也就是,我们可以在程序的那个部分去访问一个制定的标识符.全局变量与局部变量定义在函数内的变量有局部作用域,在一个模块中最高级别的变量有全局作用域.全局变量的一个特征是除非被删除掉,否则它们将存活到脚本运行结束,且对于所有的函数,他们的值都是可以被访问的,然而局部变量,就像它们存放的栈,暂时地存在,仅仅只依赖于定义它们的函数现阶段是否处于活动.当一个函数调用出现时,其局部变量就进入声明它们的作用域.在那一刻,一个新的

39 py函数作用域递归函数 变量作用域局部函数 使用lambda

第十课:函数作用域 // python 中的嵌套函数 在一个函数中再定义一个函数 # 小结 : # 函数作用域:因为:python是动态语言,定义变量的时候是不需要指定变量类型的,这样的话,我们在使用或者定义变量的时候作用域会分不清 # 如果在函数中定义一个变量,而且变量名和该函数上一级的作用域中的变量名相同 # 那么在该函数使用该变量时,就会使用局部变量 # 如果在函数中使用一个变量,但该变量在函数中并没有定义,那么会到该函数上一层的作用域去寻找该变量,如果还没有找到,会继续到上一层作用域去寻

Python 变量作用域 LEGB

回顾 - Decorator 前篇有讲到了, 闭包和装饰器的概念. 闭包就是, 函数内部嵌套函数. 而 装饰器只是闭包的特殊场景而已, 特殊在如果外函数的参数是指向一个, 用来被装饰的函数地址时(不一定是地址哈, 随意就好) , 就有了 "@xxx" 这样的写法, 还是蛮有意思的. 装饰器的作用是 在不改变原函数的代码前提下, 额外给原函数填写新功能. 写法上来看, 还是比较简洁优雅的. 装饰器的通俗写法 # 装饰器的通用写法 def out(func): def inner(*arg

第 10 章 文件和异常

至此,我们掌握了编写组织有序而易于使用的程序所需的基本技能,该考虑让程序目标更明确,用途更大了.在本章中,我们将学习处理文件,让程序能够快速地分析大量的数据:我们将学习错误处理,避免程序在面对意外情形时崩溃:我们将学习异常,它们是Python创建的特殊对象,用于管理程序运行时出现的错误:我们还将学习模块json,它让我们能够保存用户数据,以免在程序停止运行后丢失. 学习处理文件和保存数据可以让我们的程序使用起来更容易:用户将能够选择输入什么样的数据,以及在什么时候输入:用户使用我们的程序做一些工

Sass学习笔记 -- 变量及变量作用域历史遗留问题

sass有两种后缀名文件: 一种后缀名为sass,写选择器时不能使用大括号和分号 一种后缀名为scss,使用大括号和分号 //后缀名为sass的语法,不能出现大括号和分号 $highlight-color: #abcdef .selected   border: 1px $highlight-color solid    //后缀名为scss的语法,跟css一样,需要大括号和分号 $highlight-color: #abcdef; .selected{   border:1px solid $

OC点语法和变量作用域

OC点语法和变量作用域 一.点语法 (一)认识点语法 声明一个Person类: 1 #import <Foundation/Foundation.h> 2 3 @interface Person : NSObject 4 { 5 int _age;//默认为@protected 6 } 7 8 - (void)setAge:(int)age; 9 - (int)age; 10 11 @end Person类的实现: 1 #import "Person.h" 2 3 @imp

C# 变量作用域

变量作用域是一个让很多初学者很容易混淆的一个概念. 变量的作用域是可以访问该变量的代码区域.一般情况下,确定作用域遵循以下规则: 只要类在某个作用域中,其字段也(也称成员变量)也在该作用域内. 局部变量存在于表示声明该变量的块语句或方法结束的右花括号({})之前的作用域内.(请认真解读读透这句话) 在for.while或类似语句中声明的局部变量存在于该循环体内. 局部变量的作用域冲突 大型程序在不同部分的变量使用相同的变量名很常见.只要变量的作用域是程序的不同部分,就不会有问题,就不会产生多义性

C语言-数据类型、常量、变量、变量作用域、printf、scanf函数

4.数据类型介绍 数据:文本数据.音频.视频.图像.数字 C语言中有5大数据类型:基本类型.构造类型.空类型.指针类型.自定义类型 基本数据类型: 整型    长整型long int    整型int(4)    端整型short int 实型    单精度float(4)    双精度 double(8) 字符型   char(1) 内存: 1> 内存分配:4G存储大小:4*1024*1024*1024Byte; 内存的基本单元为一个字节(就是8bit) 2> 内存区域:栈 (存放局部变量)