hash

一、集set

​ 约定
​ set 翻译为集合
​ collection 翻译为集合类型或容器,是一个大概念
​ set
可变的、无序的、不重复的元素的集合

set定义 初始化

set() -> new empty set object
set(iterable) -> new set object
s1 = set()
s2 = set(range(5))
s3 = set(list(range(10))) 
s4 = {} # ?错误写发,这样写是字典
s5 = {9,10,11} # set s6 = {(1,2),3,'a'}
s7 = {[1],(1,),1} # 不可以有非哈希值

1,元素

set的元素要求必须可以hash
目前学过的不可hash的类型有list、set、bytearray
元素不可以索引
set可以迭代

2,set增加

dd(elem)
增加一个元素到set中
如果元素存在,什么都不做

update(*others)
合并其他元素到set集合中来
参数others必须是可迭代对象
就地修改

3,set删除

remove(elem)
从set中移除一个元素元素不存在,抛出KeyError异常。为什么是KeyError?

discard(elem)
从set中移除一个元素
元素不存在,什么都不做

pop() -> item
移除并返回任意的元素。为什么是任意元素?
空集返回KeyError异常

clear()
移除所有元素

4,set修改、查询

修改
要么删除,要么加入新的元素

索引
非线性结构,无法索引

遍历
可以迭代所有元素

成员运算符
in 和 not in 判断元素是否在set中

5,set和线性结构

基本概念
全集
所有元素的集合。例如实数集,所有实数组成的集合就是全集
子集subset和超集superset
一个集合A所有元素都在另一个集合B内,A是B的子集,B是A的超集
真子集和真超集
A是B的子集,且A不等于B,A就是B的真子集,B是A的真超集
并集:多个集合合并的结果

​ union | 返回和多个集合合并后的新的集合

​ update |= 和多个集合合并,就地修改

​ 交集:多个集合的公共部分

​ 集合A和B,由所有属于A且属于B的元素组成的集合

​ intersection & 回和多个集合的交集
​ intersection_update &= 获取和多个集合的交集,并就地修改

​ 差集:集合中除去和其他集合公共部分

​ 集合A和B,由所有属于A 且不属于B的元素组成的集合

​ difference - 返回和多个集合的差集

​ difference_update -= 获取和多个集合的差集并就地修改

​ 对称差集:
​ 集合A和B,由所有不属于A和B的交集元素组成的集合,记作(A-B)∪(B-A)
​ symmetric_differece ^ 返回和另一个集合的对称差集
​ symmetric_differece_update ^= 获取和另一个集合的对称差集并就地修改

二、字典dict

​ key-value键值对的数据的集合
可变的、无序的、key不重复

字典dict定义 初始化

d = dict() #或者 
d = {}
dict(**kwargs) # 使用name=value对初始化一个字典
dict(iterable, **kwarg) # 使用可迭代对象和name=value对构造字典,不过可迭代对象的元素必须是一个二元结构
d = dict(((1,'a'),(2,'b'))) # 或者 
d = dict(([1,'a'],[2,'b']), c=300)
dict(mapping, **kwarg)  # 使用一个字典构建另一个字典
d = {'a':10, 'b':20, 'c':None, 'd':[1,2,3]}
# 类方法dict.fromkeys(iterable, value)
d = dict.fromkeys(range(5))
d = dict.fromkeys(range(5),0)

字典元素的访问

d[key]

​ 返回key对应的值value
​ ey不存在抛出KeyError异常

get(key[, default])

​ 返回key对应的值value
​ key不存在返回缺省值,如果没有设置缺省值就返回None

setdefault(key[, default])

​ 返回key对应的值value
​ key不存在,添加kv对,value设置为default,并返回default,如果default没有设置,缺省为None

​ 如果KV对已经有值,即使给你输入Value值,返回也是原本的 Value值

字典增加和修改

​ d[key] = value
​ 将key对应的值修改为value
key不存在添加新的kv对

​ update([other]) -> None
​ 使用另一个字典的kv对更新本字典
​ key不存在,就添加
​ key存在,覆盖已经存在的key对应的值
​ 就地修改

