逻辑运算符:与或非 and or not
and 如果前面的表达式等价为False,后面就没有必要计算了,这个逻辑表达式最终一定等价为False
or 如果前面的表达式等价为True,后面没有必要计算了,这个逻辑表达式最终一定等价为True
赋值运算符:先算右边后再赋值给左边变量
成员运算符: in 、not in
身份运算符: is 、is not

优先级:
算数运算符 > 位运算符 > 身份运算符 > 成员运算符 > 逻辑运算符
单目 > 双目
记不住用括号,长表达式多用括号,易懂易读

表达式Expression: 由数字、符号、括号、变量等的组合
算数表达式
逻辑表达式
赋值表达式 python中,赋值即定义,如果一个变量已经定义,赋值相当于重新定义

内存管理:
变量无须事先声明,也不需要指定类型,这是动态语言的特性
Python编程中一般无须关心变量的存亡,一般也不用关心内存的管理
Python使用引用计数记录所有对象的引用数,当对象引用数变为0,它就可以被垃圾回收GC
计数增加:赋值给其他变量就增加引用计数,例如x=3; y=x; z=[x,1] ;实参传参,如foo(y)
计数减少:函数运行结束时,局部变量就会被自动销毁,对象引用计数减少;变量被赋值给其他对象,例如:x=3; y=x; x=4;
有关性能的时候,就需要考虑变量的引用问题,但是该释放内存还是尽量不释放内存,看需求

for 循环中的 else 关键字指定循环结束时要执行的代码块

round(-2.5) 4舍 6入 5取偶

类型判断:
type(obj) 返回类型,而不是字符串
isinstance(obj, class_or_tuple) 返回布尔值

列表

一个列队,一个排列整齐的队伍

index(value,[start,[stop]])
L9.index(10) :查询到第一个后就不再遍历,括号中是value,随着列表中元素的增加,index 函数的效率下降,随着列表元素规模的增加,性能下降,有n元素个,时间复杂度,O(n)。匹配不到,抛出异常ValueError

count(value)
L1.count(100) :返回列表中匹配value的次数,全部遍历 O(n),随着列表数据规模的增大,而效率下降

len(list)
返回列表元素的个数

max(list)
返回列表元素最大值

min(list)
返回列表元素最小值

append(obj)
在列表末尾添加新的对象 就地修改

insert(index, obj)
将对象插入列表

extend()
L1.extend(rang(7,10)):在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)

[[1]] # [address:401] 401住着1 
# 1 、‘abc’ 字面常量,称为简单类型
# [1] 复杂类型,应用类型
l1 = [[1]] * 5  # [ a401 , a401, a401, a401, a401]  [[1],[1],[1],[1],[1]]
l1[0][0] = 100  # 修改的是 a401地址存储的值
l1 
[[100], [100], [100], [100], [100]]

remove(value) -> None
从左至右查找第一个匹配value的值,找到就移除该元素,并返回None,否则ValuError,就地修改

pop([index]) -> item
不指定索引index,就从列表尾部弹出一个元素
指定索引index,就从索引处弹出一个元素,索引超界抛出IndexError错误

reverse()
反向列表中元素

sort( key=None, reverse=False)
对原列表进行排序

copy()
复制列表

clear() -> None
清除列表所有元素,剩下一个空列表

随机数:
random模块
randint(a,b) 返回[a,b]之间的整数
choice(seq) 从非空序列的元素中随机挑选一个元素,random.choice(range(10)) 从0到9中随机挑选一个整数。random.choice([1,3,5,7])
randrange([start,]stop[,step]) 从指定范围内,按指定基数递增的集合中获取一个随机数,基数缺省值为1。random.randrange(1,7,2)
random.shuffle(list) -> None 就地打乱列表元素
sample(population, k) 从样本看空间或总体(序列或者集合类型)中随机取出k个不同的元素,返回一个新的列表

三目运算符:
True if 条件 else False

a = 10
b = 15
if a > b:
    a > b
