列表、元组、字符串属于序列,字典属于映射,集合不属于2者其中之一。
在序列中,每个元素都有编号。
1、元组(tuple)
与列表类似,但元组是不可变的,可简单将其看作是不可变的列表,元组常用于保存不可修改的内容。
# 效率比列表效率高
# 1、创建
# 元组中所有元素都放在一个小括号 () 中,相邻元素之间用逗号 , 分隔
# 元组中至少包含一个逗号,即使只有一个元素,否则,括号会被看成数学公式的括号
# type((18)), type((18,)) # (int, tuple)
# 2 、删除
# 元组中的元素不能被删除,我们只能删除整个元组,重新分配一个新的元组
# del Keyword
# 注意del是python关键字,就像def、and、or一样。它不是字典、列表的方法,但是可以用来删除字典、列表的元素
t1 = ()
print(t1)
t2 = (1, 3, 5)
print(t2)
# list->tuple
t3 = tuple([x for x in range(4) if x % 2 == 0])
print(t3)
t4 = tuple("abc")
print(t4)
t5 =("abc","def","ghi")
print(t5)
del t5
print(t5)
# 输出:
# ()
# (1, 3, 5)
# (0, 2)
# ('a', 'b', 'c')
# ('abc', 'def', 'ghi')
# NameError: name 't5' is not defined
# 推导
s={i:"{} squared is {}".format(i,i**2) for i in range(10)}
print(s[0]) # 0 squared is 0
还有一些序列的函数,len(),min(),max()
多变量赋值
注一: 不能单独使用 说明:等号左边只有一个标识符,无法解构
注二:不能多次同时使用
注三:另外一种丢弃变量下划线:’ _ ’
说明: ’ _ '是合法的标识符,大多场景表示不关心该值。
交换赋值
a,b = b, a
2、集合
可以存储不同类型元素,除了列表外都是哈希的
# 2、集合
# 只存储 key,集合的元素是不重复,不是按任何的特定顺序放置
# 集合使用花括号 {} 或者 set() 函数创建,如果创建空集合只能使用 set() 函数,以创建集合 s 为例
s1 = set()
print(s1)
s2={1,3,4}
print(s2)
# tuple->set
s3=set((1,3,5))
print(s3)
# list->set
s4=set([x for x in range(5)])
print(s4)
# 字符串的字符成为元素
s5=set("abac")
print(s5)
# set()
# {1, 3, 4}
# {1, 3, 5}
# {0, 1, 2, 3, 4}
# {'b', 'c', 'a'}
2.1、操作和访问集合
2.1.1 判断是否存在
in 或not in 判断是否元素在集合
2.1.2 增加
添加元素可以使用 add ,如果元素已经存在,则不进行操作
一、调用方法add(一次只添加一个元素)
In [1]: s1 = {2,3,5}
...: s1.add(6)
...: s1
...:
Out[1]: {2, 3, 5, 6}
二、调用方法update(一次至少添加一个元素)
In [1]: s = {2,3,5}
In [2]: s.update({2,8});s
Out[2]: {2, 3, 5, 8}
In [3]: s.update({1,4});s
Out[3]: {1, 2, 3, 4, 5, 8}
In [4]: s.update((6,7));s
Out[4]: {1, 2, 3, 4, 5, 6, 7, 8}
2.1.3 删除 remove(key) discard(key)
一、调用方法remove(一次只删除一个指定的元素)
如果指定的元素在集合中不存在,抛出KeyError。
In [1]: s={3,4,5,6,7}
...: s.remove(5)
...: s
...:
Out[1]: {3, 4, 6, 7}
二、调用方法discard(一次只删除一个指定的元素)
与方法remove不同的是:如果指定的元素在集合中不存在,不会抛出KeyError。
In [3]: s
Out[3]: {3, 4, 6, 7}
三、调用方法pop(一次只删除一个任意的元素)
该方法返回被删除的元素
In [4]: s.pop()
Out[4]: 3
In [5]: s
Out[5]: {4, 6, 7}
四、调用方法clear清空集合
In [6]: s.clear()
In [7]: s
Out[7]: set()
2.2、子集和超集
一个集合是否是另一个集合的子集
可以调用方法 issubset 进行判断。
一个集合是否是另一个集合的超集
可以调用方法 issuperset 进行判断。
s1是s2的真子集=》s1<s2
s1是s2的子集=》s1<=s2
s1是s2的真超集=》s1>s2
In [1]: s1 = {1, 2, 3}
...: s2 = {1, 3, 4, 5, 2, 6}
...:
In [2]: s1.issubset(s2)
Out[2]: True
In [3]: s1.issuperset(s2)
Out[3]: False
In [4]: s1 < s2
Out[4]: True
In [5]: s1 <= s2
Out[5]: True
In [6]: s2 > s1
Out[6]: True
2.3、判断元素是否完全相同
两个集合是否相等
可以使用运算符==和!=进行判断。
s1 = {1, 2, 3}
s2 = {1, 3, 2}
print(s1 == s2) # True
print(s1 != s2) # False
2.4 判断是否有交集
In [1]: s1 = {1,3,5,7,9}
In [2]: s2 = {2,3,6,7,10}
In [3]: s3 = {2,4,6,8,10}
In [4]: s1.isdisjoint(s2)
Out[4]: False
In [5]: s1.isdisjoint(s3)
Out[5]: True
2.5、集合数学运算 (并集 交集 差集 异或)
2.5.1 并集
并集 union 或 |
调用方法union和使用运算符|是等价的。
做并集操作后生成一个新集合,做并集操作的两个集合不变。
注意:不存在方法union_update()。
In [1]: s1 = {1, 2, 3}
...: s2 = {3, 4, 5}
...: s1.union(s2)
Out[1]: {1, 2, 3, 4, 5}
In [2]: s1 | s2
Out[2]: {1, 2, 3, 4, 5}
2.5.2 交集
交集 intersection 或&
调用方法intersection 和使用运算符&是等价的。
做交集操作后生成一个新集合,做交集操作的两个集合不变。
s1.intersetction_update(s2)的执行结果:
用s1.intersection(s2)的返回值更新s1,s2不变。
方法intersetction_update的返回值为None,结果写入s1
In [1]: s1 = {3, 2, 4}
...: s2 = {2, 3, 9, 10}
...: s1.intersection(s2)
...:
Out[1]: {2, 3}
In [2]: s2 & s1
Out[2]: {2, 3}
In [3]: s1,s2
Out[3]: ({2, 3, 4}, {2, 3, 9, 10})
In [4]: s1.intersection_update(s2)
In [5]: s1,s2
Out[5]: ({2, 3}, {2, 3, 9, 10})
2.5.3 差集
差集 s1.difference(s2) 或 s1-s2
做差集操作后生成一个新集合,做差集操作的两个集合不变。
sl.difference_update(s2)的执行结果:
用s1.difference(s2)的返回值更新s1,s2不变。
方法difference_update的返回值为None。
In [1]: s1 = {1, 2, 3}
...: s2 = {2, 3, 4}
...: s1.difference(s2)
...:
Out[1]: {1}
In [2]: s1 - s2
Out[2]: {1}
In [3]: s1,s2
Out[3]: ({1, 2, 3}, {2, 3, 4})
In [4]: s1.difference_update(s2)
In [5]: s1,s2
Out[5]: ({1}, {2, 3, 4})
2.5.4 异或 ( 对称差集)
异或 ( 对称差集) symmetric_difference 或 ^
做对称差集操作后生成一个新集合,做对称差集操作的两个集合不变。
s1.symmetric_difference_update(s2)的执行结果:
用s1.symmetric_difference(s2)的返回值更新sl,s2不变。
方法symmetric_difference_update的返回值为None。
In [1]: s1 = {1, 2, 3}
...: s2 = {2, 3, 4}
...: s1.symmetric_difference(s2)
...:
Out[1]: {1, 4}
In [2]: s1 ^ s2
Out[2]: {1, 4}
In [3]: s1,s2
Out[3]: ({1, 2, 3}, {2, 3, 4})
In [4]: s1.symmertric_difference_update(s2)
In [5]: s1,s2
Out[5]: ({1, 4}, {2, 3, 4})
2.7、总结集合与列表性能
对于in、not in 、remove,集合效率较高
集合不支持下标运算符
查找、删除元素,集合快
2.7.1 校验查找和删除速度
import random
import time
NUMBER_OF_ELEMNTS = 10000
# create a list
lst =list(range(NUMBER_OF_ELEMNTS))
random.shuffle(lst)
# create a set
s = set(lst)
# test if in list
startTime = time.time()
for i in range(NUMBER_OF_ELEMNTS):
i in lst
endTime = time.time()
print("Test time of find element in list :", int((endTime - startTime) * 1000))
# test if in set
startTime = time.time()
for i in range(NUMBER_OF_ELEMNTS):
i in s
endTime = time.time()
print("Test time of find element in set :", int((endTime - startTime) * 1000))
# test time delete list
startTime = time.time()
for i in range(NUMBER_OF_ELEMNTS):
lst.remove(i)
endTime = time.time()
print("Test time of delete element in list :", int((endTime - startTime) * 1000))
# test time delete set
startTime = time.time()
for i in range(NUMBER_OF_ELEMNTS):
s.remove(i)
endTime = time.time()
print("Test time of delete element in set :", int((endTime - startTime) * 1000))
# 单位:毫秒 测试结果:
# Test time of find element in list : 735
# Test time of find element in set : 0
# Test time of delete element in list : 373
# Test time of delete element in set : 0
2.8 不可变集合 fronzenset
In [1]: print(frozenset())
frozenset()
In [2]: print(frozenset(range(1, 6)))
frozenset({1, 2, 3, 4, 5})
In [3]: print(frozenset([3, 5, 9, 2, 6]))
frozenset({2, 3, 5, 6, 9})
In [4]: print(frozenset((3, 5, 9, 2, 6)))
frozenset({2, 3, 5, 6, 9})
In [5]: print(frozenset('35926'))
frozenset({'6', '9', '5', '2', '3'})
In [6]: print(frozenset({3, 5, 9, 2, 6}))
frozenset({2, 3, 5, 6, 9})
3、字典
除了列表和元组,字典也是Python语言提供的内置数据结构之一。
一、字典的实现原理
字典的实现原理和查字典是类似的。当我们在字典中查找某个字时,一种办法是从字典的第一页开始
往后翻,直到找到我们要查找的字为止。这种办法就是在列表中查找元素的办法,其缺点是:字典中的字数越多查找效率越低。第二种办法是先在字典的索引表里(比如部首表)查找这个字对应的页码,然后直接翻到这个字对应的页,其优点是:查找效率不会随着字典中字数的增加而降低,无论查找哪个字,查找速度都非常快。
二、字典的特点
1、字典中的所有元素都是一个key-value对,通过指定的key总能映射到唯一确定的value。
字典中不可以存在重复的key,但是可以存在重复的value。
2、字典中的元素是无序的。
顺序不重要,重要的是key和value的映射关系。
3、字典中的key必须是不可变对象。
存取字典中的key-value对时,系统会调用内置函数hash根据指定的key计算出value的存储位置,也就是哈希值。对于指定的key,为了保证每次计算出的哈希值都是相同的,要求key必须是不可变对象。也就是说,只有不可变对象才存在哈希值。
4、字典可以根据需要动态地伸缩
系统会根据需要动态地分配和回收内存,因此在使用前无须预先声明字典的容量。
5、字典会浪费较大的内存
与列表相比,是用空间换取了时间。
# keys():tuple 返回的是序列,用tuple表示
# values():tuple 返回一个由字典中的值组成的字典视图,可能重复
# items():tuple
# clear():None
# get(key):value
# get(key) 访问不存在的key时,不会报错,返回None
# get(key,defaultValue) 查询不到回复defaultValue
# setdefault()如果查询不到,就添加指定的键-值对
# pop(key):value
# popitem():tuple 方法随机返回并删除字典中的最后一对键和值。
# 如果字典已经为空,却调用了此方法,就报出KeyError异常。
3.1、创建:
dict 拥有良好的查询速度,dict 中的值可以是任意 Python 对象,多次对一个 key 赋 value,后面的 value 会把前面的 value 覆盖。
字典的内容在花括号 {} 内,键-值(key-value)之间用冒号 : 分隔,键值对之间用逗号 , 分隔,比如创建字典 d
一、 使用{} 表示
d = {'name': '小明', 'age': '18'}
二、使用 dict 类构造函数
方式一 list
d = dict([('name', '小明'), ('age', 18)])
方式二 tuple
d = dict(name='小明', age='18')
方式三 dict
d = dict({'name':'小明', 'age':'18'})
方式四 zip
d = dict(zip(['age','name'],['18','小明']))
方式五 空字典
d = dict()
d = {}
print(d) # {}
三、调用dict的方法fromkeys(iterable, value=None, /)
调用dict的方法fromKeys
调用该方法时通过参数指定所有的key,所有value的默认值都为None。
In [1]: dict.fromkeys(['name','age'])
Out[1]: {'age': None, 'name': None}
指定所有value的值
In [2]: dict.fromkeys(['name','age'], 'None')
Out[2]: {'age': 'None', 'name': 'None'}
3.2、访问、添加、修改
3.2.1 字典中的值通过 key 进行访问
3.2.2 修改操作
# 一、为已经存在的key赋予一个新的value值(一次只修改一个key对应的value)
d = {'name':'Jack', 'age':18}
d["name"] = "朱小明"
print(d)
# 二、调用方法update(一次至少修改一个key对应的value)
In [5]: d = {'name':'Jack', 'age':18}
In [6]: d.update({'name':'猪小妹'})
In [7]: d
Out[7]: {'age': 18, 'name': '猪小妹'}
In [8]: d.update([('name','猪猪侠'), ('age',20)])
In [9]: d
Out[9]: {'age': 20, 'name': '猪猪侠'}
In [10]: d.update(name='猪', age=12)
In [11]: d
Out[11]: {'age': 12, 'name': '猪'}
In [12]: d.update(name='猪三', age=13, sex='男')
In [13]: d
Out[13]: {'age': 13, 'name': '猪三', 'sex': '男'}
3.2.3 添加操作
d["address"] = "中国" # 如果有这个Key,则newValue取代oldValue
print(d) # {'name': '小明', 'age': '18', 'address': '中国'}
#如果想要往字典中添加key-value对,常见的方式有两种:
#一、为不存在的key赋予一个value值一次只添加一个key-value对
d = {'name':'Jack','age':18}
d['gender']='男'
print(d)
# {name':Jack','age':18,gender':']
#二、调用方法update(一次至少添加一个key-value对)
d = {'name':'Jack','age':18}
d.update({'gender':'男','score':90})
d.update([('gender','男'),('score',90)])
d.update(gender='男',score=90)
print(d)
#'name':Jack','age':18,'gender':'score':901
3.2.4 删除操作 pop(key) ,del dict[key], popitem(),clear()
调用方法pop(一次只删除一个指定key的key-value对)
该方法返回指定的key对应的value。
如果指定的key不存在,抛出KeyError。
为了防止指定的key不存在时抛出KeyError,可以通过参数指定一个默认返回的value。
In [1]: d = {'name': 'Jack', 'age': 18, 'gender': '男'}
In [2]: d
Out[2]: {'age': 18, 'gender': '男', 'name': 'Jack'}
In [3]: d.pop('age')
Out[3]: 18
In [4]: d.pop('age')
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-4-12cb30627781> in <module>()
----> 1 d.pop('age')
KeyError: 'age'
In [5]: d.pop('age','None')
Out[5]: 'None'
del (一次只删除一个指定key的key-value对)
如果指定的key不存在,抛出KeyError。
del d["age"]
popitem 调用方法oopitem(一次只删除一个任意的key-value对)
该方法返回被删除的key-value对。
如果字典已经为空,却调用了此方法,就报出KeyError异常。
In [1]: d = {'name': 'Jack', 'age': 18, 'gender': '男'}
...: d.popitem()
...:
Out[1]: ('gender', '男')
In [2]: d
Out[2]: {'age': 18, 'name': 'Jack'}
清空操作
d.clear()
3.3、设置默认值
In [1]: d = {'name': 'Jack'}
In [2]: d.setdefault('age',0)
Out[2]: 0
In [3]: d
Out[3]: {'age': 0, 'name': 'Jack'}
等效于
In [4]: if 'age' not in d: d['age'] = 0
In [5]: d
Out[5]: {'age': 0, 'name': 'Jack'}
3.3、视图
视图会随字典变化而变化,可以for 视图变量
In [1]: d = {'name': 'Jack', 'age': 18}
In [2]: keys = d.keys()
...: print(keys)
...: print(list(keys))
...:
dict_keys(['name', 'age'])
['name', 'age']
In [3]: values = d.values()
...: print(values)
...: print(list(values))
...:
dict_values(['Jack', 18])
['Jack', 18]
In [4]: items = d.items()
...: print(items)
...: print(list(items))
...:
dict_items([('name', 'Jack'), ('age', 18)])
[('name', 'Jack'), ('age', 18)]
字典可以使用== ,!=来判断是否元素相同
也可以用 in ,not in 判断是否存在
不可以用<,>,<=,>=等进行比较,因为条目没有顺序
.
3.5、复制
# 1、copy 浅复制 deepcopy 深复制
from copy import deepcopy
x={"username":"a","machine":['1','2','3']}
y=x.copy()
z=deepcopy(x)
x['machine'].remove('2')
print(y) # {'username': 'a', 'machine': ['1', '3']}
print(z) # {'username': 'a', 'machine': ['1', '2', '3']}
# 2、fromkeys 创建空字典
x=dict.fromkeys(['name','key'])
y=dict.fromkeys(['name','key'],'(unknown)')
print(x) # {'name': None, 'key': None}
print(y) # {'name': '(unknown)', 'key': '(unknown)'}
3.6、字典格式化:
3.6.1 一、使用百分号作为占位符
In [1]: phonebook={'张三':'13333333333',
...: '李四':'4444444444',
...: '王五':'15555555555',
...: '赵六':'16666666666'}
...: print('王五的号码:%s,张三的号码:%s' % (phonebook['王五'],phonebook['张三']))
...:
王五的号码:15555555555,张三的号码:13333333333
当定义的格式化字符串中的占位符是百分号,并且占位符对应的实际值来自于某个字典的value时,
可以把所有的实际值改写为字典,同时根据字典的value对应的key在占位符%的后面添加:(字典的key)。
其中,字典的key会被添加一对引号,因此,如果字典的key是字符串,需要去掉字典的key自带的引号。
In [2]: print('王五的号码:%(王五)s,张三的号码:%(张三)s'%phonebook)
王五的号码:15555555555,张三的号码:13333333333
3.6.2 使用花括号作为占位符
当定义的格式化字符串中的占位符是花括号,并且占位符对应的实际值来自某个字典的value时,可以
调用方法format_map并把该字典直接作为方法的参数,同时根据字典的value在花括号中指定对应的key:
[字典的key}。其中,字典的key会被添加一对引号,因此,如果字典的key是字符串,需要去掉字典的key 自带的引号。
In [1]: phonebook={'张三':'13333333333',
...: '李四':'4444444444',
...: '王五':'15555555555',
...: '赵六':'16666666666'}
In [2]: print('王五的号码:{},张三的号码:{}' .format(phonebook['王五'],phonebook['张三']))
王五的号码:15555555555,张三的号码:13333333333
In [3]: print('王五的号码:{王五},张三的号码:{张三}' .format_map(phonebook))
王五的号码:15555555555,张三的号码:13333333333
4、实例:
4.1、用字典存储,用列表排序
# 实例:统计文件中单词出现次数,字典有的出现+1,没有的添加字典+1,出现次数,由高到低显示
# 用字典存储,用列表排序
def main():
readFromText()
def readFromText():
filename = input("Enter a filename").strip() # C:\Users\Lenovo\Desktop\1.txt
infile = open(filename, "r")
wordCounts = {}
for line in infile:
processCount(line.lower(), wordCounts)
# 排序
lst = list(wordCounts.items())
newLst = [[x, y] for (y, x) in lst] # 2维的列表
newLst.sort()
for i in range(len(newLst) - 1, len(newLst) - 11, -1):
print(newLst[i][1], "--", newLst[i][0])
infile.close()
# count words
def processCount(line, wordCounts):
line = replacePunctuation(line)
words = line.split() # 列表
for word in words:
if word in wordCounts:
wordCounts[word] += 1
else:
wordCounts[word] = 1
# replace punctuation in the line with space
def replacePunctuation(line):
for ch in line:
if ch in "~!@#$%^&*()_+{}[]|\"';:?/>.<,":
line = line.replace(ch, " ")
return line
main()
4.2实例:简单的数据库
# 字典简单数据库
people = {'Alice': {'phone': '1234', 'addr': '中国'},
'Beth': {'phone': '2344', 'addr': '巴西'}}
label = {'phone': 'phone number', 'addr': "address"}
name = input("Enter a name")
if name in people:
request = input("phone number (p) or address(a)")
if request == 'p':
key = 'phone'
else:
key = 'addr'
print("{}'s {} is {}".format(name, label[key], people[name][key]))
4.3 改进的简单数据库
# 字典简单数据库
people = {'Alice': {'phone': '1234', 'addr': '中国'},
'Beth': {'phone': '2344', 'addr': '巴西'}}
labels = {'phone': 'phone number', 'addr': "address"}
name = input("Enter a name")
request = input("phone number (p) or address(a)")
key=request
if request == 'p':
key = 'phone'
if request=='a':
key = 'addr'
person=people.get(name,{})
label=labels.get(key,key)
result=person.get(key,"is not available")
print("{}'s {} is {}".format(name,label,result))
5、reverse()和reversed()
-
reverse():- - 该方法是对原来list内存的修改
是python中列表的一个内置方法(也就是说,在字典,字符串或者元组中,是没有这个内置方法的),用于列表中数据的反转; -
reversed():- - python内建函数,返回一个新的对象
作用:反向迭代序列
而reversed()是python自带的一个方法
reverse(sequence) - >反转迭代器的序列值
返回反向迭代器
也就是说,在经过reversed()的作用之后,返回的是一个把序列值经过反转之后的迭代器,所以,需要通过遍历,或者List,或者next()等方法,获取作用后的值
In [1]: a = [1,3,5,7]
In [2]: a.reverse()
In [3]: a
Out[3]: [7, 5, 3, 1]
a=[1,3,5,7]
print(list(reversed(a)))
print(a)
b=(1,2,3,4)
print(tuple(reversed(b)))
print(b)
d=[1,2,4,5]
print(d[::-1])
print(d)
6、sorted(key,reverse)
–作用于任何序列,总是返回一个有序序列
a=[1,10,9,7]
print(list(sorted(a)))
print(a)
b=(1,8,5,4)
print(tuple(sorted(b)))
print(b)
sorted()中的key可以是str.lower
# 元组排序可通过list函数将元组转换成列表,采用列表排序方法
# 1、最简单的排序,sort()对列表直接排序,返回None
a=[2,1,4]
a.sort()
print(a)
# b=a.sort() b=None
# 2、y关联到x的副本,y排序后,x不变化--y=x.copy()
a=[2,1,3]
b=a.copy()
b.sort()
print(a)
print(b)
# 3、获取排序后的副本 sorted(x)--sorted()的reverse参数接受False 或者True 表示是否逆序
a=[1,3,2]
b=sorted(a)
print(a)
print(b)
# 4、sort()不能对dict字典进行排序--sorted()
# 4.1对dict排序默认会按照dict的key值进行排序,最后返回的结果是一个对key值排序好的list
a={"1":"a","3":"b","0":"c"}
b=sorted(a)
print(a) # {'1': 'a', '3': 'b', '0': 'c'}
print(b) # ['0', '1', '3']
# 4.2、对dict的value值排序
a={"1":"a","3":"z","0":"d"}
b=sorted(a,key=lambda x : a[x])
print(b) # ['1', '0', '3']
# 5、对多层列表排序
list=[('b',6),('a',1),('c',3),('d',4)]
list.sort(key=lambda x:x[1])
print(list) # [('a', 1), ('c', 3), ('d', 4), ('b', 6)]
# 5.1 对列表的第二个元素排序后,再对第一个元素排序
list=[('b',1),('a',1),('c',3),('d',4)]
list.sort(key=lambda x:(x[1],x[0]))
print(list) # [('a', 1), ('b', 1), ('c', 3), ('d', 4)]
# 6 key=str.lower指 把字符串按小写格式排序
b=sorted("aBc",key=str.lower)
print(b) #['A', 'B', 'C']