Python提供的四种基础数据结构:list,tuple,set和dict。本文主要围绕这几种数据结构,介绍它们的各种用法。
用法一:解压序列和赋值
In [1]: employee = ['Kenny', 'Software Engineer', 30]
In [2]: name, title, age = employee
In [3]: name
Out[3]: 'Kenny'
In [4]: title
Out[4]: 'Software Engineer'
In [5]: age
Out[5]: 30
# 解压字符串
In [6]: h,e,l,l,o = 'hello'
In [7]: h
Out[7]: 'h'
In [8]: e
Out[8]: 'e'
# 部分解压
In [12]: name,_,_ = employee
In [13]: name
Out[13]: 'Kenny'
# 通过*号匹配多个值。如果*变量位于最末,那匹配到的也是一个list,即使这个list里面没有任何元素
In [20]: *begin, nine, ten = nums
In [21]: begin
Out[21]: [1, 2, 3, 4, 5, 6, 7, 8]
In [22]: nine
Out[22]: 9
In [23]: ten
Out[23]: 10
# 一个例子
In [27]: htmltags = [('url', 'www.baidu.com', 'www.sina.com.cn', 'www.zhihu.com'),
...: ('img','~/pics/a.png'),
...: ('p','段落1','段落2', '段落3', '段落4')]
In [28]: for tag, *content in htmltags:
...: if tag == 'url':
...: print('urls: ', *content)
...: else:
...: print('rest')
...:
urls: www.baidu.com www.sina.com.cn www.zhihu.com
rest
rest
用法二:可变长的参数列表
- 参数传递:如果函数的参数列表中,包含多个参数。我们可以使用一个列表来承载,传递的时候,在这个列表前方加上一个。如果使用一个字典来承载,那么则需要两个*。
- 定义冗余参数(可变参数列表): 参数列表的最后两个参数,可以通过列表和字典来接收。
# 参数传递
In [21]: def calc_price(unit = 100, unitprice = 0.5):
...: print("%d斤大白菜,单价%.2f元,总价是%.2f元。" % (unit, unitprice, unit*unitprice))
In [22]: calc_price()
100斤大白菜,单价0.50元,总价是50.00元。
In [23]: unit_price = [200, 0.3]
In [24]: calc_price(*unit_price)
200斤大白菜,单价0.30元,总价是60.00元。
In [25]: unit_price = {'unit':300, 'unitprice':0.3}
In [26]: calc_price(**unit_price)
300斤大白菜,单价0.30元,总价是90.00元。
# 定义冗余参数
In [33]: def func(a,b,*args):
...: print('a = ', a)
...: print('b = ', b)
...: if len(args) > 0:
...: print('args = ', args)
...:
In [34]: func(1,2)
a = 1
b = 2
In [35]: func(1,2,3,4,5,6)
a = 1
b = 2
args = (3, 4, 5, 6)
In [36]: def func(a,b,*args, **kv):
...: print('a = ', a)
...: print('b = ', b)
...: if len(args) > 0:
...: print('args = ', args)
...: for k in kv:
...: print('key = %s, value = %s'% (k, kv[k]))
In [37]: func(1,2,3,4,5, name = 'xxx', age = 12)
a = 1
b = 2
args = (3, 4, 5)
key = name, value = xxx
key = age, value = 12
用法三:切片操作
列表的索引与数组一样,也是从0开始到length-1结束。python中,列表的元素的索引可以是正序也可以是逆序。如下表所示:
h | e | l | l | o | w | o | r | l | d | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
-11 | -10 | -9 | -8 | -7 | -6 | -5 | -4 | -3 | -2 | -1 |
我们可以通过下标取出特定的某个元素,也可以通过切片操作从列表中取出一部分元素。切片的语法为:alist[start:end:step],其中:
- start:从下标start开始取,并且包括下标为start的这个元素。如果不指定start,则表示从头,也就是第一个元素开始。
- end:到下标end结束,但不包括下标为end的这个元素。如果不指定end,则表示取到最后一个,并且包括最后一个元素。
- step:每隔step个元素进行取值,默认为1。
# 取单一的元素
In [35]: helloworld = 'hello world'
In [36]: helloworld[10]
Out[36]: 'd'
In [37]: helloworld[-1]
Out[37]: 'd'
# 从起始位置开始取
In [43]: helloworld[:5]
Out[43]: 'hello'
In [44]: helloworld[:-5]
Out[44]: 'hello '
# 从某个位置到末尾
In [45]: helloworld[6:]
Out[45]: 'world'
In [46]: helloworld[-5:]
Out[46]: 'world'
# 取某个区间的值
In [47]: helloworld[6:10]
Out[47]: 'worl'
# 设置取值的跨度
In [49]: helloworld[::2]
Out[49]: 'hlowrd'
In [50]: helloworld[::3]
Out[50]: 'hlwl'
用法四:遍历
任何一种迭代器,都是可以通过for...in...来遍历。此外,还可以通过next()和StopIteration异常来手动遍历迭代器
In [53]: for char in helloworld:
...: print(char)
In [54]: for index in range(len(helloworld)):
...: print(helloworld[index])
In [58]: adict = {"五香牛肉粉":13, "红烧牛肉粉":13, "什锦粉":16, "卤鸡腿粉":15}
In [59]: for key in adict:
...: print(adict[key])
# 手动遍历
In [69]: myiter = iter(helloworld)
In [70]: while True:
...: try:
...: char = next(myiter)
...: print(char)
...: except StopIteration:
...: break
...:
# 反向遍历
In [71]: for char in reversed(helloworld):
...: print(char)
用法五:推导式(表达式)和生成器
推导式:实际上是一种便捷的遍历语法,最终的结果还是一个列表
- [expr for iter_var in iterable]
- [expr for iter_var in iterable if cond_expr]
# 例:对整数列表里的每个元素平方操作
In [72]: [x**2 for x in range(1,11)]
Out[72]: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 例:求偶数
In [73]: [x for x in range(1,11) if x%2 == 0]
Out[73]: [2, 4, 6, 8, 10]
# 例:求100以内的质数(除了能被1和自己整除外,就没有别的因数)
# if后面跟着一个判断式,如果后面的变量是None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()时,这个判断式的结果是False;所以加上not就相当于取反,那就是True
In [87]: [x for x in range(2,100) if not [j for j in range(2,x) if x % j ==0 ]]
生成器:是一种特殊的迭代器,可以通过便捷语法和生成器函数(yield)来创建。生成器的结果,顾名思义就是一个生成器。与迭代器类似,可以通过for...in...或者next()/StopIteration来遍历
便捷语法:
- (expr for iter_var in iterable)
- (expr for iter_var in iterable if cond_expr)
# 生成器表达式
In [96]: even_nums = (i for i in range(1,11) if i%2 == 0)
In [97]: type(even_nums)
Out[97]: generator
# 生成器函数
In [98]: def get_even_number(max):
...: for i in range(1, max):
...: if i%2 == 0:
...: yield i
...:
In [99]: even_nums_1 = get_even_number(11)
In [100]: type(even_nums_1)
Out[100]: generator
# 手动遍历生成器
In [104]: even_nums = (i for i in range(1,11) if i%2 == 0)
In [105]: while True:
...: try:
...: print(next(even_nums))
...: except StopIteration:
...: break
表达式VS生成器:表达式的结果是直接会生成一个列表,实实在在占用内存。但是生成器表达式,是一种lazy load技术,返回的结果是一个生成器。当程序中使用到具体的列表项的时候,才会返回。