翼度科技»论坛 编程开发 python 查看内容

【Python学习笔记】 第9章 元组、文件和其他核心类型

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
元组

Python元组的属性:

  • 任意对象的有序集合
  • 通过偏移量存取
  • 属于“不可变序列”
  • 固定长度、多样性、任意嵌套
  • 对象引用的数组
元组的常见方法:
运算解释()空元组T = (0,)单个元素的元组T = (0, 'Ni', 1.2, 3)四个元素的元组T = 0, 'Ni', 1.2, 3还是四个元素的元组T = ('Bob', ('dev', 'mgr'))嵌套元组T = tuple('spam')可迭代对象的元素组成的元组T索引T[j]索引的索引T[i:j]分片len(T)长度T1 + T2拼接T * 3重复for x in T: print(x)迭代'spam' in T成员关系测试[x ** 2 for x in T]列表推导(好像不应该出现在这里?)namedtuple('Emp', ['name', 'jobs'])有名元组扩展类型元组的实际应用

元组支持字符串和列表的一般序列操作,如拼接、重复、索引和分片。
  1. >>> (1, 2) + (3, 4)
  2. (1, 2, 3, 4)
  3. >>> (1, 2) * 4
  4. (1, 2, 1, 2, 1, 2, 1, 2)
  5. >>> T = (1, 2, 3, 4)
  6. >>> T[0]
  7. 1
  8. >>> T[1:3]
  9. (2, 3)
复制代码
元组的特殊语法:逗号和圆括号

如果我们要得到元组而不是表达式的值,我们要在圆括号中加,。如果要构造单个元素的元组,就要在元素的后面加上,。
  1. >>> (40)    # 数字
  2. 40
  3. >>> (40,)   # 元组
  4. (40,)
复制代码
在不会引起二义性的情况下,Python允许构造元组时省略圆括号。要用到圆括号的情形:元组出现在一个函数调用中,或嵌套在一个更大的表达式内。
转换、方法和不可变性

注意:上述的对元组的操作(拼接、重复等)会返回一个新的元组。元组不提供字符串、列表和字典中的方法。要对一个元组的元素排序,可以转换成可变对象(如列表),或者使用新的内置函数(如sorted)。
  1. >>> T = ('cc', 'aa', 'dd', 'bb')
  2. >>> T = tuple(tmp)
  3. >>> tmp = list(T)
  4. >>> tmp.sort()
  5. >>> sorted(T)
  6. ['aa', 'bb', 'cc', 'dd']
  7. >>> T
  8. ('aa', 'bb', 'cc', 'dd')
复制代码
list将元组转换为列表,tuple将列表转换为元组。
列表推导也可以用来转换元组。
  1. >>> T = (1, 2, 3, 4, 5)
  2. >>> L = [x + 20 for x in T]
  3. >>> L
  4. [21, 22, 23, 24, 25]
复制代码
列表的本质是不可变序列操作,列表推导甚至可以用在某些并非实际存储的序列上,任何可迭代对象都可以。
元组有属于自己的方法——index索引,count寻找元组中元素的数目。
  1. >>> T = (1, 2, 3, 2, 4, 2)
  2. >>> T.index(2)      # 第一个2的索引
  3. 1
  4. >>> T.index(2, 2)   # 从偏移2开始,第一个2的索引
  5. 3
  6. >>> T.count(2)
  7. 3
复制代码
注意:元组的不可变性只适用于元组本身顶层而非其内容。我们可以修改元组内部的列表。
  1. >>> T = (1, [2, 3], 4)
  2. >>> T[1] = 'spam'
  3. Traceback (most recent call last):
  4.   File "<stdin>", line 1, in <module>
  5. TypeError: 'tuple' object does not support item assignment
  6. >>> T[1][0] = 'spam'
  7. >>> T
  8. (1, ['spam', 3], 4)
复制代码
为什么有了列表还需要元组

“元组”的概念来自于数学,元组的不可变性提供了某种一致性,确保元组不会被另一个引用修改,类似于“常量”声明。
重访记录:有名元组

