字典内置方法
1.字典内置方法
1.类型转换
# 转换1:
>>> info=dict([['name','tony'],('age',18)])
>>> info
{'age': 18, 'name': 'tony'}
# 转换2:fromkeys会从元组中取出每个值当做key,然后与None组成key:value放到字典中
>>> {}.fromkeys(('name','age','sex'),None)
{'age': None, 'sex': None, 'name': None}
2.字典取值get
d1 = {'name': 'jason','age': 18,'hobbies': ['play game', 'basketball']}
1.按key取值
print(d1['name']) # tony 键存在
print(d1['xxx']) # 键不存在直接报错
直接按key取值 键如果存在就能取出值(V)来,如果不存在就会直接报错,整个程序将直接不能运行。所以'涉及到字典取值 更加推荐下面的方式'
print(d1.get('name')) # tony 键存在
print(d1.get('xxx')) # None 键不存在不会报错 而是返回None
print(d1.get('xxx', '这个键不存在')) # 如果第二个参数不写默认返回None 写了的话则返回写了的('这个键不存在')
print(d1.get('name', '这个键不存在')) # 如果键存在 则不需要使用到第二个参数
3.修改值、添加键值对
print(id(d1))
d1['name'] = 'tony1' # 键存在是修改值
print(d1, id(d1)) #输出id地址是一样的 说明字典也是可变类型
d1['pwd'] = 123 # 键不存在则是新增一个键值对
print(d1)
#{'name': 'tony', 'age': 18, 'hobbies': ['play game', 'basketball'], 'pwd': 123}
4.统计字典中键值对的个数、成员运算len、in
统计字典中键值对的个数
print(len(d1)) # 3
成员运算 也只能判断key而已
print('tony' in d1) # False
print('name' in d1) # True
5.删除键值对del、pop、popitem
通用方式:
del d1['name']
print(d1)
# {'age': 18, 'hobbies': ['play game', 'basketball']}
弹出:
print(d1.pop('age'))
print(d1)
{'name': 'tony', 'hobbies': ['play game', 'basketball']}
弹出的(d1.pop('age'))可以使用,不使用将自动被删除
随机弹出:(python默认弹出最后一个)
d1.popitem()
print(d1)
# {'name': 'tony', 'age': 18}
6.获取所有的键、值、键值对
获取所有的键:
print(d1.keys())
# dict_keys(['name', 'age', 'hobbies']) 可以看成是列表
获取所有的值:
print(d1.values())
#dict_values(['tony', 18, ['play game', 'basketball']]) 可以看成是列表
获取所有的键值对:
print(d1.items())
# dict_items([('name', 'tony'), ('age', 18), ('hobbies', ['play game', 'basketball'])])
可以看成是列表套元组
"""在python2中上述三个方法就是直接返回一个列表 """
7.更新字典update、快速生成字典fromkeys
dic = {'k1': 'Tony', 'k2': 'gogo', 'k3': 'JY'}
dic.update({'k1': 'ty', 'k4': 'xxx'})
print(dic)
#{'k1': 'ty', 'k2': 'gogo', 'k3': 'JY', 'k4': 'xxx'}
# 键存在则修改 键不存在则新增
# dic = dict.fromkeys(['k1', 'k2', 'k3'], [])
# print(dic) # {'k1': [], 'k2': [], 'k3': []}
#如果 往k键添加一个值dic['k1'].append(111) # 三个键指向的是同一个列表
print(dic) # {'k1': [111], 'k2': [111], 'k3': [111]}
setdefault()
dic = {'k1': 111, 'k2': 222}
print(dic.setdefault('k3', 333))
# 333 键不存在则新增键值对 并且有返回结果是新增的v
print(dic)
# {'k1': 111, 'k2': 222, 'k3': 333}
print(dic.setdefault('k1', '嘿嘿嘿')) # 键存在 则返回对应的值 不做修改
print(dic)
#dic = {'k1': 111, 'k2': 222}
2.元组内置方法
1.类型转换
# print(tuple(11)) # 报错
# print(tuple(11.11)) # 报错
print(tuple('tony'))
print(tuple([11,22,33,44]))
print(tuple({'name':'tony'}))
print(tuple({11,22,33,44}))
# print(tuple(True)) # 报错
'支持for循环的数据类型都可以转成元组'
2.元组的特性
# t1 = (11, 22, 33, 44)
# print(type(t1)) # <class 'tuple'>
# t2 = (11)
# print(type(t2)) # int
# t2 = (11.11)
# print(type(t2)) # float
# t2 = ('tony')
# print(type(t2)) # str
"""当元组内只有一个元素的时候 一定要在元素的后面加上逗号"""
# t2 = (11,)
# print(type(t2)) # tuple
# t2 = (11.11,)
# print(type(t2)) # tuple
# t2 = ('jason',)
# print(type(t2)) # tuple
#所以一般情况下 我们会习惯性的将所有可以存储多个数据的类型的数据,如果内部只有一个元素也会加逗号。
3.索引取值、切片操作
t1 = (11, 22, 33, 44, 55, 66)
1.索引取值
print(t1[0]) # 11
print(t1[-1]) # 66
2.切片操作
print(t1[1:4]) #(22, 33, 44)
print(t1[-1:-4:-1]) #(66, 55, 44)
print(t1[-4:-1]) #(33, 44, 55)
4.间隔、统计元组内元素的个数
1.print(t1[1:4:2]) #(22, 44)
2.print(len(t1)) # 6
5.成员运算、统计某个元素出现的次数
1.print(11 in t1) # True
2.print(t1.count(22)) # 1
6.元组内元素不能"修改" 元组内各个索引值指向的内存地址不能修改
t1[0] = 111 #报错
ps:
tt = (11, 22, 33, [11, 22])
tt[-1].append('heiheihei')
问:执行之后的结果
A.报错 B.正常添加
#正确答案选B #(11, 22, 33, [11, 22, 'heiheihei']),外面虽然是元组但是元组里面列表的里面是可以添加元素的.
3.集合内置方法
1.类型转换
# print(set(11)) # 报错
# print(set(11.11)) # 报错
# print(set('jason'))
# print(set([11,22,33,44]))
# print(set({'name':'jason'}))
# print(set((11,22,33)))
# print(set(True)) # 报错
"""集合内元素只能是不可变类型"""
2.去重、关系运算
1.去重
集合内不能出现重复的元素(自带去重特性)
如果出现了 会被集合自动去重
s1={1,1,1,1,1,1,2,2,2,2,2,1,2,3,2,2,1,2,3,2,3,4,3,2,3}
print(s1) #{1, 2, 3, 4}
eg:列表如何去重:
l = ['a', 'b', 1, 'a', 'a']
s1 = set(l)
l = list(s1)
print(l)
#['a', 'b', 1, ]
2.关系运算
判断两个群体内的差异
eg:共同好友 共同关注 共同点赞
f1 = {'jason', 'kevin', 'tony', 'jerry'} # 小李的好友列表
f2 = {'jason', 'tom', 'jerry', 'jack'} # 小王的好友列表
# 1.求两个人的共同好友
# print(f1 & f2) # {'jerry', 'jason'}
# 2.求小李的单独好友
# print(f1 - f2) # {'kevin', 'tony'}
# 3.求两个人所有的好友
# print(f1 | f2) # {'kevin', 'jack', 'tom', 'jason', 'jerry', 'tony'}
# 4.求两个人各自的好友
print(f1 ^ f2) # {'jack', 'tony', 'tom', 'kevin'}
4.垃圾回收机制
一. 什么是垃圾回收机制
垃圾回收机制(简称GC)是Python解释器自带一种机,专门用来回收不可用的变量值所占用的内存空间
二. 为什么要用垃圾回收机制?
程序运行过程中会申请大量的内存空间,而对于一些无用的内存空间如果不及时清理的话会导致内存使用殆尽(内存溢出),导致程序崩溃,因此管理内存是一件重要且繁杂的事情,而python解释器自带的垃圾回收机制把程序员从繁杂的内存管理中解放出来
Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题,并且通过“分代回收”(generation collection)以空间换取时间的方式来进一步提高垃圾回收的效率
- 引用计数
引用计数就是:变量值被变量名关联的次数
如:age=18
变量值18被关联了一个变量名age,称之为引用计数为1
增加:m=age (把age的内存地址给了m,此时,m,age都关联了18,所以变量值18的引用计数为2)
减少:age=10(名字age先与值18解除关联,再与3建立了关联,变量值18的引用计数为1)del m(del的意思是解除变量名x与变量值18的关联关系,此时,变量18的引用计数为0)
值18的引用计数一旦变为0,其占用的内存地址就应该被解释器的垃圾回收机制回收
-
标记/清除算法的做法是当应用程序可用的内存空间被耗尽的时,就会停止整个程序,然后进行两项工作,第一项则是标记,第二项则是清除
#1、标记 通俗地讲就是: 栈区相当于“根”,凡是从根出发可以访达(直接或间接引用)的,都称之为“有根之人”,有根之人当活,无根之人当死。 具体地:标记的过程其实就是,遍历所有的GC Roots对象(栈区中的所有内容或者线程都可以作为GC Roots对象),然后将所有GC Roots的对象可以直接或间接访问到的对象标记为存活的对象,其余的均为非存活对象,应该被清除。 #2、清除 清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。
-
分代回收的核心思想是:在历经多次扫描的情况下,都没有被回收的变量,垃圾回收机制就会认为,该变量是常用变量,垃圾回收机制对其扫描的频率会降低,具体实现原理如下:
分代指的是根据存活时间来为变量划分不同等级(也就是不同的代) 新定义的变量,放到新生代这个等级中,假设每隔1分钟扫描新生代一次,如果发现变量依然被引用,那么该对象的权重(权重本质就是个整数)加一,当变量的权重大于某个设定得值(假设为3),会将它移动到更高一级的青春代,青春代的gc扫描的频率低于新生代(扫描时间间隔更长),假设5分钟扫描青春代一次,这样每次gc需要扫描的变量的总个数就变少了,节省了扫描的总时间,接下来,青春代中的对象,也会以同样的方式被移动到老年代中。也就是等级(代)越高,被垃圾回收机制扫描的频率越低
虽然分代回收可以起到提升效率的效果,但也存在一定的缺点