#字典:字典是 Python 中唯一的映射类型,每个元素由键(key)和值(value)构成,键必须是不可变类 型,比如数字、字符串和元组。
#字典基本操作:
# 1. 创建字典
# 2.遍历字典
# 3.判断键是否在字典里面
#1.创建字典:
dicts={}
print(dicts) #空字典
dict1 = {'name': 'ethan', 'age': 20}
dict1['age']=21  #更新字典 {'name': 'ethan', 'age': 21}
print(dict1)
#使用dict函数
d=dict(name='ethan',age=21)
print(d)
item = [('name', 'ethan'), ('age', 20)]
d1=dict(item)   #{'name': 'ethan', 'age': 20}
print(d1)
#2.遍历字典
d = {'name': 'ethan', 'age': 20}
for key in list(d.keys()):  #python3 使用list(d.keys())  python使用  for key in d.keys():
    if key=='name':
        del d[key]
        print(d)  # 结果:{'age': 20}
#3.判断键是否在字典中这时可以用 in 进行判断:
d = {'name': 'ethan', 'age': 20}
#访问不存在的键 就会抛出KeyEoor
#字典常用方法: clear  copy  get  setdefault update pop popitem
#keys/iterkeys  values/itervalues items/iteritems  formkeys
#clear  方法用于清空字典所有项,这是个原地操作,所以无返回值(或者说是 None)
d = {'name': 'ethan', 'age': 20}
rv = d.clear()
print(d) #{}
print(rv) # None
#copy 方法实现的是浅复制(shallow copy)
#对可变对象的修改保持同步; list
#对不可变对象的修改保持独立; str tuple dict
#name的值是不可变对象  books的值是可变对象
d1 = {'name': 'ethan', 'books': ['book1', 'book2', 'book3']}
d2=d1.copy( )
print(d2)  #结果:{'name': 'ethan', 'books': ['book1', 'book2', 'book3']}
d2['name']='peter'
#因为d2是字典不可变对象 则修改d2 不会改变d1
print(d2) #结果:{'name': 'peter', 'books': ['book1', 'book2', 'book3']}
d2['books'].remove('book2') # d2 对可变对象的修改会影响 d1
print(d1) #{'name': 'ethan', 'books': ['book1', 'book3']}
print(d2)  #{'name': 'peter', 'books': ['book1', 'book3']}
#和浅复制对应的是深复制(deep copy),它会创造出一个副本,跟原来的对象没有关系,可以通过 copy 模块的 deepcopy 函数来实现:
from copy import deepcopy
d1 = {'name': 'ethan', 'books': ['book1', 'book2', 'book3']}
d2 = deepcopy(d1)   # 创造出一个副本
print(d2)  #{'name': 'ethan', 'books': ['book1', 'book2', 'book3']}
d2['books'].remove('book2')
print(d2)# 对 d2 的任何修改不会影响到 d1  #{'name': 'ethan', 'books': ['book1', 'book3']}
print(d1) # {'name': 'ethan', 'books': ['book1', 'book2', 'book3']}
d1['books'].remove('book3')
## 对 d1 的任何修改也不会影响到 d2
print(d1) #{'name': 'ethan', 'books': ['book1', 'book2']}
print(d2) #{'name': 'ethan', 'books': ['book1', 'book3']}
#get方法当我们试图访问字典中不存在的项时会出现 KeyError,
但使用 get 就可以避免这个问题。
d = {}
print(d.get('name'))  #None
print(d.get('name', 'ethan'))  ## 'name' 不存在,使用默认值 'ethan'
#setdefault :方法用于对字典设定键值。使用形式如下:
#dict.setdefault(key, default=None)
d={}
print(d.setdefault('name', 'ethan')) # 返回设定的默认值 'ethan'
print(d)  # d 被更新
d['age'] = 20
print(d) #{'age': 20, 'name': 'ethan'}
print(d.setdefault('age', 18))  ##返回20 age 已存在,返回已有的值,不会更新字典
#!!!!总之:可以看到,当键不存在的时候,setdefault 返回设定的默认值并且更新字典。当键存在的时候,会 返回已有的值,但不会更新字典。
#update 方法用于将一个字典添加到原字典,如果存在相同的键则会进行覆盖。
d = {}
d1 = {'name': 'ethan'}
d.update(d1) ## 将字典 d1 添加到 d
d3 = {'name': 'michael'}
d.update(d3)    ## 将字典 d3 添加到 d,存在相同的 key,则覆盖
#items/iteritems:items 方法将所有的字典项以列表形式返回,这些列表项的每一项都来自于(键,值)。我们也经常 使用这个方法来对字典进行遍历。
d = {'name': 'ethan', 'age': 20}
print(d.items())  #dict_items([('name', 'ethan'), ('age', 20)])
for k, v in d.items():
    print('%s: %s' % (k, v)) #name: ethan   age: 20
#iteritems 的作用大致相同,但会返回一个迭代器对象而不是列表,同样,我们也可以使用这个方法 来对字典进行遍历,而且这也是推荐的做法:
#keys/iterkeys:方法将字典的键以列表形式返回,iterkeys 则返回针对键的迭代器。
d = {'name': 'ethan', 'age': 20}
print(d.keys()) #dict_keys(['name', 'age'])
#values/itervalues :方法将字典的值以列表形式返回,itervalues 则返回针对值的迭代器。
print(d.values()) #dict_values(['ethan', 20])
#pop:方法用于将某个键值对从字典移除,并返回给定键的值。
print(d.pop('name')) #ethan
#popitem 用于随机移除字典中的某个键值对。
d = {'id': 10, 'name': 'ethan', 'age': 20}
print(d.popitem()) #('age', 20)