python数据类型补充,copy知识点及文件的操作

数据类型的补充
1,元组中里面如果只有一个元素,且没有逗号,则该数据类型与里面的元素相同
1)例子
tu1 = ('lannanhai')
tu2 = ('laonanhai',)
print(tu1,type(tu1)) #字符串
print(tu2,type(tu2)) #元组
2)例子
tu1 = (1)
tu2 = (1,)
print(tu1,type(tu1)) #整数
print(tu2,type(tu2))#元组

**************list列表小知识点**************

l1 = [111,222,333,444,555,666,777,888,999,]
del l1[1::2]
print(l1) #删除index为奇数的元素,用del 切片
或者用 for循环 但是的从倒着删除 不会改变索引值
for index in range(len(l1)-1,-1,-1): for循环最好不要改变他的长度
***************dict字典**********************
1) dic = dict.fromkeys('abc',666)# 可迭代添加 这个作用是创建新的一个字典
#{‘a’:666,'b':666,'c':666}
一个这个fromkeys有个bug
dic = dict.fromkeys([1,2,3],[]) # 前面无论是什么数据类型 ,迭代的是其中的元素
注意:
dic = dict.fromkeys([1,2,3],[])
dic[1].append(666)
print(id(dic[1]),id(dic[2]),id(dic[3])) id地址一致
dic[1].append(666)
print(dic) # {1:[666],2:[666],3,[666]} # 说明fromkeys中的第二个参数位置id是固定不变得
2) dic = {'k1':'v1','k2':'v2','k3':'v3','name':'alex'}
for i in dic:
if 'k' in i:
del dic[i] # 这样会报错,程序无法进行,因为改变了dict的大小。
所以在循环dict中,最好不要改变dict的大小,会影响结果或者报错。
dic = {'k1':'v1','k2':'v2','k3':'v3','name':'alex'} #正确方法 主要记得使用‘In’的方法,这个没记牢。
l1 = []
for i in dic:
if 'k' in i:
l1.append(i)
print(l1)
for key in l1:
del dic[key]
print(dic)
**********************数据类型的转换***********************
1):
str --->list split()
list --->str join()
2):
tuple ---->list list()
例子 tu1 = (1,2,3)
l1 = list(tu1)
print(l1)
list --->tuple tuple()
3):
dic ---> list list()注意 这样只能将字典中的键给转换成列表

list --->dic dict()注意 无法成功,会报错。
4)list ---> set set() 但要注意list里面必须不可变的元素组成的,否则无法转化,会报错。好的是可以为列表转化为集合 直接去重了
set ----> list
5)
数字0,‘’,[],(),{}---->bool 为Fasle
*************************set集合***********************
集合是一个可变的数据类型,他是以{}形式存在的,里面是一个一个的元素无键值对
空集合set()
set{}是个空字典
但是它要求它里面的元素是不可变得,集合是无序的,不重复的。
作用 1,去重 本身带有去重功能set1 = {11,11,11,22}
   2,关系测试
集合的增删改,因为是无序的无法查

set.add(元素) 增加的是无序的
set.update(元素)迭代添加 按照最小的元素增加

set.remove(元素)
set.pop()随机删除,有返回值
set.clear()清空 得出 set() 创建空集合 set1 = set()
整体删除 del set

只能for循环 遍历查询
for i in set1:
print(i) #得出的是无序的

***************set集合的关系测试***************
交集 & intersetion
set1 = {1,2,3,4,5}
set2 = {4,5,6,7,8}
print(set1 & set2)
并集 | union
差集 - difference :得到set1 独有的元素 (除去了两则的交集值)
反交集:^ symmetric_difference
子集 set1 <set2 issubset "<"返回True 那么set1是set2的子集
set1 = {1,2,3}
set2 = {1,2,3,4,5,6,}
超集 set2 <set1 issuperset ">"返回True set2是set1的超级

set = frozenset({1,2,3,'aqwe'})
将集合冻结 有可变变成不可变得数据类型,可以做字典的键等 类型type是 frozenset类型
***********************copy复制*****************************
l1 = [1,2,3]
l2= l1
l2.append(666)
print(l1,l2)#[1,2,3,666] [1,2,3,666] 说明l1和l2在内存中只是一个
#对于赋值运算来说,指向的都是同一个内存地址,一变都变。

1)浅copy
l1 = [11,22,33]
l2 = l1.copy()
l1.append(666)
print(l1,l2) #l1= [11,22,33,666] l2= [11,22,33]
print(l1,id(l1))
print(l2,id(l2)) id地址不一样,值也不一样。

