笔记之《Python学习手册》第4版

Learning Python

(4th Edition

 

Python学习手册

第4版

 

Mark Lutz著

李军 刘红伟等译

 

O’REILLY Media, Inc

机械工业出版社


其实,我原先是不准备做这个笔记的,感觉编程这是技术性问题,多练即可,无奈大脑记性不佳,且技术之间的关系又没有搞清楚,故特作此笔记,以图理清脉络,加强记忆。

这篇笔记不会像以前那样详细,只是作为个人一种梳理、助记工具而已。

话说该作者挺为初学者着想的,全面详细,美中不足的是话有些重复。

一个多星期读完这本书,我好佩服自己啊!!!

 

类型和运算

  1. 程序由模块构成。
  2. 模块包含语句。
  3. 语句包含表达式。
  4. 表达式建立并处理对象。

核心数据类型

数字

字符串

列表

字典

字典视图

元组

文件

集合

动态类型

变量在赋值是创建,可以引用任何类型的对象,并且必须在引用之前赋值

变量是一个系统表的元素拥有指向对象的连接的空间

对象是分配的一块内存有足够的空间去表示它们代表的值

引用是自动形成的从变量到对象的指针

类型属于对象其头部有一个类型标识符和一个引用计数器

引用计数器为零时,该对象的内存空间会被回收。

作为一种优化Python会缓存不变的对象通常是小的整数和小的字符串并对其复用

共享引用——多个变量名引用了同一个对象。当对象是不变对象时,修改其中一个变量不会影响到另外一个,但对象是可变对象时,原处修改则会影响到。

内置类型陷阱

赋值产生引用,而不是拷贝

重复能够增加层次深度

留意循环数据结构

不可变类型不可以在原处改变

语句和语法

赋值表达式和打印

赋值

赋值语句执行时,python会建立相应的临时数据类型储存右侧变量原始的值

Python 3.0中的扩展序列解包,*号会使变量匹配剩下的内容

If测试和语法规则

布尔运算时,有短路规则,返回的是短路时所测试的对象。

While和for循环

循环else语句用于非break语句跳出,注意其缩进。

内置的range函数返回一系列连续增加的整数可作为for中的索引

zip函数返回并行元素的元祖列表可用于for中遍历数个序列

enumerate函数产生偏移值及偏移值处的值

迭代器和解析,第一部分

一般情况下,“可迭代的”指支持iter的一个对象,“迭代器”值iter所返回的一个支持next(I)的对象

for循环开始时会通过它传给iter内置函数以便从中取得迭代器

列表解析从语法上讲源于集合理论表示法中的一个结构难道是我在高中学的那个】。通常其迭代是以C语言的速度执行

文档

#注释

dir函数

文档字符串:__doc__

写成字符串,放在模块文件、函数以及类语句的顶端的注释

PyDoc:help函数

提取文档字符串并且自动提取其结构化的信息,并将其格式化成各种类型的排列友好的报表。

PyDoc:HTML报表

函数

函数基础

def语句是实时执行的

作用域

作用域法则

内嵌的模块是全局作用域。

全局作用域的作用范围仅限于单个文件

每次对函数的调用都创建一个新的本地作用域

赋值的变量名除非声明为全局或非本地否则均为本地

所有其他的变量名都快归纳为本地全局或内置的

变量名解析:LEGB原则

当在函数中使用为认证的变量名时,会搜索4个作用域,本地(L),上层函数的本地(E),全局(G),内置(B,__builtin__标准库模块),在第一个找到处停下。

当在函数中给一个变量名赋值时Python总是创建或改变本地的变量名除非已经声明为全局变量

在函数外给变量名赋值时,本地与全局是相同的。

global语句

全局变量如果在函数内被赋值的话,必须经过global声明

全局变量名在函数内部不经过声明也可被引用

作用域和嵌套函数

嵌套函数能够记住嵌套作用域的变量值,即使上层函数已经返回了。

nonlocal语句

将变量映射到上层函数作用域中的对应变量。

参数

在函数调用中,参数必去以此顺序出现:任何位置参数(value),后面跟着任何关键字参数(name=value)和*sequence形式的组合,后面跟着**dict形式。

在函数头部参数必须以此顺序出现任何一般参数name),紧跟着任何默认参数(name=value),如果有的话,后面是*name的形式,后面跟着name或name=value keyword-only参数后面跟着**name形式