我们可以实现一个同时提供序号和键两种询问方式的对象。例:namedtuple工具实现了一个增加了逻辑的元组扩展类型(在模块collections被使用),能同时支持使用序号和属性访问组件。
  1. >>> from collections import namedtuple
  2. >>> Rec = namedtuple('Rec', ['name', 'age', 'jobs'])
  3. >>> bob = Rec('Bob', age=40.5, jobs=['dev', 'mgr'])
  4. >>> bob
  5. Rec(name='Bob', age=40.5, jobs=['dev', 'mgr'])
  6. >>> bob[0]
  7. 'Bob'
  8. >>> bob[2]
  9. ['dev', 'mgr']
  10. >>> bob.name
  11. 'Bob'
  12. >>> bob.jobs
  13. ['dev', 'mgr']
  14. >>>
复制代码
可以将其转换成一个字典,或者类似字典的结构:
  1. >>> O = bob._asdict()
  2. >>> O['name']
  3. 'Bob'
  4. >>> O['jobs']
  5. ['dev', 'mgr']
  6. >>> O
  7. {'name': 'Bob', 'age': 40.5, 'jobs': ['dev', 'mgr']}
复制代码
元组和有名元组都支持解包元组赋值:
  1. >>> bob = Rec('Bob', 40.5, ['dev', 'mgr'])
  2. >>> name, age, jobs = bob
  3. >>> name
  4. 'Bob'
  5. >>> jobs
  6. ['dev', 'mgr']
复制代码
但是,解包元组赋值有时候不适用于字典,因为字典中的键值是没有序号的。
  1. >>> bob = {'name': 'Bob', 'age': 40.5, 'jobs': ['dev', 'mgr']}
  2. >>> bob.values()
  3. dict_values(['Bob', 40.5, ['dev', 'mgr']])
  4. >>> job, name, age = bob.values()
  5. >>> job
  6. 'Bob'
  7. >>> name
  8. 40.5
复制代码
文件

通过open,我们能够创建一个Python文件对象作为到计算机上一个文件的链接。在调用open后,我们可以通过返回的文件对象的方法,在程序与相应文件之间来回传递串形式的数据。
文件对象与前面介绍的核心数据类型不同,它只支持与文件处理任务相关的方法。常见的文件操作见下表:
操作解释output = open(r'C:\spam', 'w')创建输出文件('w'代表写入文件)input = open('data', 'r')创建输入文件('r'代表从文件读入)input = open('data')同上('r'是默认值)aString = input.read()把整个文件读入字符串aString = input.read()读取接下啦的N个字符到一个字符串aString = input.readline()读取下一行(包括行末的'\n')到一个字符串aList = input.readlines()读取整个文件到一个字符串列表,列表中的元素是包括行末的'\n'的行output.write(aString)把字符串写入文件output.writelines(aList)把列表内所有的字符串写入文件output.close()手动关闭(文件收集完成时会自动关闭)output.flush()把输出缓冲区刷入硬盘中,但不关闭文件anyFile.seek(N)把文件位置移动到偏移量N处以便进行下一个操作for line in open('data'): use line文件迭代器逐行获取open('f.txt', encoding='latin-1')Python 3.X Unicode文件(str字符串)open('f.bin', 'rb')Python 3.X 字节码文件(bytes字符串)codecs.open('f.txt', encoding='utf-8')Python 2.X Unicode文件(unicode字符串)open('f.bin', 'rb')Python 2.X 字节码文件(str字符串)打开文件

打开文件时,程序调用内置函数open,第一个参数是外部文件名,第二个参数是文件的处理模式,返回文件对象,这个文件对象带有传输数据的方法:
  1. afile = open(filename, mode)
  2. afile.method()
复制代码
第一个参数是外部文件名,它可能有相对路径前缀,如果没有,则默认在脚本所运行的目录下。

第二个参数是打开方式,'r'表示读文件,'w'表示写文件,'a'表示在文件内容追加内容并打开文件,'b'表示可以进行二进制处理,'+'表示同时支持输入输出。
第三个参数是可选的,控制输出缓冲,0表示输出无缓冲。
使用文件

基础用法的提示:

  • 文件迭代器最适合逐行读取
  • 写入文件的内容必须是字符串,Python不会帮你转换
  • 文件是被缓冲的、可定位的,写入的文本不会被立刻从内存转移到硬盘,除非关闭文件或用flush()方法
  • close是可选的,回收时自动关闭