d = {}
d.update(red=1) 		# {'red': 1}
d.update((('red',2),))	# {'red': 2}
d.update({'red':3})		# {'red': 3}

字典删除

​ pop(key[, default])
​ key存在,移除它,并返回它的value
​ key不存在,返回给定的default
​ default未设置,key不存在则抛出KeyError异常

​ popitem()
​ 移除并返回一个任意的键值对
​ 字典为empty,抛出KeyError异常

​ clear()
​ 清空字典

​ del语句

	a = True
	b = [1]
	d = {'a':1, 'b':b, 'c':[1,3,5]}
	del a # 删除了a 
	del b[0] # 删除了b列表的第一个元素
	del d['c'] # 删除了key值的velue值[1,3,5]
	del c # NameError
	del b # 删除了列表b
	del d['b'] # 删除了字典d中key ‘b'的velue值 b

字典遍历

​ for … in dict
​ 遍历key

​ 遍历value

​ 遍历item,即kv对

d = {'a':1, 'b':B, 'c':[1,3,5]}
	for b in d:		   # a B c
		print(b)
	for b in d.keys():
		print(b)       # a B c
	for b in d.values():
		print(b)       # 1  B [1,3,5]
	for b in d:
    	print(b[b])    # 1  B [1,3,5]
	for b in d.keys():
    	print(b.get(b)) # 1  B [1,3,5]
    for b,_ in d.items():
		print(b)       #  B
  	for _ ,b in d.items():
        print(b)       #  b

总结

​ Python3中,keys、values、items方法返回一个类似一个生成器的可迭代对象,不会把函数的返回结果复制到内存中
​ Dictionary view对象,可以使用len()、iter()、in操作
​ 字典的entry的动态的视图,字典变化,视图将反映出这些变化
​ keys返回一个类set对象,也就是可以看做一个set集合。如果values都可以hash,那么items也可以看做是类set对象
​ Python2中,上面的方法会返回一个新的列表,占据新的内存空间。所以Python2建议使用iterkeys、 itervalues、iteritems版本,返回一个迭代器,而不是返回一个copy

字典遍历和移除

d = dict(a=1, b=2, c='abc') 
keys = []
for k,v in d.items():
	if isinstance(v, str):
		keys.append(k)
for k in keys:
	d.pop(k)
    print(d) 
# {'a': 1, 'b': 2}  

字典的key

​ key的要求和set的元素要求一致
​ set的元素可以就是看做key,set可以看做dict的简化版
​ hashable 可哈希才可以作为key,可以使用hash()测试
​ d = {1 : 0, 2.0 : 3, “abc” : None, (‘hello’, ‘world’, ‘python’) : “string”, b’abc’ : ‘135’}

defaultdict

​ collections.defaultdict([default_factory[, …]])
​ 第一个参数是default_factory,缺省是None,它提供一个初始化函数。当key不存在的时候,会调用这个工厂函数来生成key对应的value

from collections import defaultdict import random
d1 = defaultdict(list) 
	for k in 'abcdef':
		for i in range(random.randint(1,5)):
			d1[k].append(i)
print(d1)
# defaultdict(<class 'list'>, {'a': [0, 1, 2, 3], 'b': [0, 1], 'c': [0, 1, 2, 3], 'd': [0, 1, 2, 3], 'e': [0, 1, 2], 'f': [0, 1, 2]})

OrderedDict

​ collections.OrderedDict([items])

​ key并不是按照加入的顺序排列,可以使用OrderedDict记录顺序

from collections import OrderedDict
import random
d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2} 
print(d)
keys = list(d.keys())
random.shuffle(keys)
print(keys)
od = OrderedDict()
for key in keys:
    od[key] = d[key]
print(od)
print(od.keys())
# {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
# ['orange', 'pear', 'apple', 'banana']
# OrderedDict([('orange', 2), ('pear', 1), ('apple', 4), ('banana', 3)])
# odict_keys(['orange', 'pear', 'apple', 'banana'])