参数匹配步骤

  1. 通过位置分配非关键字参数
  2. 通过匹配变量名分配关键字参数
  3. 其他额外的非关键字参数分配到*name元祖中
  4. 其他额外的关键字参数分配到**name字典中
  5. 用默认值分配给在头部未得到分配的参数

函数的高级话题

尽量用循环,而不是递归,因为for循环会自动迭代。

函数注解编写在def头部行参数注解,参数列表->注解。

匿名函数lambda

是一个表达式,不是一个语句。

主体是一个单个的表达式不是代码块

迭代和解析,第二部分

列表解析通用结构 [expression for target1 in iterable1 [if condtion1] for target2 in iterable2 [if condition2]…]

重访迭代器生成器

生成器函数:编写为常规的def语句,但使用yield语句一次返回一个结果,在每个结果之间挂起和继续他们的状态。yield语句编译为生成器调用时返回一个支持自动创建__init__方法的迭代器

生成器表达式类似于列表解析返回按需产生结果的一个对象。括在圆括号中而不是方括号中。

模块

模块:宏伟蓝图

import如何工作

第一次导入指定文件时,会执行三个步骤。1、找到模块文件。2、编译成位码(需要时)。3、执行模块的代码来创建所定义的对象。

模块搜索路径

sys.path包括四个部分

  1. 程序的主目录
  2. PYTHONPATH目录
  3. 标准链接库目录
  4. 任何.pth文件的目录

模块代码编写基础

import和from是赋值语句

import将整个模块对象赋给一个变量名

from将一个或多个变量名赋给另一模块中同名的对象

导入和作用域

函数绝对无法看见其他函数内的变量名,除非它在处于这个函数内

模块程序代码绝对无法看见其他模块内的变量名除非明确地进行了导入

重载模块

reload函数强制已加载的模块代码重新载入并重新执行。新的代码的赋值语句会在适当的地方修改现有的模块对象。

模块包

Python代码的目录称为包

包和搜索路径设置

包所在的容器目录应在模块搜索路径中

__init__.py包文件

包导入路径中的每个目录内都必须有__init__.py文件

包首次导入时会自动执行该文件

可为目录所创建的模块对象提供命名空间包含所赋值的所有变量名

使用__all__列表,定义目录以from*语句形式导入时,需要导出什么。

包相对导入

Python 3.0中的变化

修改了模块导入搜索路径语义,以默认地跳过包自己的目录。到如只是检查搜索路径的其他组件。这叫做“绝对”导入。

扩展了from语句的语法以允许显式地要求导入值搜索包的目录。这叫做“相对”导入。

高级模块话题

最小化from*的破坏:_X和__all__

_X会阻止from*导入此变量名

__all__列表列出了from*语句要导出的变量

Import语句和from语句的as扩展

若要重载from语句导入的变量需先重载该模块(若该模块没有导入的话,需先导入,再重载),再重新执行from语句。

类和OOP

类代码编写基础

类产生多个实例对象

类对象提供默认行为

Class语句创建类对象并将其赋值给变量名

Class语句的赋值语句会创建类的属性

类属性提供对象的状态和行为

实例对象是具体的元素

像函数那样调用类对象会创建新的实例对象

每个实例对象继承类的属性并获得了自己的命名空间

在方法内对self属性做赋值运算会产生每个实例自己的属性

类通过继承进行定制

超类列在了类开头的括号中

类从其超类中继承属性

实例会继承所有可读取类的属性

每个object.attribute都会开启新的独立搜索

逻辑的修改是通过创建子类而不是修改超类

类可以截获Python运算符

以双下划线命名的方法(__X__)是特殊钩子

当实例出现在内置运算时这类方法会自动调用

类可覆盖多数内置类型运算

运算符覆盖方法没有默认值而且也不需要

运算符可让Python的对象模型相集成

更多实例

步骤1:创建实例

编写构造函数

以两种方式使用代码作为模块文件或作为脚本使用__name__运行测试代码