文件的实际应用

首先为输出打开一个文件,写入两行文本,关闭文件:
  1. >>> afile = open('1.txt', 'w')
  2. >>> myfile = open('myfile.txt', 'w')
  3. >>> myfile.write('hello text file\n')
  4. 16
  5. >>> myfile.write('goodbye text file\n')
  6. 18
  7. >>> myfile.close()
复制代码
在Python 3.X中,写入字符串会返回字符数,但Python 2.X不会。
然后打开文件,逐行读取。第三个readline()返回空字符串,表示文件已经到达末尾。
  1. >>> myfile = open('myfile.txt')
  2. >>> myfile.readline()
  3. 'hello text file\n'
  4. >>> myfile.readline()
  5. 'goodbye text file\n'
  6. >>> myfile.readline()
  7. ''
复制代码
read方法把整个文件内容读入到一个字符串中:
  1. >>> open('myfile.txt').read()
  2. 'hello text file\ngoodbye text file\n'
复制代码
如果要逐行扫描文件并对每一行操作,文件迭代器是最佳选择:
  1. >>> for line in open('myfile.txt'):
  2. ...     print(line.upper(), end='')
  3. ...
  4. HELLO TEXT FILE
  5. GOODBYE TEXT FILE
复制代码
这样,open创建的临时文件对象将自动在每次循环迭代时读入并返回一行。优点:容易编写、更高的内存使用效率、更快。
文本和二进制文件:一个简要的故事

Python总是支持文本和二进制文件,其中:

  • 文本文件把内容表示为常规的str字符串,自动执行Unicode编码和解码,并且默认执行末行转换;
  • 二进制文件把内容表示为一个特殊的bytes字节串类型。
由于文本文件实现了Unicode编码,因此不能以文本模式打开一个二进制文件,否则解码会失败。当我们读取一个二进制文件时,会得到一个bytes对象(字节串)。
  1. >>> open('myfile.txt', 'rb').read()
  2. b'hello text file\r\ngoodbye text file\r\n'
复制代码
此外,二进制文件不会对数据执行任何字符串转换。
在文件中存储Python对象:转换

下面的例子把多种Python对象写入一个文本文件的各行,必须把对象转换成字符串。
  1. >>> open('myfile.txt', 'r').read()
  2. 'hello text file\ngoodbye text file\n'
  3. >>> X, Y, Z = 43, 44, 45
  4. >>> S = 'Spam'
  5. >>> D = {'a': 1, 'b': 2}
  6. >>> L = [1, 2, 3]
  7. >>>
  8. >>> F = open('datafile.txt', 'w')
  9. >>> F.write(S + '\n')
  10. 5
  11. >>> F.write('%s,%s,%s\n' % (X, Y, Z))
  12. 9
  13. >>> F.write(str(L) + '$' + str(D) + '\n')
  14. 27
  15. >>> F.close()
复制代码
创建文件后,我们可以读取文件中的内容。注意,交互式(在交互模式下输入对象)显示给出直接的字节内容,而print操作解释内嵌的换行符”:
  1. >>> chars = open('datafile.txt').read()
  2. >>> chars
  3. "Spam\n43,44,45\n[1, 2, 3]${'a': 1, 'b': 2}\n"
  4. >>> print(chars)
  5. Spam
  6. 43,44,45
  7. [1, 2, 3]${'a': 1, 'b': 2}
复制代码
但是,问题是如何将文本文件中的字符串转换成Python对象。
把第一行转换为字符串:
  1. >>> F = open('datafile.txt')
  2. >>> line = F.readline()
  3. >>> line
  4. 'Spam\n'
  5. >>> line.rstrip()
  6. 'Spam'
复制代码
把第二行转换为数字序列。这里int函数可以忽略数字字符串旁边的的空白:
  1. >>> line = F.readline()
  2. >>> parts = line.split(',')
  3. >>> parts
  4. ['43', '44', '45\n']
  5. >>> numbers = [int(P) for P in parts]
  6. >>> numbers
  7. [43, 44, 45]
