一. tuple功能
特点:不可变,可迭代,可拆包,但tuple不可变性不是绝对的
其实只要类里包含__iter__或者__getitem__任一个魔法函数都是可迭代的
1. 拆包
1.1 基本用法
name = ("jack", "hong")
# 按位置赋值给变量
name1, name2 = name
print(name1, name2)
输出
jack, hong
1.2 使用星号代替不想取的元素
name = ("jack", "hong", "tiger")
# 只想取第一个元素
name3, *other = name
print(name3, other)
输出结果,剩余的元素放到了一个列表中
jack ['hong', 'tiger']
2. 当元组元素中嵌套列表元素时,其实也是可以改变的。这种写法不推荐
name_tuple = ("jack", [12, 13])
name_tuple[1].append(14)
print(name_tuple)
输出为
('jack', [12, 13, 14])
3. tuple比list好的地方
不可变属性可提高编译速度,线程安全,可作为字典的键(重要)
name_tuple = ("jack", "hong")
dict = {}
dict[name_tuple] = "people's name"
print(dict)
输出结果
{('jack', 'hong'): "people's name"}
需要注意的是列表也可拆包
name_list = ["jack", "hong"]
name1, *other = name_list
print(name1, other)
输出结果
jack ['hong']
二. namedtuple功能详解
1. 把元组像类一样使用,namedtuple可生成一个类
from collections import namedtuple
# 第一个参数名是类名, 后面列表中的元素是类中的属性
User = namedtuple("User", ["name", "age", "height"])
user = User(name="hong", age=21, height=177)
print(user.age, user.height, user.name)
输出结果
21 177 hong
相比字典的好处:
1)namedtuple是tuple的一个子类
2)相比一般的类,它更省空间,没有普通类中内置的很多函数和变量
2. 函数中的魔法参数
def ask(*args, **kwargs):
pass
ask("hong", 22)
#ask(name="hong", age=22)
当调用函数不带参数名时, 调试结果如下
带参数名时
3. 上面代码可改写为如下
1)数据不带参数名
from collections import namedtuple
User = namedtuple("User", ["name", "age", "height"])
data = ("jack", 28, 188)
user = User(*data)
print(user.name)
2)把数据改为带参数名,并且在类中添加一个edu属性
from collections import namedtuple
User = namedtuple("User", ["name", "age", "height", "edu"])
data1 = {
"name": "jack",
"age": 27,
"height": 177
}
user = User(**data1, edu="master")
user = User("jack", 28, 199, "master")
print(user.name)
4. namedtuple中的内部函数_make,可不用在参数前加星号,参数为可迭代对象
不带参数名时
from collections import namedtuple
User = namedtuple("User", ["name", "age", "height"])
data = ("jack", 28, 188)
user = User._make(data)
print(user.name)
带参数名时。不太懂,先不管这个了
from collections import namedtuple
User = namedtuple("User", ["name", "age", "height"])
data1 = {
"name": "jack",
"age": 27,
"height": 177
}
user = User._make(data1)
user = User("jack", 28, 199)
print(user.name)
注意此时必须有2次实例化
5. 内部函数之_asdict(),可把元组转变为排序字典
user_info_dict = user._asdict()
二. defaultdict详解, c写的
需求:统计列表中各元素出现的次数
1. 普通方法如下:
num_dict = {}
nums = ["tiger", "monkey", "tiger", "chicken", "monkey", "tiger", "sheep"]
for num in nums:
if num not in num_dict:
num_dict[num] = 1
else:
num_dict[num] += 1
print(num_dict)
输出如下
{'chicken': 1, 'tiger': 3, 'monkey': 2, 'sheep': 1}
2. 使用dict中的setdefault()简化代码
num_dict = {}
nums = ["tiger", "monkey", "tiger", "chicken", "monkey", "tiger", "sheep"]
for num in nums:
num_dict.setdefault(num, 0)
num_dict[num] += 1
print(num_dict)
3. 使用defaultdict
3.1首先看一个defaultdict的简单例子
from collections import defaultdict
default_dict = defaultdict(list)
a = default_dict["hong"]
print(a)
输出如下
[]
说明:
defaultdict是dict的一个子类,它的参数为可调用的对象名字,比如list,int,也可以是函数名等。
上例中键名不存在,且指明为list,则返回一个空list;
如果把list修改为int,则输出结果为0
3.2 使用defaultdict简化需求代码,不需要设置默认值
from collections import defaultdict
default_dict = defaultdict(int)
nums = ["tiger", "monkey", "tiger", "chicken", "monkey", "tiger", "sheep"]
for num in nums:
default_dict[num] += 1
print(default_dict)
print(default_dict.get("tiger"))
输出结果如下
defaultdict(<class 'int'>, {'chicken': 1, 'sheep': 1, 'monkey': 2, 'tiger': 3})
3
3.3 如果是一个嵌套的dict,不能简单的照上面的样式使用defaultdict,可以把这个嵌套的dict放到一个函数中,比如想初始化一个学生的姓名为空,年龄为0
from collections import defaultdict
def gen_default():
return {
"name": "",
"age": 0
}
default_dict = defaultdict(gen_default)
text = default_dict["student1"]
print(text)
输出结果如下
{'age': 0, 'name': ''}
三. deque:双端队列,参数为可迭代对象
用法和list很相似,不过增加了一些功能,具体看源代码吧
deque是线程安全的,而list不是
例子1
from collections import deque
deque1 = deque([12, 44, 28])
print(deque1)
print(deque1[0])
输出结果如下
deque([12, 44, 28])
12
说明:
list和deque一般用来保存相同的数据类型
四. Counter,用来统计可迭代对象中的元素个数
Counter是dict的一个子类,参数也是需要可迭代的对象,比如列表,元组,字符串
1. 基本使用方法
from collections import Counter
users = ["jack", "hong", "jack"]
user_counter = Counter(users)
print(user_counter)
print(user_counter.get("jack"))
输出结果如下
Counter({'jack': 2, 'hong': 1})
2
2.1 它里面的update()函数可以用来做合并处理
from collections import Counter
letter_counter = Counter("aabb")
print(letter_counter)
letter_counter.update("abc")
print(letter_counter)
输出结果如下
Counter({'a': 2, 'b': 2})
Counter({'a': 3, 'b': 3, 'c': 1})
2.2 update里面的参数也可以是一个Counter变量
from collections import Counter
letter_counter = Counter("aabb")
print(letter_counter)
x = Counter("abc")
letter_counter.update(x)
print(letter_counter)
输出结果和上面一样
3. most_common()函数可统计出现次数最多的前N个元素
from collections import Counter
letter_counter = Counter("aaabbc")
top2 = letter_counter.most_common(2)
print(top2)
输出结果如下
[('a', 3), ('b', 2)]
注意返回结果类型是列表
五. OrderedDict,继承dict,它的有序性是按照添加的字典元素顺序输出
python3中dict其实也是按照添加元素的顺序输出,但是python2中是无序的
1. 基本用法
from collections import OrderedDict
user_dict = OrderedDict()
user_dict["c"] = "jack1"
user_dict["a"] = "jack2"
user_dict["b"] = "jack3"
print(user_dict)
输出结果如下
OrderedDict([('c', 'jack1'), ('a', 'jack2'), ('b', 'jack3')])
2. popitem(),把字典中最后一个键值对弹出来
from collections import OrderedDict
user_dict = OrderedDict()
user_dict["c"] = "jack1"
user_dict["a"] = "jack2"
user_dict["b"] = "jack3"
print(user_dict)
user_dict.popitem()
print(user_dict)
输出结果如下
OrderedDict([('c', 'jack1'), ('a', 'jack2'), ('b', 'jack3')])
OrderedDict([('c', 'jack1'), ('a', 'jack2')])
说明:
pop()方法也可弹出键值对,它需要指明要弹出键值对的键名,例如user_dict.pop("a")
3. move_to_end(),将某个键值对移到最后,需要指明键名
from collections import OrderedDict
user_dict = OrderedDict()
user_dict["c"] = "jack1"
user_dict["a"] = "jack2"
user_dict["b"] = "jack3"
print(user_dict)
user_dict.move_to_end("a")
print(user_dict)
输出结果如下
OrderedDict([('c', 'jack1'), ('a', 'jack2'), ('b', 'jack3')])
OrderedDict([('c', 'jack1'), ('b', 'jack3'), ('a', 'jack2')])
六. ChainMap, 可将多个字典链接起来进行for循环,遍历取到键和值。
1. 基本用法
from collections import ChainMap
dict1 = {"a": "jack1", "b": "jack2"}
dict2 = {"c": "jack3", "d": "jack4"}
newdict = ChainMap(dict1, dict2)
for key, value in newdict.items():
print(key, value)
输出结果如下
a jack1
b jack2
d jack4
c jack3
注意:如果dict2中有和dict1相同的键名,那么只会遍历出dict1中的键值对,如下
from collections import ChainMap
dict1 = {"a": "jack1", "b": "jack2"}
dict2 = {"a": "jack3", "d": "jack4"}
newdict = ChainMap(dict1, dict2)
print(newdict)
for key, value in newdict.items():
print(key, value)
输出结果如下
ChainMap({'a': 'jack1', 'b': 'jack2'}, {'a': 'jack3', 'd': 'jack4'})
a jack1
b jack2
d jack4
2. ChainMap中的new_child函数可动态的添加新的链接字典
from collections import ChainMap
dict1 = {"a": "jack1", "b": "jack2"}
dict2 = {"c": "jack3", "d": "jack4"}
newdict1 = ChainMap(dict1, dict2)
dict3 = {"e": "jack5"}
newdict2 = newdict1.new_child(dict3)
print(newdict2)
for key, value in newdict2.items():
print(key, value)
输出结果如下
ChainMap({'e': 'jack5'}, {'a': 'jack1', 'b': 'jack2'}, {'c': 'jack3', 'd': 'jack4'})
a jack1
e jack5
c jack3
b jack2
d jack4
3. maps属性可把链接起来的字典变为list类型,maps不是拷贝,只相当于指向
from collections import ChainMap
dict1 = {"a": "jack1", "b": "jack2"}
dict2 = {"c": "jack3"}
newdict = ChainMap(dict1, dict2)
print(newdict)
print(newdict.maps)
# 修改后会影响原数据
newdict.maps[0]["a"] = "hong"
for key, value in newdict.items():
print(key, value)
输出结果如下
ChainMap({'b': 'jack2', 'a': 'jack1'}, {'c': 'jack3'})
[{'b': 'jack2', 'a': 'jack1'}, {'c': 'jack3'}]
b jack2
a hong
c jack3