else:
    a < b

a > b if a > b else a < b

exp1 if contion else exp2
condition 是判断条件,exp1 和 exp2 是两个表达式。如果 condition 成立(结果为真),就执行 exp1,并把 exp1 的结果作为整个表达式的结果;如果 condition 不成立(结果为假),就执行 exp2,并把 exp2 的结果作为整个表达式的结果。

命名元组namedtuple
namedtuple(typename,field_names,verbose=False,rename=False)
命名元组,返回一个元组的之类,并定义了字段,field_names可以时空白符或逗号分割的字段的字符串,可以是字段的列表
同元组一样,命名元组的属性们的值不可变

from collections import namedtuple
Point = namedtuple('Point' , ['x','y'])
p1 = Point(4, 5)   # 一旦赋值 ,不可修改
p1.x , p1.y  # (4, 5)

Student = namedtuple('Student','name age')
tom = Student('tom',20)
jerry = Student('jerry',18)
tom.name , jerry.age  # ('tom', 18)

class A : 
    def __init__(self, x, y):
        self.x = x 
        self.y = y 
    def __repr__(self):
        return "A (x={}, y={})".format(self.x , self.y)
		
a = A(5,6)	
a.x , a.y  # (5, 6)

字符串

一个个字符组成的有序的序列,是字符的集合
使用单引号、双引号、三引号引住的字符序列,是不可变对象
Python3起,字符串就是Unicode类型

0x31   ==>  0011 0001    49 
0x41   ==>  0100 0001    65
0x61   ==>  0110 0001    97
a = 'abc'
a = f'{a}+++'  # 差值 3.6版本以上
a    ## 'abc+++'

range(5)        # 惰性
range(0, 5) 

list(range(5))  # 立即
[0, 1, 2, 3, 4]

map(str, range(5))   # 惰性,可迭代对象
<map at 0x14ab30181c8>

b = R'c:\windos\nt'
":".join(b)   # 用 : 连接 b 中的每一个字符  
'c:::\\:w:i:n:d:o:s:\\:n:t'

",".join(map(str, range(5)))    # join后必须是str
'0,1,2,3,4'

rsplit(sep=None,maxsplit=-1) -> list of strings
从右向左开始切,但是输出的字符串字符不会反
sep指定分割字符串,缺省的情况下空白字符串作为分隔符
maxsplit指定分割的次数,-1表示遍历整个字符串

s1 = " I'm \ta super student."
s1.rsplit()  #  ["I'm", 'a', 'super', 'student.']
s1.rsplit('s')   # [" I'm \ta ", 'uper ', 'tudent.']
s1.rsplit('s',maxsplit=1)  #  [" I'm \ta super ", 'tudent.']

partition(sep) -> (head,sep,tail)
从左至右,遇到分隔符就把字符串分割成两部分,返回头、分隔符、尾三部分的三元组;如果没有找到分隔符,就返回头、两个空元素的三元组
sep分割字符串必须指定

s1 = " I'm \ta super student."
s1.partition('s')   # (" I'm \ta ", 's', 'uper student.')
s1.partition('stu')  # (" I'm \ta super ", 'stu', 'dent.')

rpartition(sep) -> (head,sep,tail)
从右至左,遇到分隔符就把字符串分割成两部分,返回头、分隔符、尾三部分的三元组;如果没有找到分隔符,就返回头、两个空元素的三元组

splitlines()

"""\    
a
b
c
""".splitlines()   # 开头三引号后加反斜线 ,否则多切出一段
['a', 'b', 'c']

'a\n\nb\r\n\r\nc\rd\te'.splitlines()
('a', ' ', ' b')

'a     b'.partition('t')    # 特殊例子 切割符	
('a     b', '', '')

upper() 全大写
lower() 全小写
swapcase() 交换大小写
title() -> str 标题的每个单词都大写
capitalize() -> str 首个单词大写
center(width[,fillchar]) -> str width打印宽度 fillchar填充的字符
zfill(width) -> str width打印宽度,居右,左边用0填充
ljust(width[,fillchar]) -> str 左对齐
rjust(width[,fillchar]) -> str 右对齐