复制代码
转换第三行时,我们可以运行eval函数,它把字符串参数当作可执行程序代码:
  1. >>> line = F.readline()
  2. >>> line
  3. "[1, 2, 3]${'a': 1, 'b': 2}\n"
  4. >>> parts = line.split('$')
  5. >>> parts
  6. ['[1, 2, 3]', "{'a': 1, 'b': 2}\n"]
  7. >>> eval(parts[0])
  8. [1, 2, 3]
  9. >>> eval(parts[1])
  10. {'a': 1, 'b': 2}
复制代码
存储Python原生对象:pickle

eval的缺陷是:它会执行任何表达式,包括删除计算机中所有文件的表达式。如果要存储Python的原生对象,就应该使用pickle。
pickle是一种能够让我们直接在文件中存储几乎任何Python对象的高级工具,而且不需要字符串转换。
例:在文件中存储字典:
  1. >>> D = {'a': 1, 'b': 2}
  2. >>> F = open('datafile.pkl', 'wb')
  3. >>> import pickle
  4. >>> pickle.dump(D, F)
  5. >>> F.close()
复制代码
想要取回字典时,再次使用pickle重建即可:
  1. >>> F = open('datafile.pkl', 'rb')
  2. >>> E = pickle.load(F)
  3. >>> E
  4. {'a': 1, 'b': 2}
复制代码
实际上,pickle将字典转化为一系列二进制的字节串,也能从字节串转化为对象:
  1. b'\x80\x04\x95\x11\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x01a\x94K\x01\x8c\x01b\x94K\x02u.'
复制代码
shelve也可以实现类似功能,但这里不讨论。
用JSON格式存储Python对象

JSON是一种新兴的数据交换格式,它与语言无关,也支持多种系统。它的可移植性在一些场景中会带来巨大优势。此外,由于JSON与Python中的字典和列表在语法上的相似性,使Python的json标准库模块能够很容易地在Python对象与JSON之间来回转换。
比如,Python的字典和JSON数据十分相似。我们创建一个字典,发现可以将字面量几乎原封不动地传给JSON文件:
  1. >>> name = dict(first='Bob', last='Smith')
  2. >>> rec = dict(name=name, job=['dev', 'mgr'], age=40.5)
  3. >>> rec
  4. {'name': {'first': 'Bob', 'last': 'Smith'}, 'job': ['dev', 'mgr'], 'age': 40.5}
  5. >>> import json
  6. >>> json.dumps(rec)
  7. '{"name": {"first": "Bob", "last": "Smith"}, "job": ["dev", "mgr"], "age": 40.5}'
  8. >>> S = json.dumps(rec)
  9. >>> O = json.loads(S)
  10. >>> O
  11. {'name': {'first': 'Bob', 'last': 'Smith'}, 'job': ['dev', 'mgr'], 'age': 40.5}
复制代码
json模块可以使JSON表达式和Python对象互相转换。从json文件读取对象时,json模块把文件地内容从JSON表示重建成Python对象。这里,dump把对象地字面量读取到json文件中,load把json文件中的字面量加载到变量。注意,实际上的文件扩展名应该是.json而不是.txt。
  1. >>> json.dump(rec, fp=open('testjson.txt', 'w'), indent=4)
  2. >>> print(open('testjson.txt').read())
  3. {
  4.     "name": {
  5.         "first": "Bob",
  6.         "last": "Smith"
  7.     },
  8.     "job": [
  9.         "dev",
  10.         "mgr"
  11.     ],
  12.     "age": 40.5
  13. }
  14. >>> P = json.load(open('testjson.txt'))
  15. >>> P
  16. {'name': {'first': 'Bob', 'last': 'Smith'}, 'job': ['dev', 'mgr'], 'age': 40.5}
复制代码
存储打包二进制数据:struct

struct模块能够构造/解析打包二进制数据。
要生成一个打包二进制数据,可以用'wb'(写入二进制)打开它,并将一个格式化字符串和几个Python对象传给struct。
  1. >>> F = open('data.bin', 'wb')
  2. >>> import struct
  3. >>> data = struct.pack('>i4sh', 7, b'spam', 8)
  4. >>> data
  5. b'\x00\x00\x00\x07spam\x00\x08'
  6. >>> F.write(data)
  7. 10
  8. >>> F.close()
