python 小数据池copy文件操作

Posted 北边的大鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 小数据池copy文件操作相关的知识,希望对你有一定的参考价值。

一、编码进阶

# 字符串转换成bytes型
s1 = \'taibai\'
s2 = b\'taibai\' # 默认的str是(py2.x里的)unicode, bytes是(py2.x)的str, b+字符串代表的就是bytes 


# 将字符串的第一个字母变成大写,其他字母变小写
s1 = b\'lily\'
print(s1.capitalize())


# 编码
str ---> bytes  编码 encode()
s1 = \'alex\'
b1 = s1.encode(\'utf-8\')  # 编码
b2 = s1.encode(\'gbk\')
print(s1, type(s1))
print(b1, type(b1))
print(b2, type(b2))

# 解码
s1 = \'猪八戒\'
b1 = s1.encode(\'utf-8\')
b2 = s1.encode(\'gbk\')
print(s1,b1)
print(s1,b2)

bytes ---> str  decode()解码
b1 = b\'\\xe5\\xa4\\xaa\\xe7\\x99\\xbd\'
s1 = b1.decode(\'gbk\')
print(s1)

 

二、小数据池

1. id  查看内存地址

s1 = \'太白\'
s2 = \'太白\'
print(s1 == s2)  # 值是否相等
print(id(s1))
print(id(s2))# 内存地址

2. is 身份运算 判断的是内存地址是否相同

s1 = \'太白\'
s2 = \'太白\'
print(s1 is s2) # 判断内存地址是否相等

3. 小数据池

i1 = -3
int: -5 ~ 256 范围之内
str: 满足一定得规则的字符串(详见博客https://www.cnblogs.com/jin-xin/articles/9439483.html)

小数据池的优点:
1,节省空间。
2,提高性能。

 

三、集合

  集合里面的元素必须是不可变的数据类型,集合本身是可变的数据类型。

  集合是无序的,不重复。

print({[1, 2, 3], {\'name\': \'lily\'}})
print({\'lily\', \'marry\', \'tony\', \'老猪\', \'AnNi\'})

 

1、 列表去重。  

l1 = [1, 1, 2, 3, 4, 3, 2, 4, 5, 6]
set1 = set(l1)  # 
print(set1)  # {1, 2, 3, 4, 5, 6}
l1 = list(set1)
print(l1)  # [1, 2, 3, 4, 5, 6]

 

2、关系测试。

set1 = {\'lily\', \'marry\', \'tony\', \'老猪\', \'AnNi\'}
for i in set1:
    print(i)

 

3、不可变的数据类型

set2 = frozenset({1, 2, 3, 7})  # frozenset() 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素
print(set2, type(set2))  # 不可变的数据类型
dic = {set2: 666}
print(dic)
for i in set2:
    print(i)

 

4、集合的增删改查

# 1、集合的创建
set1 = set({1, 2, \'barry\'})
set2 = {1, 2, \'barry\'}
print(set1, set2)  # 结果为:{1, 2, \'barry\'} {1, 2, \'barry\'}

# 2、集合的增
set1 = {\'alex\', \'wusir\', \'ritian\', \'egon\', \'barry\'}
set1.add(\'景女神\')
print(set1)

# 3、update:迭代着增加
set1.update(\'A\')
print(set1)
set1.update(\'老师\')
print(set1)
set1.update([1, 2, 3])
print(set1)

# 4、集合的删
set1 = {\'alex\', \'wusir\', \'ritian\', \'egon\', \'barry\'}

set1.remove(\'alex\')  # 删除一个元素
print(set1)

set1.pop()  # 随机删除一个元素
print(set1)

set1.clear()  # 清空集合
print(set1)

del set1  # 删除集合
print(set1)

# 5、集合的计算
set2 = {4, 5, 6, 7, 8}
set1 = {1, 2, 3, 4, 5}
print(set2 - set1)  # {8, 6, 7} 只输出set2中比set1中多余的部分
print(set1.difference(set2))  # {1, 2, 3} 只输出set1中比set2中多余的部分

 

5、集合的其他操作:

# 1、交集
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
print(set1 & set2)  # {4, 5}
print(set1.intersection(set2))  # {4, 5}

# 2、并集。(| 或者 union)
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
print(set1 | set2)  # {1, 2, 3, 4, 5, 6, 7,8}
print(set2.union(set1))  # {1, 2, 3, 4, 5, 6, 7,8}

# 3、差集。(- 或者 difference)
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
print(set1 - set2)  # {1, 2, 3}
print(set1.difference(set2))  # {1, 2, 3}

# 4、反交集。 (^ 或者 symmetric_difference)
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
print(set1 ^ set2)  # {1, 2, 3, 6, 7, 8}
print(set1.symmetric_difference(set2))  # {1, 2, 3, 6, 7, 8}

# 5、frozenset 不可变集合,让集合变成不可变类型。
s = frozenset(\'barry\')
print(s, type(s))  # frozenset({\'a\', \'y\', \'b\', \'r\'}) <class \'frozenset\'>

 

四、深浅copy

1、赋值运算

l1 = [\'alex\', \'女神\',]
l2 = l1  # 赋值运算
l1.append(\'日天\')
print(l1, id(l1))  # [\'alex\', \'女神\', \'日天\'] 4348215176
print(l2, id(l2))  # [\'alex\', \'女神\', \'日天\'] 4348215176
#  赋值运算是相同的内存地址

 

2、浅copy 第一层开辟的新的内存地址,但是从第二层乃至更深的层来说,公用的都是一个。

l1 = [1, 2, 3, [\'大锤\', \'悟空\']]

l2 = l1.copy()  # 不同的内存地址
print(l1, id(l1))  # [1, 2, 3, [\'大锤\', \'悟空\']] 4399517640
print(l2, id(l2))  # [1, 2, 3, [\'大锤\', \'悟空\']] 4400231496


l1[1] = 222  # 第一层是不同的内存地址
print(l1, id(l1))  # [1, 222, 3, [\'大锤\', \'悟空\']] 4399517640
print(l2, id(l2))  # [1, 2, 3, [\'大锤\', \'悟空\']] 4400231496

l1[3][0] = \'wusir\'  # 第二层是相同的内存地址
print(l1, id(l1[3]))  # [1, 222, 3, [\'wusir\', \'悟空\']] 4399517576
print(l2, id(l2[3]))  # [1, 2, 3, [\'wusir\', \'悟空\']] 4399517576

 

小总结: 

对于浅copy来说,第一层创建的是新的内存地址,而从第二层开始,指向的都是同一个内存地址,所以,对于第二层以及更深的层数来说,保持一致性。

 

3、深拷贝deepcopy

import copy
l1 = [1, 2, 3, [\'悟空\', \'大锤\']]

l2 = copy.deepcopy(l1)  # 不同的内存地址
print(l1, id(l1))  # [1, 2, 3, [\'悟空\', \'大锤\']] 4421605128
print(l2, id(l2))  # [1, 2, 3, [\'悟空\', \'大锤\']] 4421812104

l1[1] = 222  # 不同的内存地址
print(l1, id(l1))  # [1, 222, 3, [\'悟空\', \'大锤\']] 4421605128
print(l2, id(l2))  # [1, 2, 3, [\'悟空\', \'大锤\']] 4421812104

l1[3][0] = \'wusir\'  # 不同的内存地址
print(l1, id(l1[3]))  # [1, 222, 3, [\'wusir\', \'大锤\']] 4421606472
print(l2, id(l2[3]))  # [1, 2, 3, [\'悟空\', \'大锤\']] 4421845320

 

小总结:

对于深copy来说,两个是完全独立的,改变任意一个的任何元素(无论多少层),另一个绝对不改变。

 

五、文件操作

1、文件操作的流程

#  1. 打开文件,得到文件句柄并赋值给一个变量
f=open(\'a.txt\',\'r\',encoding=\'utf-8\')  
# 打开模式就为r,open()是内置函数,用来操作文件
# f是文件句柄f1,fh,file_handle,f...都可以作为文件句柄

#  2. 通过句柄对文件进行操作读,写,追加,读写...)
data=f.read()  # data是str类型

#  3. 关闭文件句柄,即关闭文件
f.close()

 

 

2、关闭文件的注意事项

打开一个文件包含两部分资源:操作系统级打开的文件 + 应用程序的变量。
在操作完毕一个文件时,必须把与该文件的这两部分资源一个不落地回收,回收方法为:
1、f.close()  # 回收操作系统级打开的文件
2、del f  # 回收应用程序级的变量

其中del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件还没有关闭,白白占用资源,
而python自动的垃圾回收机制决定了我们无需考虑del f,这就要求我们在操作完毕文件后,一定要记住f.close()

虽然我这么说,但是很多同学还是会忘记f.close(), 所以我们推荐傻瓜式操作方式:使用with关键字来帮我们管理上下文
with open(\'a.txt\', \'w\') as f:
    pass

with open(\'a.txt\', \'r\') as read_f, open(\'b.txt\', \'w\') as write_f:
    data = read_f.read()
    write_f.write(data)

 

3、文件的编码

f=open(...)是由操作系统打开文件,那么如果我们没有为open()指定编码,那么打开文件的默认编码很明显是操作系统说了算了,操作系统会用自己的默认编码去打开文件,在windows下是gbk,在linux下是utf-8。

# 若要保证不乱码,文件以什么方式存的,就要以什么方式打开。
f=open(\'a.txt\',\'r\',encoding=\'utf-8\')

 

4、文件的打开模式

# 1. 打开文件的模式有(默认为文本模式):
r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
w,只写模式【不可读;不存在则创建;存在则清空内容】
a, 只追加写模式【不可读;不存在则创建;存在则只追加内容】

# 2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作
#   (而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
rb 
wb
ab
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码

# 3,‘+’模式(就是增加了一个功能)
r+, 读写【可读,可写】(删除以前的所有数据)
w+,写读【可写,可读】
a+, 写读【可写,可读】

# 4,以bytes类型操作的读写,写读,写读模式
r+b, 读写【可读,可写】
w+b,写读【可写,可读】
a+b, 写读【可写,可读】

 

5、文件的常用操作方法

  5-1、文件操作--读(r)   

# r  只读模式
# 第一种 read() 全部读取
f1 = open(\'a.txt\', encoding=\'utf-8\')  # 默认的打开方式是r,可以不用写
content1 = f1.read()  # 读取全部的文件内容,str类型
print(content1)
f1.close()


# 第二种 read(n)  打开模式为文本时按照字符去读取,打开方式为b模式时,代表读取3个字节
f1 = open(\'a.txt\', encoding=\'utf-8\')  # 原文件内容为:王大锤啊
content2 = f1.read(3)  # 只读取前三个字符
print(content2)  # 结果为:王大锤
f1.close()

f1 = open(\'a.txt\',  mode=\'rb\')  # 原文内容为: 12345,b模式打开的不能规定编码格式
content1 = f1.read(3)  # 按照字节读取前三个字符
print(content1)  # 结果为:b\'123\' ,表示b方式的结果为123
f1.close()


# 第三种 readline() 按行读取,无内容输出空。
# readline(n)  读取当前行的前n个字符
f1 = open(\'a.txt\', encoding=\'utf-8\')
print(f1.readline().strip())  # 读取第一行
print(f1.readline().strip())  # 读取第二行
print(f1.readline().strip())  # 读取第三行,第三行无内容,当前行就为空
print(f1.readline(3).strip())  # 读取第四行的前三个字符
f1.close()
print(666)  # 在关闭文件后再次输出


# 第四种 readlines() 返回一个列表,列表中的每个元素是原文件的一行
# readlines(n) 从文件中读取前n个字符,只返回这n个字符所在的字符串
f1 = open(\'a.txt\', encoding=\'utf-8\')
# 文件内容会以单行为一个元素,存储成一个列表,每个元素是字符串格式,
# 行末换行以\\n的格式存储在这一行的所在的元素中,如[\'1234\\n\', \'qwer\\n\']
content3 = f1.readlines()
print(content3)  # content为list格式
f1.close()

# readlines(n) 加参数的例子
f1 = open(\'a.txt\', encoding=\'utf-8\')
content4 = f1.readlines(4)  # [\'1234\\n\'],只输出前四个字符所在行的字符串
content5 = f1.readlines(5)  # [\'1234\\n\', \'qwer\\n\'],输出前5个字符所在行的字符串,不包含换行
print(content4)
print(content5)
f1.close()


# 第五种 for循环,循环输出每行的内容
f1 = open(\'a.txt\', encoding=\'utf-8\')
for line in f1:  # 依次读取每行
    print(line.strip())  # 去掉每行头尾空白
f1.close()

# for 循环的第二种方法,借助readlines
f1 = open(\'a.txt\', encoding=\'utf-8\')
for line in f1.readlines():  
    print(line.strip())
f1.close()


# 第六种  rb 按照二进制位进行读取
f1 = open(\'b.jpg\', mode=\'rb\')  # 读取图片文件b.jpg
content6 = f1.read()
print(content6, type(content6))  # byte类型
f1.close()


# 第七种  wb 按字节的方式写如 (此例是读取其他图片内容,并写入新文件)
f1 = open(\'b.jpg\', mode=\'rb\')
content7 = f1.read()
f2 = open(\'c.jpg\', mode=\'wb\')
f2.write(content7)  # 或者可以写成f2.write(f1.read())读取f1文件的内容,写入f2(即复制图片并重命名)
f1.close()
f2.close()


# 第八种  r+ 先读后写(后追加)
f1 = open(\'a.txt\', encoding=\'utf-8\', mode=\'r+\')
content8 = f1.read()  # 先以读的方式打开文件
f1.write(\'666\')  # 写入文件内容666,此处没有换行,所以写入的位置是在原文件最后一行的末尾
f1.write(\'\\n来了\')  # 加了\\n, 会在原来文件的最后一行后换行再输入内容
print(f1.read())
f1.close()

  

  5-2、文件操作--写(w)   

# w  只写模式【不可读;不存在则创建;存在则清空内容】
# 1,没有文件创建文件写入内容。
# 2,有文件先清空后写入。
f1 = open(\'a.txt\', encoding=\'utf-8\', mode=\'w\')
f1.write(\'又好了...\')
f1.close()

 

 

  5-3、文件操作--追加(a)  

# a 只追加写模式【不可读;不存在则创建;存在则只追加内容】
# 1,没有文件创建文件写入内容。
# 2,有文件直接在后面追加。
f1 = open(\'a.txt\', encoding=\'utf-8\', mode=\'a\')
f1.write(\'\\n喇叭坏了 fuck\')
f1.close()

  

  5-4、文件操作常用的方法  

# readable() 检查指定的文件是否可读,如果文件可读,readable()这个函数返回True,否则返回False
f1 = open(\'log1\', encoding=\'utf-8\', mode=\'w\')  # 前提:没有log1文件
if f1.readable():  # 判断文件是否可读
    print(f1.read())   # 如果可读,输出文件内容
print(f1.readable())  # 如果不可读,返回readable()这个函数的值:True或False
f1.close()


# writable() 检查指定的文件是否可写,如果文件可写,readable()这个函数返回True,否则返回False
f1 = open(\'log1\', encoding=\'utf-8\', mode=\'w\')  # 前提:没有log1文件
if f1.writable():  # 判断文件是否可写
    pass   # 如果可写,pass
print(f1.writable())  # 如果不可写,先创建文件,再返回writable()这个函数的值:True或False
f1.close()


# tell() 告诉你光标的位置(按照字节),换行也算
f1 = open(\'a.txt\', encoding=\'utf-8\')
content = f1.read()  # 全部读取
print(f1.tell())  # 因为是全部读取,所以当前光标所在位置是文件的最后一个字符后一个位置
f1.close()

f1 = open(\'a.txt\', encoding=\'utf-8\')
content1 = f1.read(3)  # 读取前三个字符
print(f1.tell())  # 只读取前三个字符,所以当前光标所在位置是第三个字符的位置,结果为3
f1.close()


# seek() 调整光标的位置(按照字节),输出当前字节后的文件内容,换行符也算,后边无内容不会报错
f1 = open(\'a.txt\', encoding=\'utf-8\')  # 原文件内容为qwerty
f1.seek(4)  # 原光标位置在文件开头,现在调整到文件第四个字符的位置,即光标所在位置为r
content2 = f1.read()
print(content2)  # 结果为ty
f1.close()



# fileno 件描述符
# flush 刷新文件内部缓冲区
# isatty 判断文件是否是同意tty设备
f1 = open(\'a.txt\', encoding=\'utf-8\')
content1 = f1.fileno()
content2 = f1.flush()
content3 = f1.isatty()
print(content1)
print(content2)
print(content3)
f1.close()

# readinto 读取到缓冲区,不要用,将被遗弃
# truncate(self, size=None): 截断数据,文件内容仅保留指定之前数据
f1 = open(\'a.txt\', \'r+\')  # 因为需要读且修改,所以是r+,原文件内容为qwer
f1.truncate(3)  # 截取到第3个字符
content4 = f1.read() # 读取截取完的文件
print(content4)  # 结果为qwe,文件内容被更改成qwe
f1.close()

# write 写入指定字符串,原文件内容会被删除
f1 = open(\'a.txt\', \'w\')
f1.write(\'大锤\')  # 原文件内容被删除,内容只有:大锤
f1.close()

# writelines  按写入指定字符串,原文件内容会被删除
f1 = open(\'a.txt\', \'w\')
seq = [\'第一行\\n\', \'第二行\\n\', \'第三行\']  # 将参数直接赋值给字符串
f1.writelines(seq)  # 读取这个列表,列表中的每个元素是这个文件中的一行
f1.close()

 

 

   5-5、修改文件的方法  

  修改文件不一定是追加,所以w的操作不适用修改

\'\'\'
  修改一个文件的方法:
        1,以读的模式打开原文件
        2,以写的模式打开一个新文件
        3,对原文件的内容进行修改,形成新内容写入新文件
        4,删除原文件
        5,将新文件重命名为原文件。
\'\'\'

# 第一种read() 直接读取原文件全部内容,占用内存
import os
with open(\'a.txt\', encoding=\'utf-8\') as f1, \\
        open(\'b.txt\', encoding=\'utf-8\', mode=\'w\') as f2:  # 以读的方式打开原文件a,以写的方式打开新文件b
    old_content = f1.read()  # 读取原文件内容,全部存入内存
    new_content = old_content.replace(\'123\', \'SB\')  # 对原文件内容进行修改
    f2.write(new_content)  # 将修改后的内容写入新文件
os.remove(\'a.txt\')  # 删除相对路径下的原文件,如果是绝对路径,要写上路径
os.rename(\'b.txt\', \'a.txt\')  # 将新文件的名字命名为原文件,原文件会被删除,相当于新文件覆盖了原文件


# 第二种用for循环读取文件内容,节省内存
import os
with open(\'a.txt\', encoding=\'utf-8\') as f1, \\
        open(\'b.txt\', encoding=\'utf-8\', mode=\'w\') as f2:
    for line in f1:  # 循环读取每一行,一行一行存入内存
        new_line = line.replace(\'SB\', \'123\')  # 如果读取到这一行内容有SB,则替换成123
        f2.write(new_line)  # 把新修改的行写入到文件2
os.remove(\'a.txt\')  # 删除原文件
os.rename(\'python集合深浅copy

小数据池 深浅copy 集合

python 深浅拷贝,集合 ,小数据池 操作

Python小数据池和字典操作

python之路——集合and 深浅copy

python 06 id is == set 深浅copy