'abc'.upper().lower()    # upper 统一转大写  lower 统一转小写
'abc'

"abC".swapcase()  #大小写转换
'ABc'

str.upper('abc') , 'abc'.upper()
('ABC', 'ABC')

'user-agent'.capitalize()   #  首字母大写
'User-agent'

'user-agent abc'.title() 
'User-Agent Abc'

"abc".center(20,'0')
'00000000abc000000000'

"abc".ljust(20)
'abc                 '

"abc".rjust(20,"0")
'00000000000000000abc'

"abc".zfill(20)
'00000000000000000abc'

replace(old,new[,count]) -> str
字符串中找到匹配替换为新子串,返回新字符串,count表示替换几次,不指定就是替换全部

'www.magedu.com'.replace('w','p')    # 'ppp.magedu.com'
'www.magedu.com'.replace('w','p',2)  # 'ppw.magedu.com'
'x  y'.replace('  ',' ')   # 'x y'

strip([chars]) -> str
从字符串两端去除指定的字符集chars中的所有字符,如果chars没有指定,去除两端的空白字符

'   \n  a bc \t   '.strip() # 默认拿掉字符串两端的所有空白字符
'a bc'

'   \n  a bc \t   '.strip(' ')
'\n  a bc \t'

' \f i am very very very sorry\t\r\n '.strip('\f\t\n\r yiar')
'm very very very so'

' \f i am very very very sorry\t\r\n '.strip('\f\t\n\ryiar')
' \x0c i am very very very sorry\t\r\n '

lstrip([chars]) -> str 从左边开始
rstrip([chars]) -> str 从右边开始

index(sub[,start[,end]]) -> int
在指定的区间[start,end), 从左至右查找子串sub。找到返回正索引,没找到抛出异常ValueError
rindex(sub[,start[,end]]) -> int
在指定的区间[start,end), 从左至右查找子串sub。找到返回正索引,没找到抛出异常ValueError

count(sub[,start[,end]]) -> int
在指定的区间[start,end), 从左至右统计子串sub出现的次数

len(string)
返回字符串的长度,即字符的个数

find、index和count方法都是O(n), 随着列表数据规模的增大,而效率下降

'\t a bc\r\ndef bc'.index('bc',5)   #12  找不到时,返回ValueError
'\t a bc\r\ndef bc'.count('bc')     #2   返回找到几个 没找到时返回0 不报错
'\t a bc\r\ndef bc'.find('abc')     #-1  没有找到时,返回 小于零的数

endswith(suffix[,start[,end]]) -> bool
在指定的区间[star,end) ,字符串是否是suffix结尾
startswith(suffix[,start[,end]]) -> bool
在指定的区间[star,end) ,字符串是否是suffix开头

s = 'I am very very very very sorry'
s.startswith('very',5)    # True
s.endswith('very',5,9)    # True
s.endswith('sorry',5,100) #True

isalnum() -> bool 是否是字母和数字组成
isalpha() 是否是字母
isdecimal() 是否只包含十进制数字
isdigit() 是否全部数字(0~9)
isidentifier() 是不是字母和下划线开头,其他都是字母、数字、下划线
islower() 是否都是小写
isupper() 是否全部是大写
isspace() 是否只包含空白字符

字符串的格式化是一种拼接字符串输出样式的手段,更灵活方便
join 拼接只能使用分隔符,且要求被拼接的是可迭代对象且其元素是字符串
“+” 拼接字符串还算方便,但是非字符串需要先转换为字符串才能拼接

format函数格式字符串语法 ———— Python鼓励使用
“{}{xxx}”.format(*args, **kwargs) -> str
args是可变位置参数,是一个元组
kwargs是可变关键字参数,是一个元组
花括号表示占位符
{}表示按照顺序匹配位置参数,{n}表示取位置参数索引为n的值
{xxx}表示在关键字参数中搜索名称一致的
{{}}表示打印花括号