l1 = [11,22,['barry']]
l2 = l1.copy()
l1[2].append('alex')
print(l1,id(l1))
print(l2,id(l2)) id地址不一样 但是l1 和 l2相同。
print(l1,id(l1[-1]))
print(l2,id(l2[-1])) 列表里的列表 id地址一样
对于浅copy来说,第一层创建的是新的内存地址,而从第二层开始,指向的都是同一个内存地址,所以对于第二层以及更深的层数来说,保持一致性。
对于切片来说,它是浅copy
l1 = [1,2,3,4,5,6,[11,22]]
l2 = l1[:]
l1.append(666)
print(l1,l2) # l1 = [1,2,3,4,5,6,[11,22],666] l2=[1,2,3,4,5,6,[11,22]]
l1[-1].append(666)
print(l1,l2) # l1 = [1,2,3,4,5,6,[11,22,666]] l2=[1,2,3,4,5,6,[11,22,666]]
2)深copy
import copy #引入一个模块
l2 = copy.deepcopy(l1)
深copy各层均是独立的。

对于浅copy来说,只是在内存中重新创建了开辟了一个空间存放一个新列表,但是新列表中的元素与原列表中的元素是公用的。


对于深copy来说,列表是在内存中重新创建的:列表中可变的数据类型是重新创建的,列表中的不可变的数据类型是公用的。


注意:
l1 = [1,2,3] #根据学的小数据池知道,列表没有小数据池的,只有字符串str和int有。
l2 = [1,2,3]
l1.append(666)
print(l1,l2) #l1 = [1,2,3,666] l2=[1,2,3]

切片

l1 = [1,2,3,[11,22]]

l2 = l1[:]

l1.append(666)

print(l1,l2)   结果是不一样的 即第一层id地址是不一样的

l1 = [1,2,3,[11,22]]

l2 = l1[:]

l1[-1].append(666)

print(l1,l2)   结果是一样的,即切片是浅copy

*********************文件操作**************************
python代码:
path 文件路径:
encoding 编码方式: utf-8 gbk....这里的意思是用什么编码方式解码
mode 操作方式: 只读 只写 追加 读写 写读......
f1 = open('d:python练习.txt',encoding = 'utf-8',mode = 'r')
print(f1.read())
f1.close()
# f1 变量f1_obj f1_file file file_handle 文件句柄
#open : python的内置函数,但是底层调用的是windows系统的open功能,open功能就是操作文件用的
注意: windows系统默认的编码方式gbk ;linux,macos:utf-8

流程:1,打开文件,产生文件句柄
    2,对文件句柄进行操作
    3,关闭文件
路径:绝对路径:从根目录开始一直找到文件。
相对路径:从当前目录开始找到的文件。操作同一文件的其他文件。

f1 = open('d:python练习.txt',encoding = 'utf-8',mode = 'r')#绝对路径
print(f1.read())
f1.close()

f1 = open('python练习.txt',encoding = 'utf-8',mode = 'r')#相对路径
print(f1.read())
f1.close()

###utf-8和gbk之间英文字符 数字 特殊字符可以直接转换,但是中文不行,原因是gbk和utf-8对于字母,数字,特殊字符的编码都是引用ascii码,所以可以直接转换。
//读
r模式:如果一个文件不设置mode ,那么默认使用功能r模式 只读操作文件
读返回的是字符串
在r模式下 read(n)n是字符 在rb模式下 read(n)读的是字节
1)read()将文件中的内容全部读取出来,但是如果文件很大就会很占内存,甚至导致内存崩溃

2)read(n) 在只读模式下,n按照字符读取 即 读到文件中的那个字符
3)readline()读取每次只读取一行,注意:readline()读取出来的数据在后面都有一个
解决办法是在文件后面加一个strip() 里面也可以加数字readline(n)
msg1 = f.readline().strip()
4)readlines() 返回一个列表,列表里面每个元素是原文件的每一行,如果文件很大,占内存,崩盘。
以上都不是很好,大文件读取困难
5)for循环
可以通过for循环去读取,文件句柄是一个迭代器,它的特点是每次循环只在内存中占一行的数据,非常节省内存。

f1= open(r'D:python练习2.txt',encoding='gbk',mode= 'r+' )
for line  in f1:
    print(line)
f1.close