​ 有序字典可以记录元素插入的顺序,打印的时候也是按照这个顺序输出打印
​ 3.6版本的Python的字典就是记录key插入的顺序(IPython不一定有效果)
​ 应用场景:
​ 假如使用字典记录了N个产品,这些产品使用ID由小到大加入到字典中
​ 除了使用字典检索的遍历,有时候需要取出ID,但是希望是按照输入的顺序,因为输入顺序是有序的
​ 否则还需要重新把遍历到的值排序

三、解析式、生成器

标准库datetime

​ 对日期、时间、时间戳的处理
​ datetime类
​ 类方法
​ today() 返回本地时区当前时间的datetime对象
​ now(tz=None) 返回当前时间的datetime对象,时间到微秒,如果tz为None,返回和today()一样
​ utcnow() 没有时区的当前时间
​ fromtimestamp(timestamp, tz=None) 从一个时间戳返回一个datetime对象
​ datetime对象
​ timestamp() 返回一个到微秒的时间戳。
​ 时间戳:格林威治时间1970年1月1日0点到现在的秒数

​ 构造方法 datetime.datetime(2016, 12, 6, 16, 29, 43, 79043)
​ year、month、day、hour、minute、second、microsecond,取datetime对象的年月日时分秒及微秒
​ weekday() 返回星期的天,周一0,周日6
​ isoweekday() 返回星期的天,周一1,周日7
​ date() 返回日期date对象
​ time() 返回时间time对象
​ replace() 修改并返回新的时间
​ isocalendar() 返回一个三元组(年,周数,周的天)

​ 日期格式化*
​ 类方法 strptime(date_string, format) ,返回datetime对象
​ 对象方法 strftime(format) ,返回字符串
​ 字符串format函数格式化

import datetime
dt = datetime.datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") print(dt.strftime("%Y-%m-%d %H:%M:%S"))
print("{0:%Y}/{0:%m}/{0:%d} {0:%H}::{0:%M}::{0:%S}".format(dt))
# 2006-11-21 16:30:00
# 2006/11/21 16::30::00

​ timedelta对象
​ datetime2 = datetime1 + timedelta
​ datetime2 = datetime1 - timedelta
​ timedelta = datetime1 - datetime2
​ 构造方法
​ datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
​ year = datetime.timedelta(days=365)
​ total_seconds() 返回时间差的总秒数

标准库time

time
time.sleep(secs) 将调用线程挂起指定的秒数

列表解析List Comprehension

​ 语法
​ [返回值 for 元素 in 可迭代对象 if 条件]
​ 使用中括号[],内部是for循环,if条件语句可选
​ 返回一个新的列表

​ 列表解析式是一种语法糖
​ 编译器会优化,不会因为简写而影响效率,反而因优化提高了效率
​ 减少程序员工作量,减少出错
​ 简化了代码,但可读性增强

even = []
for x in range(10):
	if x % 2 == 0:
		even.append(x)
		
		
even = [x for x in range(10) if x%2==0]
[expr for item in iterable if cond1 if cond2]
	
ret = []
for item in iterable:
	if cond1:
		if cond2:
			ret.append(expr)

[expr for i in iterable1 for j in iterable2 ]
ret = []
for i in iterable1:
	for j in iterable2:
		ret.append(expr)

生成器表达式Generator expression

​ 语法
​ (返回值 for 元素 in 可迭代对象 if 条件)
​ 列表解析式的中括号换成小括号就行了
​ 返回一个生成器
​ 和列表解析式的区别
​ 生成器表达式是按需计算(或称惰性求值、延迟计算),需要的时候才计算值
​ 列表解析式是立即返回值
​ 生成器
可迭代对象
迭代器

g = ("{:04}".format(i) for i in range(1,11)) 
next(g)
for x in g:
	print(x)
for x in g:
	print(x)
# 延迟计算
# 返回迭代器,可以迭代
# 从头走到完,不能回头,除非生成新的
g = ["{:04}".format(i) for i in range(1,11)] 
for x in g:
	print(x)
for x in g:
	print(x)
# 立即计算
# 返回的不是迭代器,返回可迭代对象列表
# 从前到后早完一遍后,可以重新回头迭代

和列表解析式的对比

​ 计算方式

	生成器表达式延迟计算,列表解析式立即计算