位置参数:
“{}:{}”.format(‘192.168.1.100’,8888),这就是按照位置顺序用位置参数替换前面的格式字符串的占位符
关键字参数或命名参数:
“{server}{1}{0}”.format(8888,’192.168.1.100′,server=’Web Server Info:’),位置参数按照序号匹配,关键字参数按照名词匹配
访问元素:
“{0[0]}.{0[1]}”.format((‘magedu’,’com’))
对象属性访问:

from collections import namedtuple
Point = namedtuple('Point' , 'x y')
p = Point(4, 5)    
"{0.x},{0.y}".format(p)   #'4,5'

'{0}'.format(list(range(5)))
'[0, 1, 2, 3, 4]'

'{0[4]}'.format(list(range(5)))
'4'

from collections import namedtuple   
Student = namedtuple('Stu','name  age')
tom = Student('tom', 20)
"{}".format(tom)
"Stu(name='tom', age=20)"

"{0.name} is {0.age}".format(tom)   # 不使用
'tom is 20'

"{} is {}".format(tom.name, tom.age, tom)
'tom is 20'

ip = [192, 168, 1, 127]	
"{} {} {} {}".format(*ip)  # *ip 192, 168, 1, 127
'192 168 1 127'

"{:x} {{{}}}   {:#x} {:#X}".format(*ip) 
'c0 {168}  0x1 0X7F'

对齐:

'{0}*{1} = {2:<2}'.format(3,2,2*3)  # '3*2 = 6 '
'{0}*{1} = {2:<02}'.format(3,2,2*3)  # '3*2 = 60'
'{0}*{1} = {2:>02}'.format(3,2,2*3)  # '3*2 = 06'
'{:^30}'.format('centered')  # '           centered           '
'{:*^30}'.format('centered') # '***********centered***********'

进制:

"int:{0:d}; hex:{0:x}; oct:{0:o}; bin:{0:b}".format(42)
# 'int:42; hex:2a; oct:52; bin:101010'

"int:{0:d}; hex:{0:#x}; oct:{0:#o}; bin:{0:#b}".format(42)
# 'int:42; hex:0x2a; oct:0o52; bin:0b101010'

octets = [192, 168, 0, 1]
'{:02X}{:02X}{:02X}{:02X}'.format(*octets)
# 'C0A80001'

浮点数

"{}".format(3**0.5)  #'1.7320508075688772'
"{:f}".format(3**0.5)  # '1.732051'  精度默认6
"{:10f}".format(3**0.5)  #'  1.732051'  右对齐,宽度10
"{:2}".format(102.231)  # '102.231'  宽度为2数字
"{:.2}".format(3**0.5)  # '1.7'  2个数字
"{:.2f}".format(3**0.5)   #'1.73' 小数点后2位
"{:3.2f}".format(3**0.5)  # '1.73' 宽度为3,小数点后2位
"{:20.3f}".format(0.2745)  # '               0.275'  宽度为20,小数点后3位
"{:3.3%}".format(1/3)  #'33.333%'
x = 2 ** 0.5 
"{}".format(x)
'1.4142135623730951'

"{:.3f}".format(x)
'1.414'

"{:^20.2}".format(x)
'        1.4         '

"{:*^20.2}".format(x)
'********1.4*********'

"{:4.4%}".format(x)
'141.4214%'

"{:e}".format(x)
'1.414214e+00'

"{:2}".format(x)
'1.4142135623730951'

"{:.2}".format(x)
'1.4'

Python3引入两个新类型 bytes bytearray

bytes 不可变字节序列
bytearray 字节数组 可变

字符串与bytes
字符串是字符组成的有序序列,字符可以使用编码来理解
bytes是字节组成的有序的不可变序列
bytearray是字节组成的有序的可变序列

