Python系列(3)- Python 数据类型、推导式、迭代器与生成器
1. 数据类型
Python3 中有六个基本的数据类型:
不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
可以使用内置的 type() 函数可以用来查询变量所指的对象类型,也可以使用 isinstance。isinstance 和 type 的区别在于:
type() 不会认为子类是一种父类类型。
isinstance() 会认为子类是一种父类类型。
1) Number(数字)
Python3 支持 int、float、bool、complex(复数)。
在 Python3 中,只有一种整数类型 int,表示为长整型,没有 python2 中的 Long。
在 Python3 中,bool 是 int 的子类,True 和 False 可以和数字相加,True==1、False==0 会返回 True。
complex(复数)由实数部分和虚数部分构成,可以用 a + bj,或者 complex(a,b) 表示, 复数的实部 a 和虚部 b 都是浮点型。
使用 del 语句删除对象引用,语法格式:
del var1[,var2[,var3[....,varN]]]
示例:
#!/usr/bin/python3 a, b, c, d = 20, 5.5, True, 4+3j print('type(a), type(b), type(c), type(d): ', type(a), type(b), type(c), type(d)) print('isinstance(a, int): ', isinstance(a, int)) print() # 类型判断 class A: pass class B(A): pass print('isinstance(A(), A): ', isinstance(A(), A)) print('type(A()) == A): ', type(A()) == A)) print('isinstance(B(), A): ', isinstance(B(), A)) print('type(B()) == A: ', type(B()) == A) print() # 布尔型 print('issubclass(bool, int): ', issubclass(bool, int)) print('True==1: ', True==1) print('False==0: ', False==0) print('True+1: ', True+1) print('False+1: ', False+1) print() # 数值运算 print('3 + 7: ', 3 + 7) print('4.6 - 2: ', 4.6 - 2) # 在混合计算时,Python 会把整型转换成为浮点数 print('3 * 5: ', 3 * 5) print('5 / 2: ', 5 / 2) # 除法,得到一个浮点数 print('5 // 2: ', 5 // 2) # 除法,得到一个整数 print('17 % 3: ', 17 % 3) print('2 ** 3: ', 2 ** 3) print() del a,b print('del -> a:', a)
输出结果如下:
type(a), type(b), type(c), type(d): <class 'int'> <class 'float'> <class 'bool'> <class 'complex'> isinstance(a, int): True isinstance(A(), A): True type(A()) == A): True isinstance(B(), A): True type(B()) == A: False issubclass(bool, int): True True==1: True False==0: True True+1: 2 False+1: 1 3 + 7: 10 4.6 - 2: 2.5999999999999996 3 * 5: 15 5 / 2: 2.5 5 // 2: 2 17 % 3: 2 2 ** 3: 8 Traceback (most recent call last): File "data_type.py", line 42, in <module> print('del -> a:', a) NameError: name 'a' is not defined
2) String(字符串)
Python 中的字符串用单引号 ' 或双引号 " 括起来,使用反斜杠 \ 转义特殊字符,不想让反斜杠发生转义,可以在字符串前面添加一个 r,表示原始字符串。
反斜杠 \ 可以作为续行符,表示下一行是上一行的延续。也可以使用 """...""" 或者 '''...''' 跨越多行。
Python 没有单独的字符类型,一个字符就是长度为 1 的字符串,字符串内的字符不能修改,整个字符串可以重新赋值。
字符串的截取的语法格式如下:
变量[头下标:尾下标]
索引值以 0 为开始值,-1 为从末尾的开始位置。
加号 + 是字符串的连接符,星号 * 表示复制当前字符串,与之结合的数字为复制的次数。
示例:
#!/usr/bin/python3 str = 'python string' str2 = 'pytho\n string' str3 = r'pytho\n string' print("str: ", str) # 输出字符串 print("str[0:-1]: ", str[0:-1]) # 输出第一个到倒数第二个的所有字符 print("str[0]: ", str[0]) # 输出字符串第一个字符 print("str[2:5]: ", str[2:5]) # 输出从第三个开始到第五个的字符 print("str[2:]: ", str[2:]) # 输出从第三个开始的后的所有字符 print("str * 2: ", str * 2) # 输出字符串两次,也可以写成 print (2 * str) print("str + ' connect': ", str + " connect") # 连接字符串 str = 'new string' print("str2: ", str2) print("str3: ", str3) print("str: ", str)
输出结果如下:
str: python string str[0:-1]: python strin str[0]: p str[2:5]: tho str[2:]: thon string str * 2: python stringpython string str + ' connect': python string connect str2: pytho string str3: pytho\n string str: new string
3) List(列表)
List(列表) 是 Python 中使用最频繁的数据类型。
列表可以完成大多数集合类的数据结构实现。列表中元素的类型可以不相同,它支持数字,字符串甚至可以包含列表(所谓嵌套)。
列表截取的语法格式如下:
变量[头下标:尾下标]
索引值以 0 为开始值,-1 为从末尾的开始位置。
加号 + 是列表连接运算符,星号 * 是重复操作。
格式:
l = [ value1, value2, ... ]
示例:
#!/usr/bin/python3 l1 = [ 'abcd', 456 , 100.07, 'test', 6.99 ] l2 = [ 123, 'good' ] print("l1: ", l1) # 输出完整列表 print("l1[0]: ", l1[0]) # 输出列表第一个元素 print("l1[1:3]: ", l1[1:3]) # 从第二个开始输出到第三个元素 print("l1[2:]: ", l1[2:]) # 输出从第三个元素开始的所有元素 print("l2 * 2: ", l2 * 2) # 输出两次列表 print("l1 + l2: ", l1 + l2) # 连接列表 l1[1] = 'replaced' print("l1: ", l1)
输出结果如下:
l1: ['abcd', 456, 100.07, 'test', 6.99] l1[0]: abcd l1[1:3]: [456, 100.07] l1[2:]: [100.07, 'test', 6.99] l2 * 2: [123, 'good', 123, 'good'] l1 + l2: ['abcd', 456, 100.07, 'test', 6.99, 123, 'good'] l1: ['abcd', 'replaced', 100.07, 'test', 6.99]
4) Tuple(元组)
元组(tuple)与列表类似,不同之处在于元组的元素不能修改。元组写在小括号 () 里,元素之间用逗号隔开,元组中的元素类型可以不相同。
元组与字符串类似,可以被索引且下标索引从 0 开始,-1 为从末尾开始的位置,可以把字符串看作一种特殊的元组。
元组的元素不能修改,但它可以包含可变的对象(比如 list 列表)。元组也可以被索引和切片,方法和列表一样。元组也可以使用 + 操作符进行拼接。
格式:
t = ( value1, value2, ...)
示例:
#!/usr/bin/python3 t1 = ( 'abcd', 456 , 100.07, 'test', 6.99 ) t2 = ( 123, 'good' ) print("t1: ", t1) # 输出完整元组 print("t1[0]: ", t1[0]) # 输出元组的第一个元素 print("t1[1:3]: ", t1[1:3]) # 输出从第二个元素开始到第三个元素 print("t1[2:]: ", t1[2:]) # 输出从第三个元素开始的所有元素 print("t2 * 2: ", t2 * 2) # 输出两次元组 print("t1 + t2: ", t1 + t2) # 连接元组
输出结果如下:
t1: ('abcd', 456, 100.07, 'test', 6.99) t1[0]: abcd t1[1:3]: (456, 100.07) t1[2:]: (100.07, 'test', 6.99) t2 * 2: (123, 'good', 123, 'good') t1 + t2: ('abcd', 456, 100.07, 'test', 6.99, 123, 'good')
构造包含 0 个或 1 个元素的元组比较特殊,所以有一些额外的语法规则:
tup1 = () # 空元组
tup2 = (20,) # 一个元素,需要在元素后添加逗号
string、list 和 tuple 都属于 sequence(序列)。
5) Set(集合)
集合(set)是由一个或数个形态各异的大小整体组成的,构成集合的事物或对象称作元素或是成员。
基本功能是进行成员关系测试和删除重复元素。
可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
格式:
s = {value1, value2, ...}
或
set(value)
示例:
#!/usr/bin/python3 sites = {'Google', 'Taobao', 'Zhihu', 'Baidu'} print("sites: ", sites) # 输出集合,重复的元素被自动去掉 if 'Taobao' in sites : print('Taobao 在集合中') else : print('Taobao 不在集合中') a = set('abracadabra') b = set('alacazam') c = set(['abc', 'edf', 'xyz']) print("a: ", a) print("a - b: ", a - b) # a 和 b 的差集 print("a | b: ", a | b) # a 和 b 的并集 print("a & b: ", a & b) # a 和 b 的交集 print("a ^ b: ", a ^ b) # a 和 b 中不同时存在的元素 print("c: ", c)
输出结果如下:
sites: {'Baidu', 'Google', 'Zhihu', 'Taobao'} Taobao 在集合中 a: {'r', 'b', 'a', 'd', 'c'} a - b: {'r', 'd', 'b'} a | b: {'m', 'r', 'b', 'z', 'a', 'l', 'd', 'c'} a & b: {'c', 'a'} a ^ b: {'b', 'm', 'z', 'l', 'r', 'd'} c: {'xyz', 'abc', 'edf'}
6) Dictionary(字典)
列表是有序的对象集合,字典是无序的对象集合。两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。
字典是一种映射类型,字典用 { } 标识,它是一个无序的 键(key) : 值(value) 的集合。
键 (key) 必须使用不可变类型,在同一个字典中,键(key)必须是唯一的。
格式:
d = {key1 : value1, key2 : value2, key3 : value3, ... }
或
d = dict(value1=key1, value2=key2, value3=key3, ... )
示例:
#!/usr/bin/python3 d1 = {} # 空字典 d1['one'] = "1 - 字典" d1[2] = "2 - 类型" d2 = {'name': 'test', 'code':1, 'site': 'www.test.com'} d3 = dict(Baidu=1, Google=2, Taobao=3) d4 = dict([('Baidu', 1), ('Google', 2), ('Taobao', 3)]) print('d1[\'one\']: ', d1['one']) # 输出键为 'one' 的值 print('d1[2]: ', d1[2]) # 输出键为 2 的值 print('d2: ', d2) # 输出完整的字典 print('d2.keys(): ', d2.keys()) # 输出所有键 print('d2.values(): ', d2.values()) # 输出所有值 print('d3: ', d3) print('d4: ', d4)
输出结果如下:
d1['one']: 1 - 字典 d1[2]: 2 - 类型 d2: {'name': 'test', 'code': 1, 'site': 'www.test.com'} d2.keys(): dict_keys(['name', 'code', 'site']) d2.values(): dict_values(['test', 1, 'www.test.com']) d3: {'Baidu': 1, 'Google': 2, 'Taobao': 3} d4: {'Baidu': 1, 'Google': 2, 'Taobao': 3}
2. 推导式
Python 推导式是一种独特的数据处理方式,可以从一个数据序列构建另一个新的数据序列的结构体。
Python 支持各种数据结构的推导式:
列表(list)推导式
字典(dict)推导式
集合(set)推导式
元组(tuple)推导式
1) 列表(list)推导式
格式:
[表达式 for 变量 in 列表]
[out_exp_res for out_exp in input_list]
或
[表达式 for 变量 in 列表 if 条件]
[out_exp_res for out_exp in input_list if condition]
out_exp_res:列表生成元素表达式,可以是有返回值的函数。
for out_exp in input_list:迭代 input_list 将 out_exp 传入到 out_exp_res 表达式中。
if condition:条件语句,可以过滤列表中不符合条件的值。
示例:
#!/usr/bin/python3 # 过滤掉长度 <= 3 的字符串列表,并将剩下的转换成大写字母 names = ['Bob','Tom','alice','Jerry','Wendy','Smith'] new_names = [name.upper() for name in names if len(name)>3] print(new_names) # 计算 30 以内可以被 3 整除的整数 multiples = [i for i in range(30) if i % 3 == 0] print(multiples)
输出结果如下:
['ALICE', 'JERRY', 'WENDY', 'SMITH']
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
2) 字典(dict)推导式
格式:
{ key_expr: value_expr for value in collection }
或
{ key_expr: value_expr for value in collection if condition }
示例:
#!/usr/bin/python3 # 使用字符串及其长度创建字典 listdemo = ['Google','Baidu', 'Taobao'] newdict = {key:len(key) for key in listdemo} print(newdict) # 提供三个数字,以三个数字为键,三个数字的平方为值来创建字典 dic = {x: x**2 for x in (2, 4, 6)} print(dic) print(type(dic))
输出结果如下:
{'Google': 6, 'Baidu': 6, 'Taobao': 6}
{2: 4, 4: 16, 6: 36}
<class 'dict'>
3) 集合(set)推导式
格式:
{ expression for item in Sequence }
或
{ expression for item in Sequence if conditional }
示例:
#!/usr/bin/python3 # 计算数字 1,2,3 的平方数 setnew = {i**2 for i in (1,2,3)} print(setnew) # 判断不是 abc 的字母并输出 a = {x for x in 'abracadabra' if x not in 'abc'} print(a) print(type(a))
输出结果如下:
{1, 4, 9}
{'d', 'r'}
<class 'set'>
4) 元组(tuple)推导式
元组推导式可以利用 range 区间、元组、列表、字典和集合等数据类型,快速生成一个满足指定需求的元组。
格式:
(expression for item in Sequence )
或
(expression for item in Sequence if conditional )
元组推导式和列表推导式的用法也完全相同,只是元组推导式是用 () 圆括号将各部分括起来,而列表推导式用的是中括号 [],另外元组推导式返回的结果是一个生成器对象。
示例,生成一个包含数字 1~9 的元组:
#!/usr/bin/python3 a = (x for x in range(1,10)) print(a) # a 是生成器对象 print(tuple(a)) # 使用 tuple() 函数,可以直接将生成器对象转换成元组
输出结果如下:
<generator object <genexpr> at 0x7faf6ee20a50>
(1, 2, 3, 4, 5, 6, 7, 8, 9)
3. 迭代器与生成器
1) 迭代器
迭代是 Python 最强大的功能之一,是访问集合元素的一种方式。 迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
字符串,列表或元组对象都可用于创建迭代器。迭代器有两个基本的方法:iter() 和 next()。
迭代器对象可以使用常规 for 语句进行遍历,示例:
#!/usr/bin/python3 list=[1,2,3,4] it = iter(list) for x in it: print (x, end=" ")
输出结果如下:
1 2 3 4
也可以使用 next() 函数,示例:
#!/usr/bin/python3 import sys list=[1,2,3,4] it = iter(list) while True: try: print (next(it), end=" ") except StopIteration: sys.exit()
输出结果如下:
1 2 3 4
2) 自定义迭代器
把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。
__iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。
__next__() 方法(Python 2 里是 next())会返回下一个迭代器对象。
示例,创建一个返回数字的迭代器,初始值为 1,逐步递增 1:
#!/usr/bin/python3 class MyNumbers: def __iter__(self): self.a = 1 return self def __next__(self): x = self.a self.a += 1 return x myclass = MyNumbers() myiter = iter(myclass) print(next(myiter)) print(next(myiter)) print(next(myiter)) print(next(myiter))
执行输出结果为:
1
2
3
4
3) StopIteration
StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。
示例,在 10 次迭代后停止执行:
#!/usr/bin/python3 class MyNumbers: def __iter__(self): self.a = 1 return self def __next__(self): if self.a <= 10: x = self.a self.a += 1 return x else: raise StopIteration myclass = MyNumbers() myiter = iter(myclass) for x in myiter: print (x, end=" ")
执行输出结果为:
1 2 3 4 5 6 7 8 9 10
4) 生成器
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
示例,使用 yield 实现斐波那契数列:
#!/usr/bin/python3 import sys def fibonacci(n): # 生成器函数 a, b, counter = 0, 1, 0 while True: if (counter > n): return yield a a, b = b, a + b counter += 1 f = fibonacci(10) # f 是一个迭代器,由生成器返回生成 while True: try: print (next(f), end=" ") except StopIteration: sys.exit()
输出结果如下:
0 1 1 2 3 5 8 13 21 34 55