Python2.2-原理之类型和运算
此节来自于《Python学习手册第四版》第二部分
一、Python对象类型(第4章)
1、 Python可以分解成模块、语句、表达式以及对象:1、程序由模块构成;2、模块包含语句;3、语句包含表达式;4、表达式建立并处理对象。Python是动态类型,就和matlab一样无需提前声明,但是也是强类型语言,因为一旦有了对象那么他的操作集合也就确定了。
上图Python的内置对象类型,不过并不完整,因为Python处理的每样东西都是对象,在后面会介绍像函数、模块和类这样的编程单元在Python中也是对象,他们由def、class、import、lambda这样的语句和表达式创建,而且可以自由的在脚本之间传递,存储在其他对象中。所以上图叫做核心数据类型。
2、import 命令用来导入模块,比如>>>import math 。
3、在核心类型中,数字、字符串和元组是不可变的;列表和字典不是这样(它们可以完全自由的改变)。
4、可用作多种类型的通用型操作都是以内置函数或表达式的形式出现的:len(x),X[0],但是类型的特定的操作都是以方法调用的形式出现的:aString.upper()。
5、>>>dir(S)可以返回一个列表,其中都是该对象的所有属性,由于方法是函数属性,所以他们也会出现在列表中。一般来说,这个列表中会有一些双下划线开头和结尾的变量名,他们是用来表示Python实现细节的命名模式,而没有下划线的属性就是字符串对象能够调用的方法。
6、help(S.replace) dir函数是简单的给出了方法的名称,要查询它们是做什么的,就用这样的help函数。
7、在python中单引号和双引号意思一样,都可以用来表示字符串,而且三个引号的中间可以包括多行字符串常量:“”“ 第一行;第二行;第三行“”“。
8、>>>import re >>>match = re.match('hello[\t]*(.*)world',"hello python world") >>>match.group(1);这是第98页模式匹配例子。以此作记录而已。
9、在字典中进行索引是用【】的不是用()的;【】在序列中都可以使用。
10、在c这样的底层语言中,需要自己手动释放所有对象空间,在Python中,当最后一次引用对象(比如将这个变量用其他的值进行赋值),这个对象的内存空间就会被自动清理掉;
11、for var in dataset: your operation ... 用户定义一个循环变量var,然后将其与dataset中的进行对比,然后进行操作结果。for是用来遍历一个序列的。
12、Python的迭代协议:a、表示内存中物理存储的序列,或是在一个迭代操作情况下每次产生一个元素对象,如果一个对象在响应neixt之前先用一个对象对iter内置函数做出响应,那么属于后一种,比如for key in sort(字典):
13、还可以比如squares = 【x ××2 for x in 【1,2,3,4】】。这样的列表解析表达式。
14、上述涉及到的in 是一种表达式,比如>>>‘f’ in D 返回 false 这就说明不在里面。
15、元组看上去和列表一样,元组是序列,不过它具有不可变性,和字符串类似。它编写在圆括号中而不是方括号中,支持任意类型、任意嵌套以及常见的序列操作。Python3.0 两个元组专用调用方法:>>>T.index(4);>>>T.count(4)。
16、集合是最近增加到这门语言中的类型,它是唯一的不可变的对象的无序集合,通过内置set函数创建,或者使用3.0的新的集合常量和表达式创建,支持一般的数学几何操作。
17、python提供的新的数值类型:十进制数和分数,用来解决浮点数学的局限性和内在的不精确性。>>>import decimal ;>>>from fractions import Fraction
18、type()在3.0中,返回的就是类型class 而不是type,有三种方法可以用来测试,在书113页。
19、python支持自定义的类,也就是面向对象的编程,其中类内函数中的参数“self”对象是具有this的功能的。
20、数字、字符串和元组不可变;字符串、列表和元组是序列,有索引,合并和分片。
二、数字(第5章 )
在Python中,数字并不是一个真正的对象类型,而是一组类似类型的分类。Python数字类型的完整工具包括:1、整数和浮点数;2、复数;3、固定精度的十进制数;4、有理分数;5、集合;6、布尔类型;7、无穷的整数精度;8、各种数字内置函数和模块。
1、内置函数:hex(I)、oct(I)、bin(I)把一个整数转换为这3种进制表示的字符串,int(str,base)把一个运行时字符串转换成一个整数。
2、可以通过内置函数complex(real,imag)来创建复数。
3、下面的是内置的数学操作和扩展:
4、数字也是有很多特定于类型的方法,比如浮点数有一个as_integer_ratio,这对于分数数字类型也很有用;还有is_integer方法可以测试数字是否是一个整数;还有Python3.1将要发布的bit_length用来得到对象的值所必须的位数。
5、下面的是数字的表达式操作符:
ps:(...)用于表示元组和表达式,以及生成器表达式,后者是产生所需结果的列表解析的一种形式,而不是构建一个最终的列表,有时候圆括号会省略。
【...】用于表示列表常量或列表解析表达式,后者执行隐性循环,把表达式的结果收集到新的列表中。
yield和三元选择表达式在2.5之后采用,前者返回生成器中的send(...)参数,后者是一个多行if语句的缩写形式。如果yield不是单独的位于一条赋值语句的右边的话,需要用圆括号。
6、操作符的优先级:在表5-2中,操作符越靠后,优先级越高;如果在同一行中,则从左到右进行结合(幂运算是从右到左结合的,比较运算是从左到右结合的)。
7、python当遇到例如40+3.14的时候,也会和cpp一样进行不同的类型升级再进行运算。整数<浮点数<复数。
8、str和repr显示格式:例如>>>num = 1/3 ; >>>repr(num) ;结果是‘0.333333..1’;而>>>str(num);结果是‘0.333333’(后者是友好型)。这两个函数都是将任意对象转换成字符串表示,repr(即默认的交互模式回显)产生的结果看起来像代码;str(也就是打印语句)将有更好的用户格式。
9、//操作符通常叫做截断除法,更准确的应该叫做floor出发,是将结果向下截断到它的下层,即向下舍去>>>import math;>>>math.floor(2.5);2(如果是-2.5 结果是-3)>>>math.trunc(2.5);2(如果是-2.5结果是-2);也就是floor是数轴上往下,而trunc是数轴上往0靠拢。另:试试round()
10、接第1条,eval函数可以将字符串作为python的代码,不过更慢:>>>eval('64'),eval('0o100'),eval('0x40'),eval('0b10000000');结果(64,64,64,64);不过还能用字符串格式化方法调用表达式:>>>'{0:0},{1:x},(2:b)'.format(64,64,64);结果是‘100,40,1000000’;或者>>>'%0,%x,%X' %(64,255,255);结果是‘100,ff,FF’
11、(256).bit_length 等于len(bin(256))-2=9
12、random是模块,math是模块
13、小数数字,是通过导入的模块调用函数后创建的,不是通过运行常量表达式创建的。功能上说,小数对象就像浮点数,不过他们有固定的位数和小数点,所以小数是有固定的精度的浮点值。;而且浮点数缺乏精确性,因为它是通过存储空间来进行无线逼近的,比如>>>0.1+0.1+0.1-0.3 结果不是0,而是无限接近0的值,就算使用友好的打印格式,还是因为浮点数的精度自身缺陷没办法,使用小数就能改正:>>>from decimal import Decimal;>>>Decimal('0.1')+Decimal('0.1')+Decimal('0.1')-Decimal('0.3') 结果就是Decimal('0.0');通过Decima的构造函数创建一个小数对象,并传入一个字符串,其中是我们希望结果显示的小数位数,如果有不同位数,那么自动升级最多的那个。在3.1版本中可以使用decima.Decimal.from_float(1.25)这样来转换。或者使用decimal.getcontext().prec = 4,来将后续的设置成4位精度。
14、接13点,可以使用小数上下文管理器语句来重新设定临时的进度,语句推出后,精度又被还原:>>>with decimal.localcontext() as ctx: ... ctx.prec = 2 ... decimal.Decimal('1.00')/decimal.Decimal('3.00');
15、分数和小数一样用来解决浮点数的一些精度问题的。在python中它明确的保留了一个分子和一个分母,从而避免浮点数的不精确性和局限性;分数也存在模块中,>>>from fractions import Fraction ;>>>x = Fraction(1,3);并支持普通的数学运算;而且分数还能够自动简化成最简分数。
16、可以将浮点数对象转换成分数>>>(2.5).as_integer_ration();结果是(5,2);或者>>>f = 2.5 ;>>>z = Fraction(*f.as_integer_ratio())(这里的×是将一个元组扩展到单个的参数中);>>>Fraction.from_float(1.75);得到的就是Fraction(7,4);int<Fraction<float,遇到高的就转换成高的那个。
17、集合:不管某个元素被添加多少次,它在集合中只会出现一次。set([1,2,3,4])等同于{1,2,3,4};空的集合必须通过内置函数set来创建。通过使用union函数,可以解决,如下图:
18、集合只能包含不可变的对象类型,所以列表和字典不能嵌入到集合中,元组可以;集合本身是不可改变的,所以不能直接嵌入到其他集合中,如果需要,可以像调用set一样来调用frozenset,不过它创建的是一个不可变集合,该集合不可修改不过可以嵌套到其他集合中。
19、3.0版本中,引入了一个集合解析构造,类似列表解析的形式,不过不是写在方括号而是花括号中,而且作用于集合而不是列表。集合解析运行一个循环并在每次迭代时收集一个表达式的结果,通过一个循环变量来访问当前的迭代值以用于集合表达式中。结果是通过运行代码创建的一个新的集合。>>>{x ** 2 for x in [1,2,3,4]} 结果就是{16,1,4,9};这里循环部分写在for右边,而集合表达式写在for左边。集合天生的功能可以用来将一些列表过滤掉重复项。
20、布尔类型:>>>True == 1;True,可是如果>>>True is 1 结果是False
三、动态类型(第6章)
犹如matlab一样,无需事先声明变量,直接拿来用即可,从变量到对象的连接称作引用。也就是说,引用是一种关系,以内存中的指针形式实现。一旦变量被使用(即被引用),python自动跟随这个变量到对象的连接。每个对象都有2个标准的头部信息:一个类型标志符标识这个对象的类型;一个引用计数器,表示是否可以回收。这是因为类型是属于对象的,而不属于变量名,所以可以一直换,变量没有类型,所以实际上并没有改变变量a的类型,只是让变量引用了不同的类型的对象而已。
1、在内部,python在每个对象中保持一个计数器,计数器记录当前指向该对象的引用的数目,一旦计数器设置成0,这个对象的内存空间就会被自动回收,当变量被赋值给新的对象的时候,前一个对象的计数器就会被设置成0,而引发回收操作。ps:由于引用的实现是靠指针的,所以当情况1:一个对象引用自己;情况2:一个对象引用了另一个引用自己的对象。这两种情况下对象的引用计数器不会清零,要特别注意。
2、a = 3;b = a;a = a+3;结果来说并不会改变b的副作用。事实上,也没法改变,因为整数本身就是不可变的。在python中,变量总是一个指向对象的指针,而不是可改变的内存区域的标签:给一个变量赋一个新值,不是替换原始的对象,而是让变量去引用完全不同的一个对象。
3、L==M;和L is M ;前者是测试两个被引用的对象是否有相同的值,而后者是检查是否同一性,如果两个变量名都精确的指向同一个对象,那么就是True的,所以后者更严格。其实is 是比较两个引用的指针。
4、按照3的观点:x=42;y=42;x==y 和x is y ,;前者是没问题,可是按道理来说这是两个不同的常量表达式,不过因为python系统的针对小的整数和字符串被缓存并复用了,所以is 让我们知道这两个引用的是同一个对象。不过可以使用sys模块中的getrefcount函数来返回对象的引用次数。
四、字符串(第7章)
一个有序的字符的集合,与c不同的是python没有char类型,只有单个字符的字符串。下表是常见的字符串常量和操作,空字符串表示为一对引号(单引号,双引号无所谓)
1、python通过标准库re模块支持基于模式的字符串处理(第四章),还有xml解析器。在3.0中,有3中字符串类型:str用于unicode文本(ascii或其他),bytes用于二进制数据(包括编码的文本),bytearray是bytes的一种可变的变体。(这里对应的2.6版本略,p169)。
2、python也支持在任意的表达式中合并相邻的字符串常量:t = ‘wara’ “fawea”;结果就是t = ‘warafawea‘;len(s)用来返回字符串中有多少个字节,因为有时候使用\n 或者\t 等来做转义字符:
3、在python中,零(空)字符不会像c语言那样去结束一个字符串,相反,python在内存中保持了整个字符串的长度和文本。而且python没有字符会结束一个字符串。python会以16进制显示非打印的字符。
4、raw字符串抑制转义:myfile = open(‘C:\new\text.dat’,‘w’);这个语句中\n和\t就会被认为是转义字符而无法真正的打开。如果使用myfile = open(r‘C:\new\text.dat’,‘w’);也就是在前面加一个r用来关闭这个字符串的转义机制,不过该方法不能能以'...\'单个反斜杠结束,必须在最后手动添加一个'...\\'这样结束;或者在这种有歧义的地方使用\\两个斜杠来保证会有一个斜杠输出;而且python会自动在windows和unix中使用正斜杠表示字符串路径,比如"C:/new/text.data"。
5、三重引号编写多行字符串块,略
6、in是用来测试成员关系的,这里很像str.find(),它返回一个布尔结果,而不是子字符串的位置。>>> 'k' in 'kl' ;返回的是True.
7、字符串支持负偏移,s = 'spam'; s[0],s[-2],s[1:3],s[1:],s[:-1]。不过记得这里的偏移量是【)这样的左闭右开的范围。不过X【I:J:K】这里和matlab不一样,这里的间隔是第三个K,取范围为【I,J) 内部的值。
8、分片等同于用一个分片对象进行索引:ps:为了去掉换行字符,可以使用line.restrip方法(暂时没搞懂,因为在3.0中str.rstrip(),是将最后的空字符删除而已,不过可以使用help(str.rstrip)来看看),这个方法会留下没有换行字符那行的最后一个字符。
9、字符串-数字的简单转换>>>int("42"),str(42);结果是(42,‘42’);>>>repr(42);结果是‘42’。repr返回的对象可以作为代码的字符串,可以重新创建对象。对于字符串来说,如果是使用print语句显示,结果需要用引号括起来>>>print(str('spam'),repr('spam'));结果是(‘spam’,“ ‘ spam ’ ”)(注意引号的个数)
10、字符串代码转换:ord函数将单个字符转换成ascii,而chr函数将ascii转换成字符。ord('a') 结果是65,而chr(65)结果是‘a'。还有int('1101',2)可以将二进制转换成十进制。
11、修改字符串可以有两种方法:s = s[:4]+'Burger' + s[-1];这也就是用分片的方法来将需要的部分提取出来;或者s = s.replace('pl','pamal');这是将该字符串中原有的pl换成pamal部分。
12、字符串格式化:
13、在3.0和2.6中引入的一种叫做bytearray的新字符串类型,它是可以修改的,因为它不是真正的字符串,而是较小的,8位整数的序列。不过它支持和常规字符串相同的大多数操作,并且显示的时候打印为ascii字符,而且为必须频繁修改的大量文本提供了另一个选项。在36章中有更详细的说明。
14、除了表达式运算符外,字符串还提供一系列方法来实现更复杂的文本处理任务,方法就是与特点对象关联的函数,它们是附属于对象的属性,而属性也就是可调用的函数罢了,在python中,表达式和内置函数可能在不同范围的类型有效,但是方法通常特定与对象类型。更详细的说:函数也就是代码包,方法调用的时候进行两次操作(一次获取属性,一次函数调用):object.attribute表达式理解为“读取object对象的属性attribute的值”。方法调用表达式对象,方法(参数)从左至右运行,也就是说先读取对象方法,然后调用它,传递参数。如果一个方法计算出一个结果,它将会作为整个方法调用表达式的结果被返回。
s是一个字符串对象,可选的参数包含在方括号中,这个表中的字符串方法实现了分割和连接、大小写转换、内容测试、子字符串查找和替换这样的高级操作。
15、如果想替换一个固定长度的字符串,可以先使用find搜索,然后使用分片的方法。where = s.find('spam'),如果没找到返回-1,而且s.replace('spam','eggs',1),意思是替换一次。不过如果是一个超长的字符串,需要这样不断的创建新的字符串来达到替换的目的,有些吃力,可以转换成列表: L = list(S)。在多次修改之后,如果想变回字符串:S = ‘’.join(L);该语句的意思是用‘’(这里是空分隔符,也可以‘**’,这样的分隔符)来将参数链接起来。
16、文本解析:通过分片将数据从原始字符串中分出来;如果你所需要的数据组件没有固定的偏移,而是被分隔符分开,那么可以使用split提取出来。比如:line.split(',')是以逗号分隔符分开。
17、实际应用的一些常见的字符串方法:
18、相比较来说调用对象方法:X.method(argument)比通过string模块调用相同的运算要好:string.method(X,argument)。(需要事先导入string模块)
19、字符串格式化有两种形式:a、字符串格式化表达式;b、字符串格式化方法调用。a、%操作符为编写多字符串替换提供了一种简洁的方法,格式化字符串:在%操作符的左侧放置一个需要格式化的字符串,这个字符串带有一个或多个嵌入的转换目标,都以%开头;在%操作符右侧放置一个(或多个,嵌入到元组)的对象,这些对象将会插入到左侧想要转换的目标位置上:
20、更高级的字符串格式化表达式代码:在这其中,表达式左侧的转换目标支持多种转换操作,语法如下:%[(name)] [flags] [width] [.precision] typecode。
其中typecode就是上表的编码,其中的flags可以是左对齐(-),正负号(+)和补零(0)的标志位。
如果在运行的时候才知道大小,可以在格式化字符串中用一个×来指定通过计算得到的width和precision,从而使得它们的值是从%右边的输出中的下一项得到的:
这里×表示右边的4。
21、基于字典的字符串格式化:
,这个例子中,格式化字符串里(n)和(x)引用了右边字典的键,并提取它们相应的值。这可以用来生成类似html或者xml的程序,上面的语法中的name这里就可以看见:
这同样可以与内置函数vars配合使用,该函数返回的字典包含了所有在本函数中调用时候存在的变量,当字典用在一个格式化操作的右边时,它会让格式化字符串通过变量名来访问变量(也就是说,通过字典中的键):
22、在2.6和3.0中新的字符串对象的format方法使用主题字符串作为模板,并且接受任意多个表示将要根据模板替换的值的参数。在主题字符串中,花括号通过位置({1};{food})指出替换目标及要插入的参数。函数和方法的参数都可以使用位置和关键字名称来传递。
23、格式化调用可以变得更复杂以支持更多高级用途。比如可以指定对象属性和字典键,方括号指定字典键,而点表示位置惑关键字所引用的一项的对象属性:
上图中【】表示索引,0和1表示format中的位置。第二个例子不是通过位置,而是通过关键字来指定对象。而且在格式化字符串(也就是format左边的字符串)可以指定列表(及其他序列)偏移量以执行索引,不过只有单个的,正的偏移才合法,如果要指定负的偏移惑分片,或者使用任意表达式,需要在格式化字符串自身之外运行表达式:
24、另一种和%表达式类似的是,在格式化字符串中添加额外的语法来实现更具体的层级。对于格式化方法,在替换目标的标识之后使用一个冒号,后面跟着可以指定字段大小、对齐方式和一个特定类型编码的格式化声明:
上述语法中:fieldname是指定参数的一个数字惑关键字,后面跟着可选的“.name”或“【index】”成分引用;conversionflag可以是r、s或者a分别是在该值上对repr、str惑ascii内置函数的一次调用;formatspec指定了如何表示该值、包括字段宽度、对齐方式、补零、小数点精度等细节,并以一个可选的数据类型编码结束。冒号后的formatspec组成形式上的描述如下(方括号表示可选的组成,并且不能编写为常量):
align可能是<,>,=或^,分别表示左对齐、右对齐、一个标记字符后的补充或居中对齐。formatspec也包含嵌套的、只带有{}的格式化字符串,它从参数列表动态的获取值(和格式化表达式中的*很相似)。这里的格式化方法还允许一个“b”类型编码用来以二进制格式显示整数(它等同于使用bin内置函数),允许一个“%”类型编码来显示百分比,并且使用唯一的“d”表示十进制的整数(而不是“i”惑“u”):
这里的{0:10}意味着一个10字符宽的字段中第一个位置参数,{1:<10}意味着第二个位置参数在一个10字符宽度字段中左对齐,{0.platform:>10}意味着第一个参数的platform属性在10字符宽度的字段中右对齐。
格式化参数可以在格式化字符串中硬编码,或者通过嵌套的格式化语法从参数列表动态的获取,后者很像是格式化表达式中的星号语法:
当然2.6和3.0还提供了一种新的内置format函数,可以用来格式化一个单独的项,他是字符串格式化方法的一种更简洁的替代方法,并且大致类似%格式化表达式来格式化一个单独的项:
从技术上说,内置函数format运行主体对象的__format__方法,对于每个被格式化项目,str.format方法都是内部的,它仍然比最初的%表达式的对等体要冗长。
25、最初的%表达式无法处理关键字、属性引用、二进制类型代码,尽管%格式化字符串中的字典键引用常常能够达到类似的目标:
如下代码显示有的时候%表达式往往能够更简单:
格式化方法拥有%表达式所没有的很多高级功能,不过更复杂的格式化似乎看起来也能从根本上降低复杂性:
在方法调用中的**数据是特殊的语法,它把键和值的一个字典包装到单个“name=value”关键字参数中,以便可以在格式化字符串中用名字来引用他们:
加个逗号表示千分隔符。
26、为什么在很多地方%表达式很简单,但是还是推荐格式化方法:因为a、拥有%表达式所没有的额外功能;b、可以更明确的进行替代值引用;c、考虑从到操作符会有一个更容易记忆的方法名;d、不支持用于单个和多个替代执大小写的不同语法:
a、额外功能:
c、使用格式化表达式,单个值可以独自给,多个值必须放入一个元组中:
格式化方法通过在两种情况下接受通用的函数参数,把这两种情况绑定到一起:
也许在将来会废弃%表达式而使用format方法。
五、列表与字典(第8章)
这两种都支持原处修改,而且支持包含任意种类的对象或者被嵌套:a、任意对象的有序集合;b、通过偏移读取;c、可变长度、易购以及任意嵌套;d、属于可变序列的分类;e、对象引用数组。
1、map内置函数可以将序列中的各项应用一个函数并把结果收集到一个新的列表中:
2、sort的简单用法:
当sort()中参数为空时,默认升序排列。
3、如果使用L = L.append(X),这样的形式,会让L失去引用,因为该函数调用本身就会修改自己,所以直接写成L.append(X)就好。sort也是一样。而且现在有了内置函数sorted(),会比sort方法更有用,而且可以在排序前加上一个列表解析:
字典是python中最灵活的内置数据结构类型,如果把列表看作是有序的对象集合,那么可以把字典看成是无序的集合,它们主要差别在于字典是通过键来存取的:a、通过键而不是偏移量来读取;b、任意对象的无序集合;c、可变长、异构、任意嵌套;d、属于可变映射类型;e、对象引用表(采用最优化的散列算法来寻找键),和列表一样,字典存储的是对象引用,而不是对象本身(想象成上面说的变量名就行)。
4、当键不存在的时候通过get方法能够返回默认值(None或者用户定义的默认值),这是在当键不存在时为了避免missing-key错误而填入默认值的一个简单方法:字典的update类似于合并,不过它会盲目的覆盖相同的键的值。
5、在字典中for key in D:和for key in D.keys():效果是一样的。
6、字典用法注意事项:a、序列运算无效;b、对新索引赋值会添加项;c、键不一定总是字符串(任何不可变对象,也是可以的)。
7、字典可以用于稀疏数据结构:
这样就只存储了一个三维矩阵中两个有值的位置。
8、字典中避免missing-key的三种方法:
9、字典接口需要特别注意,因为Python的DBM接口也是通过键来获取文件的,比如anydbm模块,shelve模块,cgi模块等等。P229
10、创建字典的方法:
上图中第一种适合事先拼出整个字典,第二个可以动态创建字典,第三个只能用键做字符串,第三种可以在程序运行是将键和值逐步建成序列。而且如表8.2所示,最后一种可以与zip函数一起使用,将程序运行时动态获取的键和值的不同列表合并在一起。
11、如果想将所有的键的值初始化成一样的:
12、在3.0中字典的变化:a、支持新的字典解析表达式,这是列表和集合解析的“近亲”;b、对于D.key、D.values、D.items方法,返回可迭代的视图,而不是列表;c、因为b ,需要新的编码方式通过排序键来遍历;d、不再直接支持相对大小的比较--需要手动比较;e、不再有D.has_key方法,相反,使用in 成员关系测试。
13、字典解析只能在3.0中使用,这是上面之外的第五种方法,不过现插入一个在2.6和3.0中的动态初始化一个字典的标准方式:将其键和值对应起来并把结果传递给dict调用,如果不能在代码中预计键和值的集合,总是可以将他们构建为列表然后在对应起来:
而在3.0中可以使用字典解析表达式:
更多例子:
14、在3.0中字典的keys、values和items都返回视图对象;而在2.6中,它们返回实际的结果列表。视图对象是可迭代的,这就意味着对象每次产生一个结果项,而不是在内存中立即产生结果列表,除了可以迭代,字典试图还保持了字典成分的最初顺序,另一方面,它们不是列表,并且不支持像索引和列表sort方法的操作。想要应用列表操作或者显示它们的值,需要通过内置函数list来运行这三个方法的结果:
>>>D = dict(a = 1,b=2,c=3);
>>>K = D.keys(); >>> list(k)
>>>V = D.values(); >>>list(V)
>>>list(D.items()); >>>list(K)[0]
15、在3.0中keys方法返回的视图对象类似于集合,并且支持交集和并集等常见的集合操作;values视图不是这样,因为它不唯一,不过当(key value)对是唯一而且可散列的化,items结果是这样。如下是键列表,用于集合操作的样子,在结合操作中,视图可能与其他的视图、集合和字典混合:
如果字典项视图是可散列的,他们是类似与集合的,也就是说如果他们只包含不可变对象的话:
、
16、keys不会返回一个列表,所以需要手动转换为一个列表:Ks = D.keys()
或者直接>>>for k in sorted(Ks): print(k,d[k])。
或者 >>> for k in sorted(D) : print(k,D[k]).
17、字典大小比较:
18、3.0中的成员测试:
六、元组、文件及其他(第9章)
元组由简单的对象组构成,元组与列表非常类似,只不过其不能在原处修改,并且通常写成圆括号中的一系列项。虽然元组不支持任何方法调用,不过其具有列表的大多数属性:a、任意对象的有序集合;b、通过偏移量存取;c、属于不可变序列类型;d、固定长度、异构、任意嵌套;e、对象引用的数组。
1、元组没有方法,不过却支持字符串和列表的一般序列操作比如+,*,【】索引【I:J】分片。不过这会返回新元组
2、表9-1中因为表达式可以被圆括号括起来,为了识别用户想创建的是单个对象的元组,需要多一个逗号;在有多个创建的时候,可以省略圆括号。相比较来说,当元组作为常量传给函数调用以及元组在2.X版本的print语句中列出的特殊情况下,圆括号必不可少。
3、如果需要排序,a、将其转换成列表成为一个可变对象,或者使用内置sorted方法:>>>tmp.list(T) ;>>>tmp.sort();>>> T = tuple(tmp);或者sorted(T)。
4、列表解析也可以用于元组的转换:T = (1,2,3,4,5); L = [X +20 FOR X in T ]。
5、元组只有两个方法index 和count。元组的不可变性只适用于元组本身顶层而并非其内容。
内置open函数可以创建一个python文件对象,用来作为计算机上的一个文件链接。在调用open之后,你可以通过调用返回文件对象的方法来读写相关外部文件。文件对象只是常见文件处理任务输出模块。多数文件方法都与执行外部文件相关的文件对象的输入和输出有关,但其他文件方法可查找文件中的新位置、刷新输出缓存等。
6、打开文件:首先是外部名,接着是处理模式:a、在模式字符串尾部加上b 表示二进制数据处理(行末转换和3.0的unicode编码被关闭了);b、加上“+”意味着同时为输入和输出打开文件(也就是说,我们可以对相同文件对象进行读写,往往与对文件中的修改的查找操作配合使用)。要打开的两个参数都必须是python的字符串。第三个是可选参数,用来控制输出缓存:传入“0”意味着输出无缓存(写入方法调用时立即传给外部文件)。外部文件名参量可能包含平台特定的以及绝对惑相对目录路劲前缀。没有目录路径时,文件假定存在当前的工作目录中,即脚本运行的地方。
7、使用文件:任何情况下,python程序中的文本文件都是字符串形式,读取文件会返回字符串形式的文本,文本作为字符串传递给write方法。:a、文件迭代器是最好的读取行工具,现在从文本文件读取文字航的最佳方式是根本不要读取该文件;b、内容是字符串,而不是对象,所以从文件中读取的数据回到脚本时是一个字符串,需要对应的转换,当把数据写入文件时,python不会自动把对象转换为字符串,需要传递一个格式化的字符串;c、close是通常选项;d、文件是缓冲的并且是可查找的,python文件也是在字节偏移的基础上随机访问的,他们的seek方法允许脚本跳转到指定的位置读取或写入。
8、应用文件的一个例子:
如果想要显示带有末行字符解释的文件内容,用文件对象的read方法把整个文件读入到一个字符串中,并打印它:
如果要一行一行的扫描:
9、python总是支持文本和二进制文件,在3.0中二者之间有些差别:a、文本文件把内容表示为常规的str字符串,自动执行unicode编码和解码,并且默认执行末行转换。;b、二进制文件把内容表示为一个特殊的bytes字符串类型,并且允许程序不修改的访问文件内容。在3.0中,通常你必须使用bytes字符串处理二进制文件,并且用常规的str字符串处理文本文件,此外,由于文本文件实现了unicode编码,不能以文本模式打开一个二进制数据文件--将其内容解码为unicode文本可能会失败。
10、当读取一个二进制数据文件的时候,得到一个bytes对象--表示绝对字节值的较小整数的一个序列,其外观几乎与常规的字符串完全相同:
而且二进制文件不会对数据执行任何末行组韩圜。
11、在文件中存储并解析python对象:
在读取的时候,交互模式的回显给出的正确的字节内容,而print语句则会解释内嵌行终止符来给出用户友好结果:
12、有时候会使用字符串的rstrip来删除最后部分的"\n",不过int和一些其他转换方法会忽略数字旁边的空白。在转换11中第三行的时候,可以使用eval内置函数将字符串转换成可执行程序代码(也就是含有python表达式的字符串):
13、不过eval有时候太过强大,它会执行python的任何表达式,甚至有可能会删除计算机上所有文件的表达式,只要给予必要的权限。如果真的想储存python原生对象,但又无法信赖文件的数据来源,python标准库pickle模块会是个理想的选择。该模块是能够让我们直接在文件中储存几乎任何python对象的高级工具,也不要求我们把字符串转换来转换去,它就像一个通用的数据格式化和解析工具。例如在文件中存储字典:
之后想要取回字典,只要在用一次pickle重建就行:
pickle模块执行所谓的对象序列化,也就是对象和字节字符串之间的相互转换。这里,在pickle内部将字典转成字符串形式。ps:我们是用二进制模式打开用来存储pickle化的对象的文件,二进制模式总是python3.0中必需的,因为pickle程序创建和使用一个bytes字符串的对象,并且这些对象意味着二进制模式文件(文本模式文件意味着3.0中的str字符串)。早期的python,协议0使用文本模式文件是没问题的(默认创建ascii文本),;较高的协议要求二进制模式文件。3.0的默认协议是3(二进制),但是它即使对于协议0也创建bytes。2.6中pickle的优化版本cPickle模块可以直接导入以提高速度,3.0中改名为_pickle,并且在pickle中自动使用它。
14、struct模块可以构造并解析打包的二进制数据,从某种话说,它是另一个数据转换工具,它能够把文件中的字符串解读为二进制数据。例如:用‘wb’模式打开一个文件,并将一个格式化字符串和几个python对象传给struct:
上图中‘>i4sh’是格式化字符串,指的是一个4字节整数、一个包含4个字符的字符串以及一个2位整数的数据包,所有的这些都按照高位在前(big-endian)的形式。(更详细的使用help(struct))。
15、文件上下文管理器:在33章有更详细的:
16、虽然open函数极其返回的文件对象是python脚本中通向外部文件的主要接口,python工具集中还有其他类似的文件工具,还有其他可用的:a、标准流,在sys模块中预先打开的文件对象;b、os模块中的描述文件,处理整数文件、支持例如文件锁定之类的较低级工具;c、sockets、pipes和FIFO文件,文件类对象,用于同步进程或者通过网络进行通信;d、通过键来存取的文件;e、shell命令流,像os.open和subprocess.Popen这样的工具,支持产生shell命令,并读取和写入到标准流。不过第三方开源的比如PySerial扩展中支持与窗口交流,以及pexpect系统中的交互程序。
17、这里进行python核心内置类型的分类:
a、对象根据分类来共享操作:字符串、列表和元组都共享诸如合并、长度和索引等序列操作;b、只有可变对象(列表、字典和集合)可以原处修改;不能原处修改数字、字符串或元组;c、文件导出唯一的方法,所以可变性不真的适用于他们-当处理文件的时候,他们的状态可能会修改;d、上表中的数字包含了所有的数字雷系:整数、浮点数、复数、小数和分数;e、上表中字符串包括str以及3.0中的bytes和2.6中的unicode;3.0中的bytearray字符串类型是可变的;f、集合类似与一个无值的字典的键,但是不能映射为值,并且没有顺序,因此,集合不是一个映射类型或者一个序列类型,forzenset是集合的一个不可变的版本。;g、除了类型分类操作,上表中的所有类型都有可调研的方法,不过通常特定与他们的类型。
18、一般来说,a、列表、字典和元组可以包含任意种类的对象;b、列表、字典和元组可以任意嵌套;c、列表和字典可以动态的扩大缩小。而且因为python的符合对象类型支持任意结构,所以例如:字典的值可以是列表,而这个列表可能包含元组,而元组又可能包含字典。
19、在赋值操作中,是将对象的引用给新的变量,而不是对对象进行拷贝,如果你想要复制对象,那么就明确的告诉python你想这么做。a、没有限制条件的分片表达式(L【:】)能够复制字典;b、字典的copy方法(X.copy())能够复制字典;c、有些内置函数(比如list)能够生成拷贝(list(L));d、copy标准库模块能够生成完整拷贝。>>>A = L[:] 和>>>B = D.copy()。所以如果在其他地方填入的时候,可以使用完整分片来进行复制X【:】这样。ps:不过需要注意的是,无条件值的分片以及字典copy方法只能做顶层复制,也就是说不能够复制嵌套的数据结构,不然就得使用标准的copy模块,import copy;并使用>>>x=copy.deepcopy(Y)。
20、python的比较操作--测试相等性,相对大小等,当嵌套对象存在时,python会自动遍历数据结构,而且不断的深入。一般来说,python中不同的类型的比较方法如下:a、数字通过相对大小进行比较;b、字符串按照字典顺序,一个字符接着一个字符的进行比较;c、列表和元组从左到右对每部分内容进行比较;d、字典通过排序后的(键、值)列表进行比较,字典的相对大小比较在3.0中不支持;e、数字混合雷系比较(比如1< 'spam')在3.0中是错的,需要同类型比较。
21、在python中真假的含义是0代表假,1代表真,而且将任何空数据结构视为假,任何非空视为真:
在python中有个特殊的对象:None,这个总被认为是假。用来做空的占位作用,类似于C中的NUll。
22、类型本身在python中也是对象类型。在2.2版本中每个核心类型都有个新的内置名来支持面向对象子类的类型定制:dict、list、str、tuple、int、float、complex、byte、type、set和file(在2.6中file也是类型名称,是open的同义词,不过3.0中不是)。调用这些名称其实就是调用对象构造函数,而不仅仅是转换函数。不过在3.0中,类型标准库模块提供其他不能作为内置类型使用类型的名称,而是用isinstance函数进行类型测试:
上面所有的类型测试都为真。因为目前python的类型也可以再分为子类,一般都建议使用isinstance技术:
p264
23、除了上面介绍的几种核心对象之外,后续说道的函数、模块和类,典型的python安装还有几十种其他可用的对象类型,允许作为c语言的扩展程序或是python的类:正则表达式对象、DBM文件、GUI组件、网络套接字等。