编码与解码
字符串按照不同的字符集编码encode返回字节序列bytes
encode(encoding=’utf-8′,errors=’strict’) -> bytes
字节序列按照不同的字符集编码encode返回字符串
bytes.decde(encoding=’utf-8′,errors=’strict’) -> str
bytearray.decde(encoding=’utf-8′,errors=’strict’) -> str

ASCII (American Standard Code for Information Interchange, 美国信息交换标准代码) 是基于拉丁字母的一套单字节编码系统
\t 0x09
\r 0x0d
\n 0x0a
0~9 0x30~0x39
A~Z 0x41~0x5A
a~z 0x61~0x7A

a = '\x0d\x0a\x09'
a
'\r\n\t'

x = 'abc'
y = x.encode()  # x必须是字符串类型
x,y
('abc', b'abc')


y.decode() # bytes类型对象.decode()  二进制 => str 
'abc'

hex(123)
'0x7b'

utf-8 中文大多数都是3字节
utf-8 是一种多字节编码,适合于网络传输,所以在网络中大量的使用
unicode是双字节编码
utf-8和GBK都兼容ascii码

字符串’1′,可以写成 x = ‘1’ ,y =’\x31′
‘\x09’ 就是 ‘\t’
‘\x0d\x0a’ 就是’\r\n’, 但是’\x0d0a’表示’\r0a’,所以得一个一个字节描述

bytes() 空bytes
bytes(int) 指定字节的bytes,被0填充
bytes(iterable_of_ints) -> bytes[0,255]的int组成的可迭代对象
bytes(string,encoding[,errors]) -> bytes 等价于string.encode()
bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer 从一个字节序列或者buffer复制出一个新的不可变的bytes对象
使用b前缀定义,只允许基本ASCII使用字符形式 b’abc9’,使用16进制表示 b”\x41\x61″

和str类型类似,都是不可变类型,所以方法很多都一样。只不过bytes的方法,输入的是bytes,输出的是bytes
b’abcdef’.replace(b’f’,b’k’) #b’abcdek’
b’abc’.find(b’b’) #1

类方法 bytes.fromhex(string) ,string必须是2个字符的16进制的形式,’6161 6a 6b’, 空格将被忽略
bytes.fromhex(‘6162 09 6a 6b00′) # b’ab\tjk\x00’

hex() 返回16进制表示的字符串
‘abc’.encode() # b’abc’
‘abc’.encode().hex() #’ 616263′

索引 b’abcdef'[2] # 99 返回该字节对应的数,int类型 , ‘c’ => \0x63 => 99

bytearray和bytes类型的方法相同
bytearray(b’abcdef’).replace(b’f’,b’k’) # bytearray(b’abcdek’)
bytearray(b’abc’).find(b’b’) # 1

类方法 bytearray.fromhex(string)
string必须是2个字符的16进制的形式,’6162 6a 6′ ,空格将被忽略
bytearray.fromhex(‘6162 09 6a 6b00′) #bytearray(b’ab\tjk\x00’)

hex() 返回16进制表示的字符串
bytearray(‘abc’.encode()) # bytearray(b’abc’)
bytearray(‘abc’.encode()).hex() #’616263′

索引 bytearray(b’abcdef’)[2] # 99 返回该字节对应的数,int类型

append(int) 尾部追加一个元素
insert(index, int) 在指定索引位置插入元素
extend(iterable_of_ints) 将一个可迭代的整数集合追加到当前byterray
pop(index=-1) 从指定索引上移除元素,默认从尾部移除
remove(value) 找到第一个value移除,找不到抛ValueError异常
注意:上述方法若需要使用int类型,值在[0,255]
clear() 清空bytearray
reverse() 翻转bytearray,就地修改

b = bytearray()
b.append(97)          # bytearray(b'a')
b.append(99)          # bytearray(b'ac')
b.insert(1,98)        # bytearray(b'abc')
b.extend([65,66,67])  # bytearray(b'abcABC')
b.remove(66)          # bytearray(b'abcAC')
b.pop()               # 67   bytearray(b'abcA')
b.reverse()           # bytearray(b'Acba')
b.clear()             # bytearray(b'')