步骤2:添加行为方法

编写方法

封装,把操作逻辑包装到界面之和

步骤3;运算符重载

提供打印显示

步骤4:通过子类定制行为

编写子类

扩展方法,调用超类的方法

继承、定制和扩展

步骤5:定制构造函数

步骤6:使用内省工具

instance.__class__

object.__dict__

步骤7:把对象存储到数据库中

Pickle和Shelve

pickle:任意Python对象和字节串之间的序列化

dbm实现一个可通过键访问的文件系统以存储字符串

shelve使用另外两个模块按照键把Python对象存储到一个文件中

类代码编写细节

运算符重载

构造函数和表达式:__init__和__sub__

索引和分片:__getitem__和__setitem__

拦截分片slice()

索引迭代:__getitem__

迭代器对象:__iter__和__next__

所有迭代环境会先尝试__iter__方法,再尝试__getitem__方法。

当迭代器返回自身时只支持一个活跃的迭代器。反之,则可支持独立位置的多个活跃迭代器。

成员关系:__contains__、__iter__和__getitem__

优先级如上所示

属性引用:__getattr__和__setattr__

__getattr__拦截未定义的属性

__repr__和__str__会返回字符串表达形式

打印操作首先尝试__str__和str内置函数

右侧加法和原处加法:__radd__和__iadd__

只有+右侧对象是类实例,左侧不是时,才调用__radd__,其他所有情况下,由左侧对象调用__add__方法。

Call表达式:__call__

当调用实例时,使用该方法。

比较:__It__、__gt__和其他方法

布尔测试:__bool__和__len__

对象析构函数:__del__

类的设计

Python的OOP可概括三个概念:继承、多态和封装

应该吧程序代码写成预期的对象接口而不是特定的数据类型

OOP和继承:“是一个”关系

OOP和组合:“有一个”关系

OOP和委托:“包装”对象

类的伪私有属性

Class语句中开头有两个下划线,但结尾没有两个下划线的变量名自动扩张,_classname__x

方法是对象:绑定或无绑定

无绑定类方法对象:无self。通过对类进行点号运算从而获取类的函数属性。Python 3.0删除了该概念。

绑定实例方法对象self+函数对通过对实例进行全运算从而获取类的函数属性

多重继承:“混合”类

超类多于一个时,即为多重继承

传统类中属性搜索深度优先

新式类(以及Python 3.0的所有类),属性搜索沿着树层次广度优先

__dict__列出实例属性

用dir列出继承的属性

类的高级主题

扩展内置类型

通过嵌入扩展类型

通过子类扩展类型

新式类

(Python 3.0)所有类的继承自object,所有对象都是object的实例

新式类变化

类和类型合并

继承搜索顺序

针对内置函数的属性获取

新的高级工具

__slots__:只有其列表中的变量名可赋值为实例属性

异常和工具

异常基础

异常编码细节

try/except/else语句

try下的代码代表主要动作except定义异常的处理器else子句提供无异常时的处理器

空的except子句捕捉一切异常,捕捉Exception的异常类似于此,但会忽略和系统退出有关的异常。

一旦捕捉了错误控制权会在捕捉的地方继续下去,即try语句之下,没有直接的方式可以回到异常发生的地方

try/finally语句

当控制权离开try代码块时,Python先执行finally代码块,然后才跳出。finally不会终止异常

统一try/except/finally语句

raise语句

raise

raise   #Make and raise instance of class

raise 重新引发最近引发的异常以传播已经捕获的异常

Python 3.0异常链raise from

assert语句(断言)

with/as环境管理器

with expression [as variable]: with-block

expression返回一个支持环境管理器协议(有__enter__和__exit__方法)的对象。其__enter__方法的返回值会赋值给variable

若有异常被引发,__exit__(type,value,traceback)方法被调用,若其返回值为假,异常会重新引发,以传播到with语句外。

没有异常时,__exit__(None,None,None)会被调用。

异常对象

基于类的异常的特点:提供类型分类;附件状态信息;支持继承。

异常的设计

嵌套异常处理器

关于sys.exc_info

有处理器处理时,返回(type、value和traceback)元组

你可能感兴趣的:(读后笔记)