复制代码
Python会创建一个我们通常写入文件的二进制bytes数据字符串,主要由不可打印字符的十六进制转义组成。
要把二进制文件解析成一般的Python对象,可以直接读取字节串,并使用相同的格式字节串解压即可。
  1. >>> F = open('data.bin', 'rb')
  2. >>> data = F.read()
  3. >>> data
  4. b'\x00\x00\x00\x07spam\x00\x08'
  5. >>> values = struct.unpack('>i4sh', data)
  6. >>> values
  7. (7, b'spam', 8)
复制代码
二进制文件是高级且底层的工具,因此这里不会介绍更多细节。
文件上下文处理器

文件上下文能够让我们把文件处理代码包装到一个逻辑层中,以确保在推出后一定会自动关闭文件,而不是在垃圾回收时自动关闭:
  1. with open(r'C:\code\data.txt') as myfile:
  2.     for line in myfile:
  3.         ...use line here...
复制代码
之后学的try/finally也提供类似的功能。
其他文字工具

更多文件的方法查询:dir()函数、help()函数、第13章。
Python工具集中有其他类似可用的文件工具:

  • 标准流
  • os模块中的描述文件
  • 套接字、管道和FiFO文件
  • 通过键存取的文件
  • Shell命令流
核心类型复习总结


  • 按照分类,一些对象拥有共同的操作。如字符串、列表和元组拥有序列操作。
  • 只有可变对象可以在原位置修改。可变对象有:列表、字典和集合。
  • 文件只导出方法,因此可变性不适用于文件类型。
  • “数字”包含:整数、浮点数、复数、小数和分数。
  • 字符串包含:str、Python 3.X中的bytes和Python 2.X中的unicode。
  • 集合可以视为没有值只有键的字典。
  • 除了类型分类操作,所有类型都有可调用的方法。
请注意:运算符重载

在数值类型中,+表示将两个数的值相加;在序列中,+表示拼接两个序列。如果要设计新的类,我们可以定义加号(以及其他运算符)作用于这个类对象的含义。比如,定义类的加法可以用:def __add__(self, other):。
对象灵活性

一般来说:

  • 列表、字典和元组可以包含任何种类的对象;
  • 集合可包含任意的不可变类型对象;
  • 列表、字典和元组可以任意嵌套;
  • 列表、字典和集合可以动态地扩大和缩小。
Python的复合对象类型支持任意结构,因此它们非常适合表示程序中的复杂数据,可以嵌套任意多层。下面是一个嵌套的例子:
  1. >>> L = ['abc', [(1, 2), ([3], 4)], 5]
  2. >>> L[1]
  3. [(1, 2), ([3], 4)]
  4. >>> L[1][1]
  5. ([3], 4)
  6. >>> L[1][1][0]
  7. [3]
  8. >>> L[1][1][0][0]
  9. 3
复制代码
用图表示,就是:

引用vs复制

第6章提到,赋值操作总是存储对象的引用,而不是对象的副本。当涉及到较大的对象时,这种现象会变得微妙:
  1. >>> X = [1, 2, 3]
  2. >>> L = ['a', X, 'b']
  3. >>> D = {'x': X, 'y': 2}
复制代码
修改这三个引用的任意一个共享列表对象X,也会改变另外两个引用的对象:
  1. >>> X[1] = 'surprise'
  2. >>> L
  3. ['a', [1, 'surprise', 3], 'b']
  4. >>> D
  5. {'x': [1, 'surprise', 3], 'y': 2}
复制代码
引用是其他语言中指针的更高级模拟。虽然我们不能获得引用本身,但是我们可以在不止一个地方存储相同的引用。

这意味着,我们可以在程序范围内任何地方传递大型对象而不用复制。如果要复制,需要明确要求:

  • 没有参数的分片表达式L[:]可以复制序列;
  • 字典、集合和列表的copy方法可以复制本身;
  • 内置函数也可以复制,如将list方法应用于列表,dict方法应用于字典等等;
  • copy标准库模块能够在需要时创建完整副本。
列表和字典复制的例子:
  1. >>> L = [1, 2, 3]
  2. >>> D = {'a': 1, 'b': 2}
  3. >>> # 将副本赋值给其他变量
  4. >>> A = L[:]
  5. >>> B = D.copy()
  6. >>> # 由其他变量引发的改变将修改新产生的副本,而不是原有的对象
  7. >>> A[1] = 'Ni'
  8. >>> B['c'] = 'spam'
  9. >>> L, D
  10. ([1, 2, 3], {'a': 1, 'b': 2})
  11. >>> A, B
  12. ([1, 'Ni', 3], {'a': 1, 'b': 2, 'c': 'spam'})