int和bytes
int.from_bytes(bytes,byteorder) 将一个字节数组表示成整数
int.to_bytes(length,byteorder) bytearray字节序 将一个整数表达成一个指定长度的字节数组

i = int.from_bytes(b'abc','big')
print(i, hex(i))    # 6382179 0x616263
print(i.to_bytes(3,'big'))  # b'abc'

b1 = bytearray()
b1.append(97)  # bytearray(b'a')
b1.extend(range(98,100)) # bytearray(b'abc')

线性结构特征:
可迭代 for … in
有长度,通过len(x)获取,容器
通过整数下标可以访问元素。正索引、负索引、可以切片
sequence[start:stop]
sequence[start:stop:step]
通过给定的索引区间获得线性结构的一部分数据
start、stop、step为整数,可以是正整数、负整数、零
start为0时,可以省略
stop为末尾时,可以省略
step为1时,可以省略
切片时,索引超过上界(右边界),就取到末尾;超过下界(左边界),取到开头
在序列上使用切片[start:stop],子区间索引范围[start:stop],相当于从start开始指向stop的方向上获取数据
默认step为1,表示向右;步长为负数,表示向左
如果子区间方向和步长方向不一致,直接返回当前类型的”空对象”
如果子区间方向和步长方向一致,则从起点间隔步长取值

b = a[i:j]
表示复制a[i]到a[j-1],以生成新的list对象
a = [0,1,2,3,4,5,6,7,8,9]
b = a[1:3] # [1,2]
当i,j都缺省时,a[:] 就相当于完整复制一份a

b = a[i:j:s]
表示:i,j与上面的一样,但s表示步进,默认为1
所以 a[i:j:1] 相当于 a[i:j]

当s<0时,i 缺省时,默认为-1. j 缺省时,默认为-len(a)-1
所以a[::-1]相当于 a[-1:-len(a)-1:-1],也就是从最后一个元素到第一个元素复制一遍,即倒序

a='abcdef'

b=a[::-1]
print(b)    #fedcba

c=a[::-2]
print(c)   # fdb

封装(装箱)

将多个值使用逗号分割,组合在一起,本质上,返回一个元组,只是省掉了小括号
python特有语法,被很多语言学习和借鉴

t1 = (1, 2) 
t2 = 1, 2
type(t1)  # tuple
type(t2)  # tuple

nums = [1,2]
nums[1],nums[0] = nums[0],nums[1]
print(nums)  # [2, 1]

a, *b = 1,2,3,4,5
a, b  # (1, [2, 3, 4, 5])

a, *b ='xyz'
a, b # ('x', ['y', 'z'])

x, [a, b], z = 1, [2, (3, 5)], (2,6)
x, a, b, z  # (1, 2, (3, 5), (2, 6))

* 代表零个或任意个

for x,*y in ((1,), [2,3], (4,5,7), [6]):
    print(x,y)
1 []
2 [3]
4 [5, 7]
6 []

解构

a,*b = (1,2,3)  # (1, [2, 3])
a,b = (1,2,3)   # ValueError: too many values to unpack (expected 2)
a,b = {'a':10, 'b':20}   #非线性解构也可以解构  解构出key

使用 *变量名接收,但不能单独使用,也不能出现多个
被 *变量名 收集后组成一个列表

head, *mid, tail = range(6)
head, mid, tail  # (0, [1, 2, 3, 4], 5)

丢弃变量
这是一个惯例,一个不成文的约定,不是标准
如果不关系一个变量,就可以定义该变量名为 “
“是一个合法的标识符,也可以作为一个有效的变量使用,但是定义成下划线就是希望不要被使用,除非你明确的知道这个数据需要使用

lst = [9,8,7,20]
first, *second = lst
head, *_, tail = lst 
print(head)  # 9 
print(tail)  # 20
print(_)  # [8, 7]

“_” 是合法的表示符,看到下划线就知道这个变量就是不想被使用

