python学习笔记--python常用的数据结构list,tuple,dict,set总结

前言

在PHP中,用的最多的数据结构就是数组了。在python中,有几种数据结构是比较常用的,分别是list,tuple,dict和set。

正文

list-列表

列表(list),也是一种结构化的、非标量类型,它是值的有序序列,每个值都可以通过索引进行标识,定义列表可以将列表的元素放在[]中,多个元素用,进行分隔,可以使用for循环对列表元素进行遍历,也可以使用[]或[:]运算符取出列表中的一个或多个元素。
基本用法:

list1 = [1, 3, 5, 7, 100]
print(list1) # [1, 3, 5, 7, 100]
# 乘号表示列表元素的重复
list2 = ['hello'] * 3
print(list2) # ['hello', 'hello', 'hello']
# 计算列表长度(元素个数)
print(len(list1)) # 5
# 索引来访问list中每一个位置的元素,记得索引是从0开始
print(list1[0]) # 1
print(list1[4]) # 100
#当索引超出了范围时,Python会报一个IndexError错误,所以,要确保索引不要越界,记得最后一个元素的索引是len(classmates) - 1

#要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素
print(list1[-1]) # 100
print(list1[-3]) # 5

#列表使用append方法追加元素到末位:
# 添加元素
list1.append(200)
list1.insert(1, 400)
# 合并两个列表
list1.extend([1000, 2000])
# 先通过成员运算判断元素是否在列表中,如果存在就删除该元素
if 3 in list1:
	list1.remove(3)
if 1234 in list1:
    list1.remove(1234)

列表切片
L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素,记住:倒数第一个元素的索引是-1

fruits = ['grape', 'apple', 'strawberry', 'waxberry']
fruits += ['pitaya', 'pear', 'mango']
# 列表切片 从索引1开始,取出3个元素
fruits2 = fruits[1:4]
print(fruits2) # apple strawberry waxberry

L = list(range(100))
#前10个数:
L[:10]
#后10个数:
 L[-10:]
#前10个数,每两个取一个:
L[:10:2]
#所有数,每5个取一个:
L[::5]
#实现倒序
L[::-1]
列表生成式

列表生成式:非常简单却强大的可以用来创建list的生成式

>>> a = [x for x in range(1,23)]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
>>> a = [x*x for x in range(1,5)]
>>> a
[1, 4, 9, 16]

tuple-元组

classmates = ('Michael', 'Bob', 'Tracy')
#空元组
t = ()
#一个元素的元组
t = (1,)

元组没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,但不能赋值成另外的元素。

提问:已经有了列表这种数据结构,为什么还需要元组这样的类型呢?

  1. 元组中的元素是无法修改的,事实上我们在项目中尤其是多线程环境(后面会讲到)中可能更喜欢使用的是那些不变对象(一方面因为对象状态不能修改,所以可以避免由此引起的不必要的程序错误,简单的说就是一个不变的对象要比可变的对象更加容易维护;另一方面因为没有任何一个线程能够修改不变对象的内部状态,一个不变对象自动就是线程安全的,这样就可以省掉处理同步化的开销。一个不变对象可以方便的被共享访问)。所以结论就是:如果不需要对元素进行添加、删除、修改的时候,可以考虑使用元组,当然如果一个方法要返回多个值,使用元组也是不错的选择。
  2. 元组在创建时间和占用的空间上面都优于列表。我们可以使用sys模块的getsizeof函数来检查存储同样的元素的元组和列表各自占用了多少内存空间,这个很容易做到。我们也可以在ipython中使用魔法指令%timeit来分析创建同样内容的元组和列表所花费的时间,下图是我的macOS系统上测试的结果。

生成器

只要把一个列表生成式的[]改成(),就是一个生成器, 相比生成式生成器不占用存储数据的空间

>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

set -集合

集合不允许有重复元素,而且可以进行交集、并集、差集等运算
它是一组key的集合,但不存储value,由于key不能重复,所以,在set中,没有重复的key。

set1 = {1, 2, 3, 3, 3, 2}
print(set1)
set1.add(4)
set1.add(5)
set2.update([11, 12])
set2.discard(5)
if 4 in set2:
    set2.remove(4)

# 集合的交集、并集、差集、对称差运算
print(set1 & set2)
# print(set1.intersection(set2))
print(set1 | set2)
# print(set1.union(set2))
print(set1 - set2)
# print(set1.difference(set2))
print(set1 ^ set2)
# print(set1.symmetric_difference(set2))
# 判断子集和超集
print(set2 <= set1)
# print(set2.issubset(set1))
print(set3 <= set1)
# print(set3.issubset(set1))
print(set1 >= set2)
# print(set1.issuperset(set2))
print(set1 >= set3)
# print(set1.issuperset(set3))

## 对集合进行运算的时候可以调用集合对象的方法,也可以直接使用对应的运算符,例如&运算符跟intersection方法的作用就是一样的,但是使用运算符让代码更加直观

dict-字典

字典是另一种可变容器模型,可以存储任意类型对象,与列表、集合不同的是,字典的每个元素都是由一个键和一个值组成的“键值对”,键和值通过冒号分开。
字典类似于PHP中的数组,通过key可以定位到value,查找速度非常快,用途非常广泛

>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95
#dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value
>>> d.get('Thomas', -1)
-1

# dict的items()可以同时迭代key和value  遍历
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> for k, v in d.items():
...     print(k, '=', v)
...
y = B
x = A
z = C

dict内部存放的顺序和key放入的顺序是没有关系的。

和list比较,dict有以下几个特点:

  • 查找和插入的速度极快,不会随着key的增加而变慢;
  • 需要占用大量的内存,内存浪费多。

而list相反:

  • 查找和插入的时间随着元素的增加而增加;
  • 占用空间小,浪费内存很少。 所以,dict是用空间来换取时间的一种方法。

总结

关于这几种数据类型还有很多探讨的地方:
比如字典内部是怎么实现的,key冲突了要怎么解决,二维字典排序遍历等,
比如set一般是用在哪些情景上,有什么好处,
比如tuple如何在多线程上活用?
还有很多东西需要慢慢深究,这里留下的问题,后面学习到再总结下。

发布了15 篇原创文章 · 获赞 21 · 访问量 7943

猜你喜欢

转载自blog.csdn.net/weixin_42050895/article/details/103945611