复制代码
但是,copy方法只能进行顶层复制。
  1. >>> L0 = [1, 2, 3]
  2. >>> L1 = ['a', L0, 'b']
  3. >>> L2 = L1.copy()
  4. >>> L2
  5. ['a', [1, 2, 3], 'b']
  6. >>> L2[0] = 'c'
  7. >>> L1, L2
  8. (['a', [1, 2, 3], 'b'], ['c', [1, 2, 3], 'b'])
  9. >>> L2[1][1] = 5
  10. >>> L1, L2
  11. (['a', [1, 5, 3], 'b'], ['c', [1, 5, 3], 'b'])
复制代码
要进行深层复制(完整、独立的复制),需要copy模块中的deepcopy方法。
比较、等价性和真值

所有的Python对象都支持:测试等价性、相对大小等。比较复合对象时,会检查所有的组件,直到得出结果为止。
这种比较也被称为递归比较——对顶层对象的比较会被应用到每一个嵌套的下一次对象中,直到最底层的对象并得出结果。就核心类型而言,递归功能是默认实现的。
在比较列表对象时将自动比较所有内容,直到找到一个不匹配或完成比较:
  1. >>> L1 = [1, 2, 3]
  2. >>> L2 = [1, 2, 3]
  3. >>> L1 == L2
  4. True
  5. >>> L1 is L2
  6. False
复制代码
这里展示了两种测试等价性的方式,分别是:

  • ==运算符测试值的等价性,Python递归地比较所有内嵌对象。
  • is表达式测试对象的同一性,Python测试两者是否为同一个对象(在存储器中有相同地址)。
注意对短字符串的运行结果:
  1. >>> S1 = 'spam'
  2. >>> S2 = 'spam'
  3. >>> S1 == S2
  4. True
  5. >>> S1 is S2
  6. True
复制代码
这是因为,Python会通过重复地理利用短字符串进行优化,因此S1和S2共享同一个'spam'。但这不适用于长字符串:
  1. >>> S1 = 'A Longer String'
  2. >>> S2 = 'A Longer String'
  3. >>> S1 == S2
  4. True
  5. >>> S1 is S2
  6. False
复制代码
相对大小比较也能递归地应用于嵌套数据结构:
  1. >>> L1 = [1, ('a', 3)]
  2. >>> L2 = [1, ('a', 2)]
  3. >>> L1 < L2, L1 == L2, L1 > L2
  4. (False, False, True)
复制代码
Python比较相对大小地规则是:

  • 数字在转换成必要的公共最高级类型后,比较数值地相对大小。
  • 字符串按照字母字典顺序比较(从左到右比较字符的ASCII码大小)。
  • 列表和元组从左到右对每个组件内容进行比较,直到末尾或发现区别。
  • 集合是相等的,当且仅当它们含有相同的元素。集合的比较大小采取子集和超集的标准。
  • 字典通过比较排序后的(key, value)列表判断是否相同。(仅Python 2.X)
  • 非数字不同类型(混合类型)的比较。(仅Python 2.X)
Python 2.X和3.X混合类型比较和排序

Python 2.X中的混合类型通过任意的顺序的比较,但3.X不允许混合顺序比较。
Python 2.X和3.X中的字典比较

在Python 2.X中,字典支持相对大小比较,就等效于比较排序的键/值列表,但是在Python 3.X中,字典之间的比较大小由于开销太大,故被移除。
Python 3.X的替代方式是:要么编写循环键比较值,要么手动比较排序的键/值列表(利用sorted方法):
  1. >>> list(D1.items())
  2. [('a', 1), ('b', 2)]
  3. >>> list(D2.items())
  4. [('a', 1), ('b', 3)]
  5. >>> sorted(D1.items()) < sorted(D2.items())
  6. True
  7. >>> sorted(D1.items()) > sorted(D2.items())
  8. False
复制代码
Python中True和False的含义