_, *_, _, c = range(5)
c  # 4 

“这个变量本身无任何语义,没有任何可读性,所以不是用来给人使用的
Python中很多库,都使用这个变量,使用十分广泛。请不要再不明确作用域的情况下,使用”
“导致和库中”_”冲突

集合set

collection 翻译为集合类型或容器,是一个大概念
set 可变的、无序的、不重复的元素的集合
set() -> new empty set object
set(iterable) -> new set object

s1 = set()  # set()  空集合
s2 = set(range(5))  # {0, 1, 2, 3, 4}
s3 = set(list(range(5)))  # {0, 1, 2, 3, 4}
s4 = {}  # {}
s5 = {9,10,11}  # {9, 10, 11}
s6 = {(1,2), 3, 'a'}  # {(1, 2), 3, 'a'}
s7 = {[1], (1,), 1}   # unhashable type: 'list'

set定义时不能出现 list bytearray dict set 类型 (不可hash)

set的元素要求必须可以hash
元素不可以索引
set可以迭代

set增加
add(elem) 增加一个元素到set中,如果元素存在,什么都不做
update(*others) 合并其他元素到set集合中来,参数others必须是可迭代对象,就地修改

s1 = set(range(5))  # {0, 1, 2, 3, 4}
s1.add(4)           # {0, 1, 2, 3, 4}
s1.add(5)           # {0, 1, 2, 3, 4, 5}
s1.add((1,2))       # {(1, 2), 0, 1, 2, 3, 4, 5} 
s1.add((2,1))       # {(1, 2), (2, 1), 0, 1, 2, 3, 4, 5}
s1.add((1,2))       # {(1, 2), (2, 1), 0, 1, 2, 3, 4, 5}

t2 = 'a','b','c'
s1.add(t2)    # {('a', 'b', 'c'), (1, 2), (2, 1), 0, 1, 2, 3, 4, 5}

s2 = set(range(8))   # {0, 1, 2, 3, 4, 5, 6, 7}
s1.update(s2)   #  {('a', 'b', 'c'), (1, 2), (2, 1), 0, 1, 2, 3, 4, 5, 6, 7}

s1.update(s2, range(10,15))  # {('a', 'b', 'c'), (1, 2), (2, 1), 0, 1, 10, 11, 12, 13, 14, 2, 3, 4, 5, 6, 7}

s3 = set(list(range(100,105)))  # {100, 101, 102, 103, 104}
s2 + s3                         # unsupported operand type(s) for +: 'set' and 'set'

set 不可以相加,加的概念是合并

set删除
remove(elem) 从set中移除一个元素,元素不存在,抛出异常KeyError异常
discard(elem) 从set中移除一个元素,元素不存在,什么都不做
pop() -> item 移除并返回任意的元素
clear() 移除所有元素

s3 = set(list(range(100,105)))  # {100, 101, 102, 103, 104}
s3.remove(102)         # {100, 101, 103, 104}
s3.remove(105)         #  KeyError: 105
s3.discard(105)        # 不出错版本的remove

s3   # {100, 101, 103, 104}
s3.pop()   # 100  随机弹出
s3   # {101, 103, 104}

set 是非线性结构,无法索引,可以迭代所有元素
in 和 not in 判断元素是否在set中

list和set的效率比较

l1 = list(range(100))
l2 = list(range(1000000))
%timeit (-1 in l1)
968 ns ± 9.55 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit (-1 in l2)
9.45 ms ± 67 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

l1 = set(list(range(100)))
l2 = set(list(range(1000000)))
%timeit (-1 in l1)
42.1 ns ± 1.78 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%timeit (-1 in l2)
40.8 ns ± 1.77 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

线性结构的查询时间复杂度是O(n), 即随着数据规模的增大而增加耗时
set、dict等结构,内部使用hash值作为key,时间复杂度可以做到O(1),查询时间和数据规模无关