​ 内存占用

​ 但从返回值本身来说,生成器表达式省内存,列表解析式返回新的列表

​ 生成器没有数据,内存占用极少,但是使用的时候,虽然一个个返回数据,但是合起来占用的内存也差不多

​ 列表解析式构造新的列表需要占用内存

​ 计算速度

​ 单看计算时间看,生成器表达式耗时非常短,列表解析式耗时长

​ 但是生成器本身并没有返回任何值,只返回了一个生成器对象

​ 列表解析式构造并返回了一个新的列表

集合解析式

​ 语法
​ {返回值 for 元素 in 可迭代对象 if 条件}
​ 列表解析式的中括号换成大括号{}就行了
​ 立即返回一个集合
​ 用法
​ {(x,x+1) for x in range(10)}
​ {[x] for x in range(10)} #

字典解析式

​ 语法
​ {返回值 for 元素 in 可迭代对象 if 条件}
​ 列表解析式的中括号换成大括号{}就行了
​ 使用key:value形式
​ 立即返回一个字典
​ 用法

{x:(x,x+1) for x in range(10)}
# {0: (0, 1),
# 1: (1, 2),
# 2: (2, 3),
# 3: (3, 4),
# 4: (4, 5),
# 5: (5, 6),
# 6: (6, 7),
# 7: (7, 8),
# 8: (8, 9),
# 9: (9, 10)}
{x:[x,x+1] for x in range(10)}
# {0: [0, 1],
# 1: [1, 2],
# 2: [2, 3],
# 3: [3, 4],
# 4: [4, 5],
# 5: [5, 6],
# 6: [6, 7],
# 7: [7, 8],
# 8: [8, 9],
# 9: [9, 10]}
{(x,):[x,x+1] for x in range(10)}
#{(0,): [0, 1],
# (1,): [1, 2],
# (2,): [2, 3],
# (3,): [3, 4],
# (4,): [4, 5],
# (5,): [5, 6],
# (6,): [6, 7],
# (7,): [7, 8],
# (8,): [8, 9],
# (9,): [9, 10]}
{[x]:[x,x+1] for x in range(10)} 
# TypeError 
{chr(0x41+x):x**2 for x in range(10)}
#{'A': 0,
# 'B': 1,
# 'C': 4,
# 'D': 9,
# 'E': 16,
# 'F': 25,
# 'G': 36,
# 'H': 49,
# 'I': 64,
# 'J': 81}
{str(x):y for x in range(3) for y in range(4)}
# {'0': 3, '1': 3, '2': 3}

​ 用法

{str(x):y for x in range(3) for y in range(4)} 
# {'0': 3, '1': 3, '2': 3}

ret = {}
for x in range(3):
	for y in range(4):
		ret[str(x)] = y

总结

​ Python2 引入列表解析式
​ Python2.4 引入生成器表达式
​ Python3 引入集合、字典解析式,并迁移到了2.7
​ 一般来说,应该多应用解析式,简短、高效
​ 如果一个解析式非常复杂,难以读懂,要考虑拆解成for循环
​ 生成器和迭代器是不同的对象,但都是可迭代对象

三、内建函数

​ 标识 id
​ 返回对象的唯一标识,CPython返回内存地址
​ 哈希 hash()
​ 返回一个对象的哈希值
​ 类型 type()
​ 返回对象的类型
​ 类型转换
​ float() int() bin() hex() oct() bool() list() tuple() dict() set() complex() bytes() bytearray()
​ 输入 input([prompt])
​ 接收用户输入,返回一个字符串
​ 打印 print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)
​ 打印输出,默认使用空格分割、换行结尾,输出到控制台

​ 对象长度 len(s)
​ 返回一个集合类型的元素个数
​ isinstance(obj, class_or_tuple)
​ 判断对象obj是否属于某种类型或者元组中列出的某个类型
​ isinstance(True, int)
​ issubclass(cls, class_or_tuple)
​ 判断类型cls是否是某种类型的子类或元组中列出的某个类型的子类
​ issubclass(bool, int)

