-
tuple:元组,不可变,可迭代,可拆包
girl = ("珊珊", 21, 170, "B罩杯") name,age,height,cupSize = girl # 元组拆包 print(name, age, height, cupSize)
其不可变不是绝对的,当元组中包含数组或其他可变数据对象时,就可以改变元组的内容。
tuple比list好,原因:
其不可变性,可以保证在编译时确定其值,使得性能优化,线程安全,可以作为dict的key,具有拆包特性
如果要拿C语言来类比,Tuple对应的是struct(结构体),而list对应的是array(数组)
查看全部 -
def ask(*args, **kwargs):
pass
函数参数说明:*args参数可以接收元组(tuple)
**kwargs参数接收的是字典(key-value)形式的参数
# 函数参数 *args接收元组参数, **kwargs接收字典参数 def ask(*args, **kwargs): print(type(args)) print(type(kwargs)) print(args, kwargs) if __name__ == "__main__": ask("六月飞雪", 6) # 元组参数 ask(name = "刘豆豆", age = 22) # 字典参数
namedtuple中的_make()函数接收一个可迭代的对象,这个对象可以是元组,列表,字典,其参数一一对应。
from collections import namedtuple if __name__ == "__main__": User = namedtuple("User", ["name", "age", "height", "cupSize", "edu"]) # 使用namedtuple就相当于创建了一个User类 user = User(name="彤彤", age=23, height=172, cupSize="C罩杯", edu = "清华大学") print(user.name, user.age, user.height,user.cupSize) girl_tuple1 = ("依依", 22, 171, "B罩杯", "北京大学") user1 = User(*girl_tuple1) # 将元组作为一个参数传递给函数,其前面加个星号即可 print(user1.name, user1.age, user1.height, user1.cupSize) girl_tuple2 = ("倩倩", 23, 171, "B罩杯") user2 = User(*girl_tuple2, "北京大学") # 元组作为参数传递 print(user2.name, user2.age, user2.height, user2.cupSize, user2.edu) print("-------------------------------") # 字典 user_dict = { "name":"悠悠", "age": 24, "height": 171, "cupSize": "C罩杯" } user3 = User(**user_dict, edu="南开大学") # 字典作为参数传递,其前加两个星号 print(user3.name, user3.age, user3.height, user3.cupSize, user3.edu) user4 = User._make(girl_tuple1) #元组作为其参数 参数一定要对应,否则报错 print(user4.name, user4.age, user4.height, user4.cupSize, user4.edu) user_list = ["可可", 24, 172, "B罩杯", "浙江大学"] user5 = User._make(user_list) # 列表作为其参数 使用 _make()函数你不需要关心数据类型,只要传递一个可迭代的对象即可 print(user5.name, user5.age, user5.height, user5.cupSize, user5.edu) print("------------------") user_dict1 = { "name": "玉玉", "age": 23, "height": 173, "cupSize": "C罩杯", "edu": "武汉大学" } user6 = User._make(user_dict1) # 字典作为其参数,使用 _make()函数其参数是一个可迭代的对象,数据类型任意 print(user_dict1) print(user_dict1.values())
查看全部 -
tuple unhashable 可以作为哈希的key(字典key值) tuple可以用*解包方式赋值 *args 传进来作为tuple **kwargs 传进来 key value形式(xx=yy)查看全部
-
namedtuple 是 tuple的子类
namedtuple 省资源。节省了Class初始化 和参数检查的过程
例:
b = ("name", "age", "gender") b_k = namedtuple("user_02", b) b_v = ("tom", 19) print(b_k(*b_v, "male"))
常用方法:
_make(iterable) 生成对应关系
_asdict()
查看全部 -
user_dict = {} users = ["bobby1", "bobby2", "bobby3", "bobby1", "bobby2", "bobby2"] #第一种形式 for user in users: if user not in user_dict: user_dict[user] = 1 else: user_dict[user] += 1 #第二种形式 for user in users: user_dict.setdefault(user, 0) #若user键不存在,设为默认值0 user_dict[user] += 1 from collections import defaultdict default_dict = defaultdict(list) #在bobby键不存在时,调用传递对象的名称list,生成空数组 default_dict["bobby"] #第三种形式 default_dict = defaultdict(int) #默认传递0 for user in users: default_dict[user] += 1 #如果生成嵌套的dict def gen_default(): return {"name":"", "nums":0} default_dict = defaultdict(gen_default) default_dict["group1"] #没有group1时传递gen_default函数
查看全部 -
*args存储函数传参的值(未指明变量名的情况),**kwargs存储的是指明变量名和值的情况 前者是tuple,后者是dict
查看全部 -
deque双端队列
list和deque通常被当作容器,存储相同类型元素;tuple通常被当作一个类对象,存储不同类型元素
deque创建:
deque(iterable)(list, tuple, dict都是iterable的,传入dict时key作为deque中的元素)
deque方法:
pop(),popleft(),index(),clear(),insert(),remove(),extend(),extendleft(),count()...
最关键的:
deque是线程安全的(多线程编程时,往里put元素无需加锁),list不是线程安全的
查看全部 -
count_dict = {} all = ['a','b','c','a','b','b'] for i in all: if i not in count_dict: count_dict[i] = 0 count_dict[i] += 1 print(count_dict) ==>{'a': 2, 'b': 3, 'c': 1}
当dict中没有对应的key时会抛出keyError异常,所以一般做法是先判断dict中是否有该key,若没有先初始化
忘记判断怎么办?defaultdict会解决
count_dict = defaultdict(int) all = ['a','b','c','a','b','b'] for i in all: count_dict[i] += 1 print(count_dict) ==>defaultdict(<class 'int'>, {'a': 2, 'b': 3, 'c': 1})
defaultdict:
当你访问一个不存在的key时==>dict[key],defaultdict会自动创建键值对,value根据创建defaultdict时传入的类型对象或函数对象决定
类型对象:
dic_1 = defaultdict(int) dic_2 = defaultdict(tuple) dic_3 = defaultdict(list) dic_4 = defaultdict(str) dic_5 = defaultdict(set) print(dic_1['a']) print(dic_2['a']) print(dic_3['a']) print(dic_4['a']) print(dic_5['a']) ==> 0 () [] set()
函数对象:
可以定义嵌套结构,如下dict嵌套dict
def gen_default(): return { 'name':'', 'member_nums':0 } default_dict = defaultdict(gen_default) #注意不能加(),因为是对象不是方法 print(default_dict['group1']) ==>{'name': '', 'member_nums': 0}
查看全部 -
namedtuple是一个类
User = namedtuple('User',['name','age','height']) #类名,[属性] user = User(name='bobby',age=29,height=175) print(user.name,user.age,user.height) ==>bobby 29 175
为什么不直接class一个类,还要弄一个namedtuple出来?
1、class一个类要定义很多变量,代码量增加,空间复杂
2、在数据处理时,经常需要从数据库中读入数据,从数据库中读出的数据其实就是一个tuple
复习一下*args,**kwargs
如果不指明参数名称,全部算在args这个tuple中
如果指明参数名称,就算在kwargs这个dict中
def ask(*args,**kwargs): kwargs:{} args:('bobby',29) pass ask('bobby',29)
def ask(*args,**kwargs): args:() kwargs:{'name':'bobby','age':29} pass ask(name='bobby',age=29)
def ask(*args,**kwargs): kwargs:{'age':29} args:('bobby') pass ask('bobby',age=29)
所以创建类的时候,参数也可以这样写:
user_tuple = ('bobby',29,175) user = User(*user_tuple)
user_dict = { 'name':'bobby', 'age':29, 'height':175 } user = User(**user_dict)
namedtuple的常用函数
1、_make(iterable)(list, tuple, dict都是iterable的)创建namedtuple
user_list = ["bobby",29,175] user_tuple = ("bobby",29,175) user_dict = { 'name':'bobby', 'age':29, 'height':175 } user = User._make(user_list/user_tuple/user_dict)
和上面*args,**kwargs的区别在哪里呢?
*args,**kwargs灵活性更强,但_make()不用加*/**且多一个list参数方式
例:数据库中user表中的数据全部取出然后再加一个列
User = namedtuple('User',['name','age','height','edu']) user = User(*user_tuple,'master')
User = namedtuple('User',['name','age','height','edu']) user = User(**user_dict,edu='master')
_make()不行
2、_asdict()将namedtuple转为dict
User = namedtuple("User",["name","age","height"]) user_tuple = ("bobby",29,175) user = User(*user_tuple) user_dict = user._asdict() print(user_dict) ==>{'name': 'bobby', 'age': 29, 'height': 175}
查看全部 -
tuple的功能:
不可变、iterable
拆包
tuple不可变性不是绝对的(所以放进tuple中的元素最好是不可变的)
tuple比list好的地方
immutable(不可变)的重要性
性能优化:元素全为immutable的tuple会作为常量在编译时确定
线程安全(tuple本身加锁)
可以作为dict的key
拆包特性
user_tuple = ("bobby",29) name,age = user_tuple ==>bobby 29 user_tuple = ("bobby",29,175,"beijing","edu") name, *other = user_tuple print(name,other) ==>bobby [29, 175, 'beijing', 'edu']
查看全部 -
tuple:不可变,可迭代对象iterable(实现了__iter__或者__getitem__魔法函数)
元祖的拆包:
用法:
user_tuple = ("bobby", 28, 178)
name, age, height = user_tuple
只想提取第一个参数:
name, *other = user_tuple
输出:
bobby, [29, 175]
tuple的不可变不是绝对的:
tuple内部嵌套了可变对象(不太建议使用),嵌套对象可修改
tuple比list好用的地方:
immutable(不可变对象)的重要性:
①性能优化(元素全部为不可变对象的tuple会作为常量在编译时确定,因此产生如此显著的速度差异)
②线程安全
③可以作为dict的key(immutable对象是可哈希的,dict key也是可哈希的,适合做字典的key)
使用list做key会报错提示:TypeError: unhashable type: 'list'
④拆包特性
如果拿c语言类比,tuple好比struct,list对应的是array
查看全部 -
from collections import namedtuple
使用namedtuple可以创建一个类,返回一个带有命名字段的新元祖子类
# namedtuple 相当于创建了一个User类,里面含有name,age,height成员变量
# namedtuple是tuple的子类,
# 1、代码比直接定义类更简单
# 2、namedtuple比较节省空间,少了class里面很多内置的变量
# 3、非常适用于创建简单对象,特别用作数据处理
User = namedtuple("User",["name", "age", "height"])
user = User(name="bobby", age=29, height=178)
print(user.age, user.name, user.height)
# 应用场景:user表数据全部取出然后加一个列edu,比较方便(pymysql,查询返回结果是tuple)
User = namedtuple("User",["name", "age", "height", "edu"])
user = User(name="bobby", age=29, height=178)
user.edu = "master"
# 也可以通过传入tuple或者dict来初始化namedtuple
User = namedtuple("User",["name", "age", "height"])
user_tuple = ("bobby", 29, 175)
user = User(*user_tuple)
user_dict = {
"name":"bobby",
"age":29,
"height":175
}
user = User(**user_dict)
#namedtuple实现原理:
点击进去namedtuple类看,找到python的一个内置函数方法:
exec(class_definition, namespace) #把字符串当做代码执行
继续点击class_definition,有个_class_template,点击进去,这个就是namedtuple的实质
内部代码实现原理实际上是生成一个class,里面的方法就是namedtuple具有的所有方法
其中包括_make、_replace、__repr__、_asdict、__getnewargs__方法
重点介绍_make、_asdict方法
_make方法可传递一个iterable可迭代对象
实际前面例子创建User对象时,也可以用_make方法
User = namedtuple("User",["name", "age", "height"])
user_tuple = ("bobby", 29, 175)
user = User._make(user_tuple)
_asdict方法, 可以将tuple转换成OrderedDict
User = namedtuple("User",["name", "age", "height"])
user_tuple = ("bobby", 29, 175)
user = User(*user_tuple)
user_info_dict = user._asdict()
因为namedtuple是继承自tuple,所以它也支持拆包功能:
User = namedtuple("User",["name", "age", "height","edu"])
user = User(name="bobby", age=29, height=178, edu="master")
name, age, *other = user
查看全部 -
有大量数据需要做统计代码量会比较大,可使用Counter类
from collections import Counter
users = ['bobby1','bobby2','bobby1','bobby2','bobby2','bobby3']
users_counter = Counter(users)
print(users_counter )
Counter可以传递任何可迭代对象
users_counter = Counter("asdasdgdfwee")
Counter是dict子类,继承自dict,它返回dict类型统计结果
users_counter.update("asdasdg") # 也可以进行合并统计,使用update方法
它也可以传递另外一个Counter对象
users_counter1 = Counter("asdasdgdfwee")
users_counter2 = Counter("sdf342zz")
users_counter1.update(users_counter2 )
users_counter.most_common(2) # 统计出现次数最多的前n个元素
它的内部是通过_heapq堆数据结构实现的,这个堆是专门解决这个topn问题,性能比自己遍历更高
查看全部 -
ChainMap
from collections import ChainMap
user_dict1 = {'a':"rio1", "b":"rio2"}
user_dict2 = {'b':"rio3", "d":"rio3"}
for key, value in user_dict1.item():
print(key,value)
for key, value in user_dict2.item():
print(key,value)
如果类似上面的dict定义了多个,就需要分别去遍历多次item
ChainMap可以把所有dict连接起来一起遍历。
new_dict = ChainMap(user_dict1,user_dict2)
for key, value in new_dict.item():
xxxxxx
如果两个字典存在相同的key,只会遍历先找到的key,后面出现相同的key都不会遍历
在原来的chainmap字典中再动态新增字典,返回一个新的ChainMap
new_chainmap = new_dict.new_child( {"aa":11,“bb":22} )
以列表形式把数据展示出来
print(new_dict.maps)
=> [{'a':"rio1", "b":"rio2"}, {'b':"rio3", "d":"rio3"}]
ChainMap并不是把多个数据合并变成一个dict,而是在上面加了一个访问迭代器,并没有拷贝到新的变量里。
new_dict.maps[0]['a'] = 'rio'
for key, value in new_dict.item():
print(key,value)
查看全部 -
OrderedDict:有序字典
from collections import OrderedDict
它是dict的子类,它是有序的,其顺序是:先添加的在前边,后添加的在后
user_dict = OrderedDict()
user_dict['a'] = "rio1"
user_dict['c"] = "rio2"
user_dict["b"] = "rio3"
python3下dict和OrderedDict都是有序的,OrderedDict提供了额外的函数
pop_item可以不需要传递key并删除最后一个item,pop需要传递key
user_dict.popitem()
user_dict.pop(key)
move_to_end("key"),把指定元素移到最后
拓展:
前面小结namedtuple的_asdict()返回的就是orderedDict
查看全部
举报