可hash
数值型 int float complex
布尔型 True False
字符串 string bytes
tuple
None
以上都是不可变类型,成为可哈希类型,hashable
set的元素要求必须可以hash

解释器每次运行拿到的hash值不一样,去重时,hash值一样,就不添加

集合运算
并集:将两个集合A和B的所有元素合并到一起,组成的集合称作集合A与集合B的并集
union(*others) 返回和多个集合合并后的新的集合
| 运算符重载 等同union
update(*others) 和多个集合合并,就地修改
|= 等同update

交集:集合A和集合B,由所有属于A且属于B的元素组成的集合
intersection(*others) 返回和多个集合的交集
& 等同 intersection
intersection_update(*others) 获取和多个集合的交集并就地修改
&= 等同intersection_update

差集:集合A和集合B,由所有属于A且不属于B的元素组成的集合
difference(*others) 返回和多个集合的差集

  •                       等同difference
    

difference_update(*others) 获取和多个集合的差集并就地修改
-= 等同difference_update

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

字典dict

key-value键值对的数据集合 可变的、无序的、key不重复
d = dict() 或者 d = {}
dict(**kwargs) 使用 name=value对 初始化一个字典
dict(iterable, **kwargs)使用可迭代对象和 name=value对 构造字典,不过可迭代对象的元素必须是一个二元结构 d = dict(((1,’a’),(2,’b’))) d = dict([(1,’a’),(2,’b’)], c=300)
dict(mapping, **kwargs) 使用一个字典构建另一个字典
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, key不存在抛出KeyError异常
get(key[, default]) 返回key对应的值value, key不存在返回缺省值,如果没有设置缺省值就返回None d1.get(4,’kong’)
setdefault(key[, default]) 返回key对应的值value; key不存在, 添加kv对, value设置为default, 并返回default, 如果default没有设置, 缺省为None d1.setdefault(2,’ef’)

d[key] = value 将key对应的值修改为value, key不存在添加新的kv对
update([other]) -> None 使用另一个字典的kv对更新本字典,key不存在就添加,key存在则覆盖已经存在的key对应的值,就地修改 d2.update({5:’ad’}) d2.update(((‘red’,3),)) d2.update(red=1)

pop(key[, default]) key存在,移除它,并返回它的value; key不存在,返回给定的default; default未设置,key不存在抛出KeyError异常
popitem() 移除并返回一个任意的键值对,字典为empty,抛出异常KeyError异常
clear() 清空字典

a = True
b = [1]
d = {'a':1, 'b':b, 'c':[1, 3, 5]}
a, b, d    # (True, [1], {'a': 1, 'b': [1], 'c': [1, 3, 5]})
del d['c']   # (True, [1], {'a': 1, 'b': [1]})

看着像删除了一个对象,本质上减少了一个对象的引用,del实际上删除的是名称,而不是对象

字典遍历
for … in dict 遍历item,即kv对 d.keys() d.values()
for item in d.items():
pirint(item)
for item in d.items():
pirint(item[0], item[1])
for k,v in d.items():
pirint(k, v)
for k,_ in d.items():
pirint(k)
for _,v in d.items():
pirint(v)
for 里面允许修改值,但长度不能变化。使用到keys values items ,就不能进行kv对增加和kv对减少
while 里可以删除,修改字典长度。因为没有用到keys values items 方法

Python3中,keys、 values、 items方法返回一个类似一个生成器的可迭代对象,不会把函数的返回结果复制到内存中
Dictionary view对象,可以使用len()、 iter()、 in 操作
字典的entry的动态的视图,字典变化,视图将反映出这些变化
keys返回一个类set对象,也就是可以看做一个set集合。如果values都可以hash,那么items也可以看做是类set对象

字典的key
key的要求和set的元素要求一致,set的元素可以就是看做key,set可以看做dict的简化版
hashable可哈希才可以作为key,可以使用hash()测试

dict从3.6 按录入序记录,但实际hash值千差万别

版权声明:本文为何时明月原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/kiyalone/p/16175156.html