在Python中,1表示真,0表示假。实际上,真和假是Python中每个对象的固有属性,规则如下:

  • 数字如果等于0则为假,反之则为真。
  • 其他对象如果为空则为假,反之则为真。
一些是一些例子:
对象"spam"True""False[1, 2]True[]False{'a': 1}True{}False1True0.0FalseNoneFalse这样做会使对象的检查更加简单,如检查字符串是否为空可以简化成if X:,也可以if X != '':。
None对象

None总是为假,这是Python中一种特殊数据类型的唯一值,作用是空占位符。
None不意味着“未定义”,而是某些内容。None是一个真正的对象,有一块真实的内存。None是Python给定的一个内置名称,也是函数的默认返回值。
bool类型

Python的布尔类型bool只是扩展了Python中的真假概念。这种设计只是为了让真值更加显式,程序更明确。
Python还提供了一个内置的函数bool,显式地把对象转换为对象的布尔值。
  1. >>> bool(1)
  2. True
  3. >>> bool('spam')
  4. True
  5. >>> bool({})
  6. False
复制代码
Python的类型层次


类型和对象

即使是类型本身在Python中也是一种类型的对象:对象的类型本身,也属于type类型的对象。
从Python 2.2开始,每个核心类型都有一个新内置名,用来支持通过面向对象编写子类的类型定制:dict、list、tiple、str、int、float、complex、bytes、type、set等。
Python的其他类型

后面要学到的类型:函数、模块和类。以及扩展:正则表达式对象、DBM文件、GUI组件、网络套接字等等。它们(扩展)与核心类型的区别是:内置类型不需要导入模块,但扩展类型需要用import导入模块。
内置类型陷阱

赋值创建引用,而不是复制

可变对象的共享引用在你的程序中至关重要。
如果不想要这种共享,那么使用复制的手段来避免共享。
重复会增加层次深度

这里,当可变序列进行嵌套时,可能会使列表重复,或者列表中嵌套四个列表:
  1. >>> L = [4, 5, 6]
  2. >>> X = L * 4
  3. >>> X
  4. [4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6]
  5. >>> Y = [L] * 4
  6. >>> Y
  7. [[4, 5, 6], [4, 5, 6], [4, 5, 6], [4, 5, 6]]
复制代码
Y包含了指向原本L的列表的引用,因此出现了副作用:
  1. >>> L[1] = 0
  2. >>> X
  3. [4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6]
  4. >>> Y
  5. [[4, 0, 6], [4, 0, 6], [4, 0, 6], [4, 0, 6]]
复制代码
解决方法是:进行复制,这里用list解决:
  1. >>> L = [4, 5, 6]
  2. >>> Y = [list(L)] * 4
  3. >>> Y
  4. [[4, 5, 6], [4, 5, 6], [4, 5, 6], [4, 5, 6]]
  5. >>> L[1] = 0
  6. >>> Y
  7. [[4, 5, 6], [4, 5, 6], [4, 5, 6], [4, 5, 6]]
复制代码
但是,Y对应的列表对象所嵌套的引用仍然指向同一个对象。要避免这种现象,必须保证每一个嵌套有一个单独的副本:
  1. >>> Y[0][1] = 99
  2. >>> Y
  3. [[4, 99, 6], [4, 99, 6], [4, 99, 6], [4, 99, 6]]
  4. >>> L = [4, 5, 6]
  5. >>> Y = [list(L) for i in range(4)]
  6. >>> Y
  7. [[4, 5, 6], [4, 5, 6], [4, 5, 6], [4, 5, 6]]
  8. >>> Y[0][1] = 99
  9. >>> Y
  10. [[4, 99, 6], [4, 5, 6], [4, 5, 6], [4, 5, 6]]
复制代码
注意循环数据结构

如果一个复合对象包含指向自己的引用,就称之为循环对象。Python在检测到循环时,会打印出[...]。
  1. >>> L = [1, 2, 3]
  2. >>> L.append(L)
  3. >>> L
  4. [1, 2, 3, [...]]
复制代码
经验法则:除非真的需要,否则不要使用循环引用。
不可变类型不可以在原位置改变

如果要改变,需要通过分片、拼接等操作创建一份新的对象。

来源:https://www.cnblogs.com/hiu-siu-dou/p/18411402
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具