​ 绝对值abs(x) x为数值
​ 最大值max() 最小值min()
​ 返回可迭代对象中最大或最小值
​ 返回多个参数中最大或最小值
​ round(x) 四舍六入五取偶,round(-0.5)
​ pow(x , y) 等价于 x**y
​ range(stop) 从0开始到stop-1的可迭代对象;range(start, stop[, step])从start开始到stop-1结束步长为step的可迭代对象
​ divmod(x, y) 等价于 tuple (x//y, x%y)
​ sum(iterable[, start]) 对可迭代对象的所有数值元素求和
​ sum(range(1,100,2))

chr(i) 给一个一定范围的整数返回对应的字符
	chr(97)    chr(20013)
ord(c) 返回字符对应的整数
	ord('a')    ord('中')

​ sorted(iterable[, key][, reverse]) 排序
​ 返回一个新的列表,默认升序
​ reverse是反转

sorted([1, 3, 5])
# [1, 3, 5]
sorted([1, 3, 5], reverse=True) 
# [5, 3, 1]
sorted({'c':1, 'b':2, 'a':1})
# ['a', 'b', 'c']

​ 翻转 reversed(seq)
​ 返回一个翻转元素的迭代器

for x in reversed(['c','b','a']):
	print(x)
# a b c 

​ 枚举 enumerate(seq, start=0)
​ 迭代一个序列,返回索引数字和元素构成的二元组
​ start表示索引开始的数字,默认是0

for x in enumerate([2,4,6,8]):
	print(x)
for x in enumerate("abcde"):
	print(x,end=" ")
# (0, 2)
#(1, 4)
# (2, 6)
# (3, 8)
# (0, 'a') (1, 'b') (2, 'c') (3, 'd') (4, 'e') 

​ 迭代器和取元素 iter(iterable)、next(iterator[, default])
​ iter将一个可迭代对象封装成一个迭代器
​ next对一个迭代器取下一个元素。如果全部元素都取过了,再次next会抛StopIteration异常

it = iter(range(5))
next(it)
# 0
it = reversed([1,3,5]) 
next(it)
# 5

可迭代对象

​ 能够通过迭代一次次返回不同的元素的对象。
​ 所谓相同,不是指值是否相同,而是元素在容器中是否是同一个,例如列表中值可以重复的,[‘a’, ‘a’],虽然这个列表有2个元素,值一样,但是两个’a’是不同的元素
​ 可以迭代,但是未必有序,未必可索引
​ 可迭代对象有:list、tuple、string、bytes、bytearray、range、set、dict、生成器等
​ 可以使用成员操作符in、not in,in本质上对于线性数据结构就是在遍历对象

3 in range(10)
# True
3 in (x for x in range(10))
# True
3 in {x:y for x,y in zip(range(4),range(4,10))}
# True

迭代器

​ 特殊的对象,一定是可迭代对象,具备可迭代对象的特征
​ 通过iter方法把一个可迭代对象封装成迭代器
​ 通过next方法,迭代 迭代器对象
​ 生成器对象,就是迭代器对象

for x in iter(range(10)):
	print(x)
g = (x for x in range(10))
print(type(g)) 
print(next(g))
print(next(g))
# 0 1 2 3 4 5 6 7 8 9
# <class 'generator'> 
# 0
# 1

​ 拉链函数zip(*iterables)
​ 像拉链一样,把多个可迭代对象合并在一起,返回一个迭代器
​ 将每次从不同对象中取到的元素合并成一个元组

list(zip(range(10),range(10)))
# [(0, 0),(1, 1),(2, 2),(3, 3),(4, 4)l, (5, 5),(6, 6),(7, 7),(8, 8),(9, 9)]
list(zip(range(10),range(10),range(5),range(10)))
# [(0, 0, 0, 0), (1, 1, 1, 1), (2, 2, 2, 2), (3, 3, 3, 3), (4, 4, 4, 4)]

dict(zip(range(10),range(10)))
# {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
{str(x):y for x,y in zip(range(10),range(10))}
# {'0': 0,'1': 1,'2': 2,'3': 3, '4': 4,'5': 5,'6': 6,'7': 7,'8': 8,'9': 9}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值