注意 读完的文件句柄要关闭
rb模式:文件指针将会放在文件的开头凡是带b 不用声明encoding 
二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。记住下面讲的也是一样,带b的都是以二进制的格式操作文件,他们主要是操作非文字文件:图片,音频,视频等,并且如果你要是带有b的模式操作文件,那么不用声明编码方式。
rb模式中也有 read read(n) readline() readlines() for循环这几种。
r+模式 只的是加一个可以写 及 读写
先读后写一定要按照顺序 先读 后写
r+b模式
//写
w模式:write:只写模式 不可读
如果文件不存在,利用w模式操作文件,那么它会先创建文件,然后写入内容.
如果文件存在,利用w模式操作文件,先清空原文件内容,在写入新内容
wb模式:
以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如:图片,音频,视频等。
w+模式 写读模式
f1 = open('D:python练习.txt',encoding = 'gbk',mode = 'w+')
f1.write('666666666666666')
f1.seek(0) #调整光标,将光标位置放在起始位置,否则读不出数据。移动到结尾:seek(0,2) seek的第二个参数表示的是从哪个位置进行偏移,默认是0,表示开头,1表示当前位置,2表示结尾
print(f1.read())
seek定义:是以字节调节光标的位置。
f1. seek(offset[, whence])

whence:0,1,2三个参数,0表示文件开头,1表示当前位置,2表示文件结尾

offset:偏移量,可正可负,正数表示向后移动offset位,负数表示向前移动offset位。
f1.close()
f1.tell(): 可以获取当前光标在什么位置
f1.readable()判断是否可读
f1.writable()判断是否可写
f1.flush()刷新文件内部缓冲区 也就是强制保存
f1.fileno()通过文件描述符找到这个文件
f1.truncate(n)按照字节对源文件进行截取,只留0......n字节的数据 只能从头开始
w+b模式
//追加

打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。

新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a模式 只追加模式,不可读
a:没有文件,创建文件写内容
a:如果有文件,最后面追加内容。
ab模式
a+模式 先追加后读
a+b模式
*****************打开文件的另一种方式********************
1,利用with上下文管理这种方式,他会自动关闭文件句柄
with open('t1',encoding='utf-8') as f1:
f1.read()
2,一个with 语句可以操作多个文件,产生多个文件句柄
with open('t1',encoding='utf-8') as f1, #加个‘,’号就行了 ‘’是转行符
open('Test', encoding='utf-8', mode = 'w') as f2:
f1.read()
f2.write('老男孩老男孩')
经验小记:
wtih open('D:python练习.txt',encoding = 'gbk',mode='r') as f1:
content = f1.read()
pass
with open('D:python练习.txt',encoding = 'gbk',mode='w') as f2:
f2.write('qwer')
#因为是对同一个文件进行读 写 在第一个with语句中 很有可能文件句柄f1未关闭情况下走到
#第二个with语句中对这个文件进行 重新打开这个文件 进行 写 这时候很容易出错,所以可以主动关闭
wtih open('D:python练习.txt',encoding = 'gbk',mode='r') as f1:
content = f1.read()
f1.close() # 主动关闭,避免出错
pass
************************************************************

文件的修改:

文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体实现步骤如下:

对文件的改,实际的步骤:
1,打开原文件old_file,将原内容读取到内存
2,创建一个新文件new_file
3,将原内容通过你的改写形成新内容,写入到新文件。
4,将原文件删除。
5,将新文件重命名成原文件。
方法一:
import os
with open('D:python练习.txt',encoding = 'gbk') as f1,
open('D:新文件.txt',encoding = 'gbk',mode='w') as f2:
old_content = f1.read()
new_content = old_content.replace('ABC','qwe')
f2.write(new_content)
os.remove('D:python练习.txt') #删除原文件
os.rename('D:新文件.txt','D:python练习.txt') #更改新文件名字
################有个缺陷 如果文件很大就会崩溃
方法二:
import os
with open('D:python练习.txt',encoding = 'gbk') as f1,
open('D:新文件.txt',encoding = 'gbk',mode='w') as f2:
for line in f1:
new_line = line.replace('ABC','qwe')
f2.write(new_line) #在for里面所以没有清空,一直在写,没有结束。
os.remove('D:python练习.txt') #删除原文件
os.rename('D:新文件.txt','D:python练习.txt') #更改新文件名字
*******************************************************

经验小知识:
对于添加的元素是有规律性的 每列同属性,那么可以将属性放在开头 这样在增加列 可以在问价开头增加属性。
goods_info = []
l1 = ['name','price','amount']

with open('D:python练习.txt',encoding = 'gbk') as f1:
for line in f1:
line = line.strip().split()
dic = {}
for i in range(len(line)):
dic[l1[i]]=line[i]
print()
goods_info.append(dic)
print(goods_info)

原文地址:https://www.cnblogs.com/xiao-xuan-feng/p/12153175.html