python自学第33天 python之小白太玄经 2019.12.25

8.4.抛出异常

raise语句允许程序员强制抛出一个指定的异常。·例如:

在这里插入图片描述

要抛出的异常由raise的唯一参数标识。它必须是一个异常实例或异常类(继承自Exception的类)。

如果你需要明确一个异常是否抛出,但不想处理它,raise语句可以让你很简单的重新抛出该异常:
在这里插入图片描述

8.5.用户自定义异常

在程序中可以通过创建新的异常类型来命名自己的异常(python类的内容参见类)。
异常类通常应该直接或间接的从Exception类派生。例如:

在这里插入图片描述
在这个例子中,Exception默认是__init__()被覆盖。
新的方式简单的创建value属性。这就替代了原来创建args属性的方式。

异常类中可以定义任何其他类中可以定义的东西,但通常为了保持简单,只在其中加入几个属性信息,以供异常处理句柄提前,如果一个新创建的模块中需要抛出几种不同的错误时,一个通常的做法是为该模块定义一个异常基类,然后针对不同的错误类型派生出对应异常子类:

在这里插入图片描述

与标准异常相似,大多数异常的命名都以Error结尾
很多标准模块中都定义了自己的异常,详见类一章。

8.6.定义清理行为

try语句还有另一个可选的子句,目的在于定义在任何情况下都一定要执行的功能。
示例:
在这里插入图片描述

9章 类

python的类机制通过最小的新语法和语法在语言中实现了类。(它是C++或者Modula-3语言中类机制的混合)。
就像模块一样,python的类并没有在用户和定义之间设立绝对的屏障,而是依赖于用户不去“强行闯入定义”的优雅。
类的大多数重要特性都被完整的保留下来
类继承机制允许多重继承,派生类可以覆盖基类中的任何方法或类,可以用相同的方法名称调用基类的方法。
对象可以包含任意数量的私有数据。

9.1.术语相关

对象具有特性,并且多个名称(在多个作用域中),可以绑定在同一个对象上。其他语言称为别名。
在python的第一印象中这通常会被忽略,并且当处理不可变基础类型(数字,字符串,元组)时可以被放心的忽略。但是,在调用列表,字典这类可变对象,或者大多数程序外补类型(文件,窗体等)描述实体时,别名对python代码的语义便具有(有意而为)影响,这通常有助于程序的优化,因为在眸方便别名表现的就像指针,例如:
你可以轻易的传递一个对象,因为通过继承只是传递一个指针。并且如果一个方法修改了一个作为参数传递的对象,调用者可以接受这一变化–这消除了两种不同的参数传递机制的需要,像pascal语言。

9.2.python作用域和命名空间

python作用域的规则。 类的定义非常的巧妙的运用了命名空间,要完全理解接下来的知识,需要先理解作用域和命名空间的工作原理,另外,这一切的知识对于任何高级python程序都有用。
命名空间是从命名到对象的映射。当前命名空间主要是通过python字典实现的,不过通常不关心具体的实现方式(除非出于性能考虑),以后也有可能会改变其实现方式。以下有一些命名空间的例子;
内置命名(像abs()这样的函数,以及内置异常名)集,模块中的全局命名,函数调用中的局部命名。
某种意义上讲对象的属性集也是一种命名空间。关于命名空间需要了解一件很

重要的事就是不同命名空间中的命名没有任何联系。

例如两个不同的模块可能都会定义一个名为maximize的函数而不会发生混淆-用户必须以模块名为前缀来引用它们。

称,python中任何一个“。”之后的命名为属性–,例如,表达式在z.real中的real是对象z的一个属性。严格来讲,从模块中引用命名是引用属性:表达式modname.funcname中,modname是一个模块对象,funcname是它的一个属性。
因此,模块的属性和模块中的全局命名有直接的映射关系:它们共享同一命名空间!

属性可以是只读过或写的。后一种情况下,可以对属性赋值。你可以这样作:
modname.the_answer = 42 .可写的属性也可以用del语句删除。例如:
del modname.the_answer会从modname对象中删除the_answer属性。

不同的命名空间在不同的时刻创建,有不同的生存期。包含内置命名的命名空间在python解释器启动时创建,会一直保留,不被删除。
模块的全局命名空间在模块定义被读入时创建,通常,模块命名空间也会一直保存到解释器退出。由解释器在最高层调用执行的语句,不管它从脚本文件中读入还是来自交互输入,都是__main__模块的一部分,所以它们也拥有自己的命名空间(内置命名也同样被包含在一个模块中,它被称作builtins)

当调用函数时,就会为它创建一个局部命名空间,并且在函数返回或抛出一个并没有在函数内部处理的异常时被删除。(实际上,用遗忘来形容到底发生了什么更贴切。)当然,每个递归调用都有自己的局部命名空间。

作用域就是一个python程序可以直接访问命名空间的正文区域。这里的直接访问意思是一个对名称的错误引发会尝试在命名空间内查找。尽管作用域是静态定义,在使用时他们都是动态的,每次执行时,至少有三个命名空间可以直接访问的作用域嵌套在一起:
1.包含局部命名的使用域在最里面,首先被搜索;其次搜索的是中层的作用域,这里包含了同级的函数;
最后搜索最外面的作用域,它包含内置命名。
2.首先搜索最内层的作用域,它包含局部命名任意函数包含的作用域,是内层嵌套作用域搜索起点,包含非局部,但是也非全局的命名
3.接下来的作用域包含当前模块的全局命名
4.最外层的作用域(最后搜索)包含内置命名的命名空间

如果一个命名声明为全局的,那么对它的所有引用和赋值会直接搜索包含这个模块全局命名的作用域。如果要重新绑定最里层作用域之外的变量,可以使用nonlocal语句:如果不声明为nonlocal,这些变量将是只读的(对这样的变量赋值会在最里面的作用域创建一个新的局部变量,外部具有相同命名的那个变量不会改变)。

通常,局部作用域引用当前函数的命名。在函数之外,局部作用域与全局使用域引用同一命名空间:模块命名空间。类定义也是局部作用域中的另一个命名空间。

重要的是作用域决定于源程序的意义:一个定义于某模块中的函数的全局作用域是该模块的命名空间,而不是该函数的别名被定义或调用的位置,(这点重要)

了解这一点非常重要。另一点非常重要。另一方面,命名的实践搜索过程是动态的,在运行时确定的——然而,python语言也在不断发展,以后有可能会成为静态的“编译”时确定,所以不要依赖动态解析!(事实上,局部变量已经是静态确定了。)

python的一个特别之处在于;如果没有使用global语法,其赋值操作总是在最里层的作用域。
赋值不会赋值数据,只是将命名绑定到对象。删除也是如此; del x 只是从局部作用域的命名空间中删除命名x,事实上,所有引入新命名的操作都作用于局部作用域。特别是import语句和函数定义将模块名或函数绑定于局部作用域(可以使用global语句将变量引入到全局作用域)。

global语句用以指明某个特定的变量为全局作用域,并重新绑定它。monlocal语句用以指明某个特定的变量为封闭作用域,并重新绑定它。

9.2.1作用域和命名空间示例

示例,演示如何引用不同作用域和命名空间,以及global和nonlocal如何影响变量绑定:

在这里插入图片描述
输出为:
在这里插入图片描述
local赋值语句是无法改变scope_test的spam绑定。nonlocal赋值语句改变了scope_test的spam绑定,并且global赋值语句从模块级改变了spam绑定。
你也可以看到在global赋值语句之前对spam是没有预先绑定的。

今日学习结束,今日学习到9.3.1,第79页,剩余7章,42页。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值