Set 集合
Set是一个无序而且不重复的元素集合。下面看看他有哪些基本功能
创建集合
1
2
3
4
5
6
|
>>> s1
=
{
11
,
22
}
s2
=
set
()
s3
=
set
([
11
,
22
,
33
,
4
])
print
(s1,s2,s3)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{
11
,
22
}
set
() {
33
,
11
,
4
,
22
}
|
把列表转换成集合,注意列表中重复的元素只保留一次
1
2
3
4
5
|
>>> li
=
[
11
,
22
,
11
,
22
]
s1
=
set
(li)
print
(s1)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{
11
,
22
}
|
add给集合添加元素,clear清除集合的内容
1
2
3
4
5
6
7
8
9
10
11
12
|
>>> s
=
set
()
print
(s)
s.add(
123
)
s.add(
123
)
s.add(
123
)
print
(s)
s.clear()
print
(s)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
set
()
{
123
}
set
()
|
两个集合A和B可以通过difference进行比较, 他会输出A中存在,而B中不存在的元素
1
2
3
4
5
6
7
8
9
10
|
>>> s1
=
{
11
,
22
,
33
}
s2
=
{
22
,
33
,
44
}
s3
=
s1.difference(s2)
print
(s3)
# A中存在,B中不存在
s3
=
s2.difference(s1)
print
(s3)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{
11
}
{
44
}
|
symmetric_difference 可以输出两个集合中都不相同的元素
1
2
3
4
5
6
7
8
|
>>> s3
=
s1.symmetric_difference(s2)
print
(s1)
print
(s2)
print
(s3)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{
33
,
11
,
22
}
{
33
,
44
,
22
}
{
11
,
44
}
|
如果后面跟了update,那么他的作用是直接替换到A的结果中,比如A中存在,B中不存在的结果是11,difference_update直接替换了A的内容;类似的如果我再执行symmetric_difference_update,他把A和B都不相同的内容保存在A中。
1
2
3
4
5
6
7
|
>>> s1.difference_update(s2)
print
(s1)
s1.symmetric_difference_update(s2)
print
(s1)
-
-
-
-
-
-
-
-
-
-
-
-
{
11
}
{
33
,
11
,
44
,
22
}
|
删除某一个元素可以用discard 或者 remove,但是如果该元素不存在,使用discard不会报错;而remove会抛出异常
1
2
3
4
5
|
>>> s1
=
{
11
,
22
,
33
,
1111
}
s1.discard(
1111
)
print
(s1)
-
-
-
-
-
-
-
-
-
-
{
33
,
11
,
22
}
|
不报错
1
2
|
>>> s1
=
{
11
,
22
,
33
,}
s1.discard(
1111
)
|
抛出异常
1
2
3
4
5
6
7
|
>>> s1
=
{
11
,
22
,
33
,}
# s1.discard(1111)
s1.remove(
11111
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Traceback (most recent call last):
File
"<input>"
, line
3
,
in
<module>
KeyError:
11111
|
如果随机的删除一个元素,可以使用pop
1
2
3
4
5
6
|
>>> ret
=
s1.pop()
##随机删
print
(s1)
print
(ret)
-
-
-
-
-
-
-
-
-
-
-
-
-
{
11
,
22
}
33
|
求交集(Intersection)和并集(Union)
1
2
3
4
5
6
7
8
9
10
|
>>> s1
=
{
11
,
22
,
33
}
s2
=
{
22
,
33
,
44
}
s3
=
s1.union(s2)
print
(s3)
s3
=
s1.intersection(s2)
s1.intersection_update(s2)
print
(s3)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{
33
,
22
,
11
,
44
}
{
33
,
22
}
|
update可以把其他的列表,元祖或者字符串的元素都并集进来,当然重复的不会添加
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> s1
=
{
11
,
22
,
33
}
s1.add(
11
)
s1.add(
12
)
s1.add(
13
)
li
=
[
11
,
22
,
3
,
11
,
2
]
tup
=
(
11
,
22
,
3
,
11
,
2
)
st
=
"alexalex"
s1.update(li)
s1.update(tup)
s1.update(st)
print
(s1)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{
33
,
2
,
3
,
'l'
,
'a'
,
11
,
12
,
13
,
22
,
'x'
,
'e'
}
|
小练习:两个字典,请判断出哪些key进行了变化,添加,删除和没变?
思路:把key单独转换成集合,然后通过判断集合元素是否存在判断添加和删除;通过交集判断哪些仍然存在为改变
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
>>> old_dict
=
{
"#1"
:
8
,
"#2"
:
4
,
"#4"
:
2
,
}
new_dict
=
{
"#1"
:
4
,
"#2"
:
4
,
"#3"
:
2
,
}
new_set
=
set
(new_dict.keys())
old_set
=
set
(old_dict.keys())
remove_set
=
old_set.difference(new_set)
add_set
=
new_set.difference(old_set)
update_set
=
old_set.intersection(new_set)
print
(remove_set,add_set,update_set)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{
'#4'
} {
'#3'
} {
'#2'
,
'#1'
}
|
文件的操作
打开文件的模式
-
r ,只读模式【默认】
-
w,只写模式【不可读;不存在则创建;存在则清空内容;】
-
x, 只写模式【不可读;不存在则创建,存在则报错】
-
a, 追加模式【可读; 不存在则创建;存在则只追加内容;】
"+" 表示可以同时读写某个文件
-
r+, 读写【可读,可写】最常用
-
w+,写读【可读,可写】清空之后再写,然后可以读之后写入的内容
-
x+ ,写读【可读,可写】
-
a+, 写读【可读,可写】只能在末尾更改,无法灵活指定位置
"b"表示以字节的方式操作
-
rb 或 r+b
-
wb 或 w+b
-
xb 或 w+b
-
ab 或 a+b
文件相关的函数
-
fread() 无参数,读取全部;有参数,有b,按照字节读;有参数,无b,按照字符读
-
tell(), 获取当前位置(字节)
-
seek(), 调到指定的位置(字节)
-
write(), 写入数据, 有b,按照字节;无b,按照字符写入
-
close(), 关闭文件
-
fileno(),文件描述符,判断文件是否有变化
-
flush(), 强制刷新到内容
-
readable(),判断是否可读
-
readline(),按行读
-
truncate(),截断,清空指针后面的内容
-
for 循环
-
with自动关闭文件
下面看看具体的例子
以只读方式打开一个文件db,注意编码我指定为utf-8,在utf-8里面 一个汉字等于3个字节;而在gbk里面,一个汉字占据2个字节。
1
2
3
4
5
6
7
8
|
>>> f
=
open
(
'db'
,
'r'
,encoding
=
"utf-8"
)
data
=
f.read()
print
(data,
type
(data))
f.close()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
sdf
aa
dddd <
class
'str'
>
|
我用只读字节的方式打开文件
1
2
3
4
|
>>> f
=
open
(
'db'
,
'rb'
)
data
=
f.read()
print
(data,
type
(data))
b
'sdf\r\naa\r\ndddd'
<
class
'bytes'
>
|
下面的操作会抛出异常,因为我用字节的方式打开文件,当我尝试用字符串写入的时候,格式不兼容
1
2
3
4
5
6
7
|
>>> f
=
open
(
"db"
,
'ab'
)
f.write(
"hello"
)
f.close()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Traceback (most recent call last):
File
"<input>"
, line
2
,
in
<module>
TypeError: a bytes
-
like
object
is
required,
not
'str'
|
字节的方式添加信息
1
2
3
|
>>> f
=
open
(
"db"
,
'ab'
)
f.write(bytes(
"哈"
,encoding
=
"utf-8"
))
f.close()
|
结果如下
1
2
3
|
sdf
aa
dddd哈
|
以读写方式打开文件,指定只读取前2个字符,注意这里没有指定b,因此是按字符读取;否则按照字节读取;tell()可以获取当前指针的位置(字节)
1
2
3
4
5
6
|
>>> f
=
open
(
"db"
,
'r+'
,encoding
=
"utf-8"
)
data
=
f.read(
2
)
print
(data)
print
(f.tell())
#获取当前指针位置(字节)
sd
2
|
首先读取一个包含汉字的文件,如下所示,我指定了编码是utf-8,也指定了b,因此他是按照字符读取;这里他读取前2个字符“幸福”,然后因为utf-8一个汉字字符是3个字节,因此他的位置是6个字节处
1
2
3
4
5
6
7
|
>>> f
=
open
(
"db"
,
'r+'
,encoding
=
"utf-8"
)
data
=
f.read(
2
)
print
(data)
print
(f.tell())
-
-
-
-
-
-
-
-
-
-
-
-
-
-
幸福
6
|
如果这个时候我对这个文件做个修改,seek指定位置为第一个字节处,然后向后覆盖7777,这个时候他会把汉字(3个字节)硬拆开,导致的结果就是乱码
1
2
3
4
|
>>> f.seek(
1
)
#当前指针位置开始向后面覆盖
f.write(
"7777"
)
f.close()
|
结果如下所示
1
2
3
|
7777sdf
aa
dddd哈
|
flush函数强行把内存的数据写入硬盘保存,尽管还没有close
1
2
3
4
|
>>> f
=
open
(
'db'
,
'a'
)
f.write(
'123'
)
f.flush()
#没有close 但是内容写入了硬盘
input
(
"hhhh"
)
|
readable顾名思义,判断一个文件是否可读,这里我一个只写方式打开的文件返回False
1
2
3
4
|
>>> f
=
open
(
'db'
,
'w'
)
print
(f.readable())
-
-
-
-
-
-
-
-
-
False
|
read()是读取全部,read(x)是读取前x个字节或者字符,而 readline()是读取一行,注意指针位置变化
1
2
3
|
f
=
open
(
'db'
,
'r'
)
f.readline()
#注意指针的变化
f.readline()
|
truncate截断,指针后面的内容清空
1
2
3
|
>>> f
=
open
(
'db'
,
'r+'
,encoding
=
'utf-8'
)
f.seek(
3
)
f.truncate()
|
结果如下
1
|
sds
|
一个很常见的方式是通过for循环来读取每一行的内容,如下所示
1
2
3
4
5
6
7
8
|
>>> f
=
open
(
'db'
,
'r+'
,encoding
=
'utf-8'
)
for
line
in
f:
print
(line)
-
-
-
-
-
-
-
-
-
-
-
-
-
sds
2
234
232sd
|
with自动关闭文件,这样不需要手动的使用 f.close()了
1
2
|
with
open
(
'db'
) as f:
pass
|
Python2.7以后,可以同时操作两个文件,比如说,只读方式打开文件1,拷贝前10行文件到文件2里面
1
2
3
4
5
6
7
8
|
with
open
(
'db1'
,
'r'
,encoding
=
"utf-8"
) as f1,
open
(
'db2'
,
'w'
,encoding
=
'utf-8'
) as f2:
times
=
0
for
line
in
f1:
times
+
=
1
if
times <
=
10
:
f2.write(line)
else
:
break
|