python-字符编码、字符串格式化、字符串方法、列表、元组、字典、集合等基础知识总结

目录:

一、字符编码

二、字符串格式化

三、进制转换

四、数据类型及其操作 1.int类、2.str类

五、格式转换

六、For循环

七、三元运算

八.列表

九、列表推导式

十、元组

十一、字典

十二、集合set

十三、文件操作

十四、变量指向和深浅拷贝

 

.字符编码:

计算机由美国人发明,最早的字符编码为ASCII,只规定了英文字母数字和一些特殊字符与数字的对应关系。最多只能用 8 位来表示(一个字节),即:2**8 = 256,所以,ASCII码最多只能表示 256 个符号

ascii用1个字节代表一个字符;

unicode常用2个字节代表一个字符,生僻字需要用4个字节;

UTF-8英文字母被编码成1个字节,汉字通常是3个字节有很生僻的字符才会被编码成4-6个字节。

字母x,用ascii表示是十进制的120,二进制0111 1000

汉字中已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101。

字母x,用unicode表示二进制0000 0000 0111 1000,所以unicode兼容ascii,也兼容万国,是世界的标准

这时候乱码问题消失了,所有的文档我们都使用但是新问题出现了,如果我们的文档通篇都是英文,你用unicode会比ascii耗费多一倍的空间,在存储和传输上十分的低效

本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:

字符

Ascll

Unicode

Utf-8

x

01000001

00000000 01000001

01000001

不能表示

01001110 00101101

11100100 10111000 10101101

从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。

ASCII:只能存英文和拉丁字符,一个字符占一个字节,8位

gb2312:只能存6700多个中文,1980年

gbk1.0:存2万多字符,1995年

gb18030:存27000中文,2000年

万国码:Unicode:utf-32  一个字符占4个字节

                 Utf-16  一个字符占2个字节,或两个以上。

                 Utf-8   一个英文用ASCII码来存,一个中文占3个字节

声明编码  -*- coding:utf-8 -*-

gbk默认不认识utf-8,utf-8是Unicode的一个子集

Unicode 默认向下兼容gbk等

python3内部默认是 unicode,文件默认编码是utf-8

阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII

ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符

ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符),后来为了将拉丁文也编码进了ASCII表,将最高位也占用了

阶段二:为了满足中文和英文,中国人定制了GBK

GBK:2Bytes代表一个中文字符,1Bytes表示一个英文字符

为了满足其他国家,各个国家纷纷定制了自己的编码

日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里

阶段三:各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。如何解决这个问题呢???

说白了乱码问题的本质就是不统一,如果我们能统一全世界,规定全世界只能使用一种文字符号,然后统一使用一种编码,那么乱码问题将不复存在,

很多地方或老的系统、应用软件仍会采用各种各样的编码,这是历史遗留问题。于是我们必须找出一种解决方案或者说编码方案,需要同时满足:

1、能够兼容万国字符

2、与全世界所有的字符编码都有映射关系,这样就可以转换成任意国家的字符编码

这就是unicode(定长), 统一用2Bytes代表一个字符, 虽然2**16-1=65535,但unicode却可以存放100w+个字符,因为unicode存放了与其他编码的映射关系,准确地说unicode并不是一种严格意义上的字符编码表

很明显对于通篇都是英文的文本来说,unicode的式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的)

阶段四:于是产生了UTF-8(可变长,全称Unicode Transformation Format),对英文字符只用1Bytes表示,对中文字符用3Bytes,对其他生僻字用更多的Bytes去存。

. Python 字符串格式化

Python 支持格式化字符串的输出 。尽管这样可能会用到非常复杂的表达式,但最基本的用法是将一个值插入到一个有字符串格式符 %s 的字符串中。

格式输出汇总:

 1 #第一种
 2 val = "我叫%s,今年%d岁,身高%d"%('zrh',20,175)
 3 print(val)   #运行结果:我叫zrh,今年20岁,身高175
 4 #第二种
 5 val = "我叫{0},今年{1}岁,身高{2},我弟弟身高也是{2}"
 6 val1 = val.format("zrh",20,175)
 7 print(val1) #运行结果:我叫zrh,今年20岁,身高175,我弟弟身高也是175
 8 #第三种
 9 v = input("your name:") #用户输入姓名
10 val = "我叫{name},今年{age}岁,身高{height}"
11 val1 = val.format(name=v,age="20",height="175") #name = v是用户输入的那个姓名
12 print(val1)
13 #第四种
14 val = "我叫{name},今年{age}岁"
15 dic1 = {"name":"zrh","age":20}
16 val1 = val.format(**dic1)
17 print(val1)
18 #第五种
19 name = "我叫{name},年龄{age}"
20 val = name.format_map({'name':'海角','age':18})   #只有一种写法,里面必须是字典
21 print(val)

如果在格式化输出中想要输出%号,就要用到%%格式

print("我是%s,我的进度已经完成80%%" %('zrh'))

输出结果:

我是zrh,我的进度已经完成80%

%06d表示数字用6位表示,数字不足6位的话用0代替

from math import *
a = log(e**2)
print('%.2f'%(a))  #输出结果:2.00

百分号的输出:

num = 0.1
print("数据比例为 %.2f%%"%(num*100))
#输出结果:数据比例为 10.00%

变量名关键字:

python在定义变量名时区分大小写

import keyword as kw
print(kw.kwlist)
#['False', 'None', 'True', 'and', 'as', 'assert', 'async', 
# 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 
# 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 
# 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 
# 'try', 'while', 'with', 'yield']

转移符号相关问题:

\t 表空格

\n表换行

如果字符串中需要输出\n、\t等,需要加两个\\

print("\\n")  #输出结果 \n

如果字符串中需要输出的“\”非常多的话,可以使用原始字符串模式打印,即在字符串前输入r

 

 

如果字符串超过一行,再给变量赋值时需要使用三引号

case = '''
超过一行的字符串
'''

运算问题:

% 取余

\\ 整除

取余的原理

print(10 % 3)   #输出结果 1
print(10 % -3)  # 输出结果 -2

整除的原理:结果向下取整

.进制转换

进制也就是进制位,我们常用的进制包括:二进制、八进制、十进制与十六进制,它们之间区别在于数运算时是逢几进一位。比如二进制是逢2进一位,十进制也就是我们常用的0-9是逢10进一位,16进制的10-15用A、B、C、D、E、F来表示。

1. 十进制转二进制

方法为:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。

2. 二进制转十进制

方法为:把二进制数按权展开、相加即得十进制数。

第一个的1*2的7次方,是因为数位就是8位,8-1=7,依此类推。

#十进制转二进制
print(bin(175))  #0b10101111

#十进制转八进制
print(oct(175))  #0o257

#十进制转16进制
print(hex(175))  #0xaf

. 数据类型

Python有五个标准的数据类型:

Numbers(数字) V = 1 int类

Boolean value(布尔值) V = True (bool类)

String(字符串) V = “Good” (str类)

List(列表) V = [“good”,”best”] (list类)

Tuple(元组) V = (“good”,”best”) (tuple类)

Dictionary(字典) V = {“name”:”zrh”,”age”:20} (dict类)

字符类型的相互转换

1.int类(记住一个)

bit_length()表示当前十进制数用二进制数表示时,最少使用的位数。

代码示例:

count = 16
v = count.bit_length()
print(v,"---",count)

输出结果:

5 --- 16

注意: 

count = "1"
count1 = "2"
print(count+count1)  #输出结果:12    字符串的加法是拼接的作用
count2 = 1
count3 = 2
print(count2+count3)  #输出结果:3   数字的加法是加法作用
#需求,输入一个数字,然后每个数字相加,列入输入152,结果就是1+5+2
count4 = "152"  #在数字和字符串中只有字符串才可以遍历,所以要把count4转为str类型
val = 0
for i in range(len(count4)):    
    val += int(count4[i])   #count4[i]是字符串,所以要转为数字才能相加
print(val) 

浮点数:

2.str类

对于字符串,执行内置命令后,原来的值不变。

2.1:upper()转换字符串中的小写字母为大写

代码示例:

name = "zrh"
v = name.upper()
print(v,"---",name)

输出结果:

ZRH --- zrh

2.2:lower()转换字符串中所有大写字符为小写

代码示例:

name = "ZrH"
v = name.lower()
print(v,"---",name)

输出结果:

zrh --- ZrH

2.3:capitalize()将字符串的第一个字符转换为大写

代码示例:

name = "zrh"
v = name.capitalize()
print(v,"---",name)

输出结果:

Zrh --- zrh

2.4:strip()去除首尾的内容 空格、换行符、制表符、指定内容

代码示例:

name = " zrh "
v = name.strip()
print(v+"---",name)

输出结果:

zrh---  zrh

name_1 = "\tzrh\t"
print(name_1)
print(name_1.strip())

输出结果:

(    zrh    )空格是\t的结果

(zrh)

name_1 = "zrh"
print(name_1)
print(name_1.strip("h"))

输出结果:

zrh

zr

2.5:lstrip()截掉字符串左边的空格或指定字符

2.6:rstrip()删除字符串字符串末尾的空格

2.7:replace(str1, str2 , max)将字符串中的 str1 替换成 str2,如果max指定,则替换不超过max次

代码示例:

content = "人生自古谁无死,早死晚死都得死"
v = content.replace("","*",2)
print(v,"---",content)

输出结果:

人生自古谁无*,早*晚死都得死 --- 人生自古谁无死,早死晚死都得死

2.8: len(string)返回字符串长度

代码示例:

content = "人生自古谁无死,早死晚死都得死"
v = len(content)
print(v)

输出结果:

15

2.9:[]根据索引取值

代码示例:

#索引值从0开始计算不是从1
content = "人生自古谁无死,早死晚死都得死"
v = content[0]       #取字符串的第一个字符
v1 = content[-1]     #-代表从后往前找,1代表第一个,所以-1代表正向的最后一个
v2 = content[0:5]    #从0开始取到索引值为4的对象,不包括索引值为5的对象,相当于数学中的左闭右开区间
v3 = content[8:]     #从索引值为8的对象开始取到最后一个
v4 = content[0:15:2]  #从0开始隔一个取一个,一直取到14,2表步长表示隔一个取一个,3就表示隔2个
print(v,v1,v2,v3,v4)

输出结果:

人 死 人生自古谁 早死晚死都得死 人自谁死早晚都死

2.10 :split(“str”,num)  ()里没有参数的话,默认是空格

以 str 为分隔符截取字符串,如果 num 有指定值,则仅截取 num+1 个子字符串

代码示例:

content = "人生自古谁无死,早死晚死都得死"
v = content.split("",2)
print(v)

输出结果:

['人生自古谁无', ',早', '晚死都得死']

2.11 :.isdecimal()判断当前字符串中是否全部都是数字

代码示例:

v = "a123"
c = v.isdecimal()
print(c)

输出结果:

False

补充:

python中isdigit()、isdecimal()和isnumeric的区别  

a = "good 1 night 2"
a.isdecimal()    #如果a中只有十进制字符,则返回True,否则为False
a.isdigit()      #如果a中的所有字符都是数字,并且在S中至少有一个字符,则返回True
a.isnumeric()    #如果a中只有数字字符,则返回True,否则为False

2.12 :join(seq) 以指定字符串作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串

seq里的元素必须是字符串,不能是数字,数字和字符串(前面的“_”)不能相加,

代码示例:

list1 = ['alex','zrh','sdv']
a = '_'.join(list1)             #这里的_就表示用_连接
b = "".join(list1)              #""里什么都没有表示直接连接
print(a)
print(b)

输出结果:

alex_zrh_sdv

alexzrhsdv

2.13:把字符串转换成字节encode()

name = "天下"
name.encode("utf-8")   #把字符串(Unicode)转换成字节(utf-8格式)
name.encode("gbk")     #把字符串(Unicode)转换成字节(gbk格式)

 2.14:count() 

count() 方法用于统计字符串里某个字符出现的次数。可选参数为在字符串搜索的开始与结束位置。

name = "ooxxooxxooxx"
print(name.count("o"))
#有两个参数,不写默认为print(name.count("o",0,len(name)))
#0表示条件统计起始索引值,len(name)表示终止索引值

2.15:expandtabs() 方法把字符串中的 ('\t')转为空格,('\t')默认的空格数是 8,\t 表示横向制表符  \n表示换行符

name = "ID\tname\tpasswd\n1\tzrh1\t123\n2\tzrh2\t123"
val = name.expandtabs(20)   #20表示连同\t前面的内容一共占20个字符的位置
print(val)

输出结果:

2.16其他不常用的方法汇总:

五.格式转换

1.数字转字符串 str(对象)

2.字符串转数字 int(对象)

对象必须是形为数字,才能转换

Int(string)就会报错

3.数字转布尔值 bool(对象)

bool(0)是False

其他不是0的数都是True

但是在其他方面true = 1 flase = 0

4.字符串转布尔值 bool(对象)

bool(“”)是False

其他任何字符串都是True

代码示例:

a = 9 or 2>3
print(a)

输出结果:9

代码示例:

a = 0 or 2>3
print(a)

输出结果:False

代码示例:

a = 0 or 6
print(a)

输出结果:6

代码示例:

a = 0 or 2<3
print(a)

输出结果:True

5.元组转列表

v = (1,2,3)
val = list(v)

6.列表转元组

v = [1,2,3]
val = tuple(v)

7.列表转字符串

v = ["1","2","3"]
result = "".join(v)
print(result)

六、For循环

Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串。

for循环的一般格式如下:

for 变量接收名 in 对象 :

代码示例:

list1 = ["one","two","three",4]
for i in list1:
  print(i)

输出结果:

one

two

three

4

For循环时加上序号enumerate:

list1 = ["手机","电脑","ipad"]
for i,v in enumerate(list1,1):     #表示遍历list1这个列表,序号从1开始。
  print(i,v)

输出结果:

1 手机

2 电脑

3 ipad

循环语句可以有 else 子句,它在穷尽列表(以for循环)或条件变为 false (以while循环)导致循环终止时被执行,但循环被break终止时不执行,简而言之就是break后不会执行下级的else(注意break的级别)

range()函数

如果你需要遍历数字序列,可以使用内置range()函数,它会生成数列

range(起始值,终止值,步长)这里是左闭右开区间,可以取到起始值,但是取不到终止值,只能取到终止值的前一个,步长就是遍历时的距离,默认是1

代码示例:

for i in range(5,1,-1):
  print(i)

输出结果:

5

4

3

2

range的组和用法:

可以结合range()和len()函数以遍历一个序列的索引:

list1 = ["手机","电脑","ipad"]
for i in range(len(list1)):      #len是从1开始,range没写参数是从0开始
  print(i,list1[i])

输出结果:

0 手机

1 电脑

2 ipad

print中的自动换行

print 会自动在行末加上回车, 如果不需回车,只需在 print 语句的结尾添加一个逗号 , 并设置分隔符参数 end,就可以改变它的行为。

 

七、三元运算

a = 1
b = 2
if a < b :
    c = b
else:
    c = a

这样写代码非常繁琐,所以在遇到if else非常简单的时候,可以用到三元运算

a = 1
b = 2
c = b if a < b else a

 ①---⑥表示写三元运算时候的流程

八.列表

列表是Python中最基本的数据结构。列表中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。

创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。

如下所示:

list = ["one","two",3,4,"five"]

列表可以进行 增、删、改、查。如果列表只有一个对象,在后面也要加上,

列表中的元素可以是 数字、字符串、布尔值、列表(列表的嵌套)

复制列表:

a = [1,2,3]
b = a[:]      #[:]是复制列表
print(a,b)     

1.切片:

list[1:]      #从1开始取到最后 
list[1:-1]    #从1开始取到倒数第二值
list[1:-1:1]   #从左到右一个一个去取,取到倒数第二值
list[1::2]     #左到右隔一个去取
list[3::-1]     #从3开始从右到左一个一个取,注意索引值不变

切片器详解:

str[a:b:c]

a表示切片开始的索引位置

b表示切片结束的索引位置

a,b参数都可正可负

a,b为正数的时候,左边第一个内容索引为0

a,b为负数的时候,右边第一个内容索引为1

参数c表示从左到右(c=1)或者从右到左(c=-1)

str = 'onetwothree'
#打印字符串倒数后两位的值
val = str[-1:-3:-1]
print(val)   #打印结果:ee

2.增  添加:

2.1:append()

append(“str”)将数据插到最后一个位置

代码示例:

list = ["one","two",3,4,"five"]
list.append("six")
print(list)

输出结果:

['one', 'two', 3, 4, 'five', 'six']

append()注意事项:

1 list1 = [11,22,33]
2 val = list1.append(44)
3 print(val)
4 #这里返回的是None,对于列表来说,执行方法之后改变的是原来的值,变量接收不到

2.2:insert()

根据索引值位置将数据插入到任意一个位置

代码示例:

list = ["one","two",3,4,"five"]
list.insert(2,"two2")     #想把新对象插在什么位置就输入相应的索引值
print(list)

输出结果:

['one', 'two', 'two2', 3, 4, 'five']

3.改  修改:

想要修改首先得用切片把相应的值取出来,在进行赋值即可。

代码示例:

list = ["one","two",3,4,"five"]
list[1] = 2   #将索引值为1的对象取出来,再重新赋值
print(list)

输出结果:

['one', 2, 3, 4, 'five']

需求:将list = ["one","two",3,4,"five"]这个列表里的two 和 4 修改成 2 和 four

代码示例:

list = ["one","two",3,4,"five"]
list[1:4:2] = [2,"four"]
print(list)

输出结果:

['one', 2, 3, 'four', 'five']

注意:在list[1:4:2] = [2,"four"]中,因为list[1:4:2]输出得是一个列表,所以等号右边也必须是个列表

4.删除:

4.1:remove

remove只能删除一个,并且()里填写的是对象内容

代码示例:

list = ["one","two",3,4,"five"]
list.remove("two")     #删除two
print(list)

输出结果:

['one', 3, 4, 'five']

4.2 :pop 

pop删除的时候()里是填写索引值,并且还可以将删除数据返回出来,如果括号里面不填索引值,即pop(),则默认删除最后一个值。

代码示例:

list = ["one","two",3,4,"five"]
a = list.pop(1)    #删除 two
print(list,a)

输出结果:

['one', 3, 4, 'five'] two

4.3 :del什么都可以删除

代码示例:

list = ["one","two",3,4,"five"]
del list[0]    #删除 one
print(list)

输出结果:

['two', 3, 4, 'five']

5.列表的其他操作

5.1 :count:计算某元素出现次数

代码示例:

list = ["one","two",3,4,"five"]
v = list.count("two")   #计算two出现的次数
print(v)

输出结果:1

5.2:extend:用于在列表末尾一次性追加另一个序列中的多个值,括号中必须是可迭代对象,可以理解为批量的append()

代码示例:

a = [1,2,3]
b = [4,5,6]
a.extend(b)     #把b加到a里面
print(a)
print(b)

输出结果:

[1, 2, 3, 4, 5, 6]

[4, 5, 6]

5.3:index根据内容找位置,输出得是第一个匹配内容的索引位置

代码示例:

list = ["one","two",3,4,"five"]
T = list.index("five")      #查找five的索引值
print(T)

输出结果:4

5.4 合集

1.reverse:用于反向列表中元素

2.sort:对原列表进行排序

reverse -- 排序规则,reverse = True 降序(由大到小), reverse = False 升序(由小到大)(默认)

3.in:查一个数据在不在列表内

4.type:身份判断:判断一个对象是不是列表

代码示例:

list0 = ["one","two",str(3),str(4),"five"]
list0.reverse()             #反向列表中元素
print(list0)
list0.sort(reverse=True)    #由大到小de对原列表进行排序
print(list0)
a = "six" in list0         #判单six在不在列表里
print(a)
b = type(list0) is list     #判断list0是不是列表
print(b)

输出结果:

['five', '4', '3', 'two', 'one']

['two', 'one', 'five', '4', '3']

False

True

6.列表练习题:

list = ["one","two",3,4,"five","天才"]

把list列表中的天才的 天 改成 蠢

代码示例:

list = ["one","two",3,4,"five","天才"]
v = list[5].replace("","")
list[5] = v
print(list)

输出结果:['one', 'two', 3, 4, 'five', '蠢才']

注意:字符串不能通过索引值修改,只能通过索引值取出来。(⬇)

7.补充:

需求:索引为奇数值,删除
注意:删除列表元素时,会影响列表长度,从而使得索引取值时,容易出现错误。

li = [11,22,33,44,66]
# 解决方案一:
li = [11, 22, 33, 44, 66] # 0
new_list = []
for i in range(0,len(li)):
    if i%2 == 0:
        new_list.append(li[i])
li = new_list
print(li)

# 解决方案二:
 li = [11, 22, 33, 44, 66] # 0
 for i in range(len(li)-1,-1,-1): # 4,0
    if i%2 == 1:
        del li[i]
print(li)

#解决方案三:切片+步长
li = [11, 22, 33, 44, 66] 
del li[0:4:2]
print(li)   

九、列表推导式

需求:将[1,3,5]中的每个元素平方

正常思路:

new_list = []
for i in [1,3,5]:
    new_list.append(i*i)
print(new_list)  #输出结果:[1, 9, 25]

列表推导式:以[ ]框住里面的内容

print([i*i for i in [1,3,5]])  #输出结果:[1, 9, 25]

列表推导式图示流程:

可以看出列表推导式的作用就是简化代码

列表推导式例题:

1.输出10以内能被三整除的数的平方

print([i*i for i in range(10) if i %3 == 0])  #[0, 9, 36, 81]

2.输出列表每一个包含‘o’元素的字符串

list_case = [['one','two','three'],['four','five','six']]

正常思路:

list_case = [['one','two','three'],['four','five','six']]
for i in list_case:
    for v in i:
        if v.count('o')>0:
            print(v)

列表推导式:

list_case = [['one','two','three'],['four','five','six']]
print([v for i in list_case for v in i if v.count('o')>0])

十、元组

Python 的元组与列表类似,不同之处在于元组的元素不能修改。

元组使用小括号,列表使用方括号。

元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。

1. 创建空元组

tup1 = ()

2. 元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用:

代码示例:

tup1 = (50)
print(type(tup1))     # 不加逗号,类型为整型
tup1 = (50,)
print(type(tup1))     # 加上逗号,类型为元组

输出结果:<class 'int'>、<class 'tuple'>

3. 元组可以使用下标索引来访问元组中的值

4. 可以对元组进行连接组合

5.元组可以计算长度len()

6.元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组

7.重点:

元组的儿子不能修改,但是孙子可以,元组的元素不能修改,但如果元组的元素不是元组类型的话,那么元组的元素的元素是可以修改的。

代码示例:

tuple1 = ("one","two","three",[1,2,"zrh"],(1,2,3),"four")
tuple1[3][1] = 3
print(tuple1)
tuple1[3].append("q")
print(tuple1)

输出结果:

('one', 'two', 'three', [1, 3, 'zrh'], (1, 2, 3), 'four')

('one', 'two', 'three', [1, 3, 'zrh', 'q'], (1, 2, 3), 'four')

十一、字典

字典是另一种可变容器模型,且可存储任意类型对象。

字典的每个键值(key=>value)对,用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中

键必须是唯一的,但值则不必。

值可以取任何数据类型,但键必须是不可变类型。

不可变类型:整型、字符串、元组

可变类型:字典、列表

格式:变量名 = {键:值,键:值}

代码示例:

dict1 = {
    "name":"zrh",
    "age":20,
    "height":75
}

1.:dict.get

1.1通过键取值

代码示例:

dict1 = {
    "name":"zrh",
    "age":20,
    "height":75
}
print(dict1.get("name"))

输出结果:zrh

1.2()参数,如果键不存在,就用后面的结果当作默认值。

代码示例:

dict1 = {
    "name":"zrh",
    "age":20,
    "height":75
}
print(dict1.get("key",999))

输出结果:999

2.:dict.keys() 、 dict.values() and dict.items()

经常和for循环一起使用

字典在for循环的时候尽量不要用两个变量去分别接收 键 和 值,这样会造成内存负荷过大,可以先遍历键,然后通过键去找值

代码示例:

dict1 = {
    "name":"zrh",
    "age":20,
    "height":75
}
a = dict1.keys()         #查看所有键
print(type(a))           #查看a的类型
print(a)
print(dict1.values())    #查看所有值
print(dict1.items())     #查看所有键值对

输出结果:

<class 'dict_keys'>

dict_keys(['name', 'age', 'height'])

dict_values(['zrh', 20, 75])

dict_items([('name', 'zrh'), ('age', 20), ('height', 75)])

for循环注意事项:

dict1 = {}
for key in dict1:
    pass
for key in dict1.items():
    pass
for key in dict1.keys():
    pass
for key in dict1.values():
    pass

注意dict1后面括号的有无

3.增加键值对

代码示例:

dict1 = {
    "name":"zrh",
    "age":20,
    "height":75
}
dict1["hobby"] = "eat"
print(dict1)

输出结果:{'name': 'zrh', 'age': 20, 'height': 75, 'hobby': 'eat'}

如果增加的键已经存在,那就是改的功能。

4.删除

代码示例:

dict1 = {
    "name":"zrh",
    "age":20,
    "height":75
}
del dict1["name"]     #删除指定键值对
print(dict1)
dict1.clear()
print(dict1)         #清空字典中所有键值对,但空字典还存在
dict2 = {
    "name":"zrh",
    "age":20,
    "height":75
}
a = dict2.pop("name")    #通过键去删除,并可以返回相应的值
print(a)
print(dict2)
b = dict2.popitem()
print(b)
print(dict2)            #随机删除一对键值对,并且返回相相应键值对

输出结果:

{'age': 20, 'height': 75}

{}

zrh

{'age': 20, 'height': 75}

('height', 75)

{'age': 20}

5.嵌套

字典里面可嵌套字典或者列表都可以,列表页都可以嵌套字典。

在修改时,遇到字典用键,遇到列表用索引值,然后查找出来之后赋值即可,其他操作一样,反正一句话:

遇到字典用键,遇到列表用索引值。

6.update()用于将括号中的键值对添加到目标对象中,如果括号中的键在目标对象中存在,则更新目标对象的值

1 dict1 = {
2     'k1':'v1',
3     'k2':'v2',
4     'k3':'v3'
5 }
6 dict1.update({'k4':'v4','k1':'v11'})
7 print(dict1)
8 #输出结果:{'k1': 'v11', 'k2': 'v2', 'k3': 'v3', 'k4': 'v4'}

7.fromkeys()创建字典

 1 #fromkeys使用的时候不是文件名.  是用dict.来调用
 2 val = dict.fromkeys(['k1','k2','k3'],666)   #将666作为值赋给K1 K2 K3三个键
 3 print(val)          #输出结果{'k1': 666, 'k2': 666, 'k3': 666}
 4 val['k1'] = 999     #给数字重新赋值,在内存中重新开辟一块内存用来储存999,然后k1指向999,原来的k2 k3值不变
 5 print(val)         #输出结果{'k1': 999, 'k2': 666, 'k3': 666}
 6 
 7 val = dict.fromkeys(['k1','k2','k3'],[])
 8 val['k1'].append(666)
 9 val['k2'].append(999)
10 #k1 k2 k3指向的是同一个值,即[],每次往里加内容的时候 k1  k2  k3 的值都会发生变化
11 print(val)   #输出结果{'k1': [666, 999], 'k2': [666, 999], 'k3': [666, 999]}
12 
13 val = dict.fromkeys(['k1','k2','k3'],[])
14 val['k1'].append(666) 
15 val['k1'] = [1,2,3]  #这里是重新赋值操作,在内存中重新开辟一块空间储存[1,2,3],k1指向他,k2 k3值不变
16 print(val)  #输出结果{'k1': [1, 2, 3], 'k2': [666], 'k3': [666]}

8.补充

# 题:dic = {'k1':"v1",'k2':'v2'}把key="k1",键值对删除
del dic['k1']
# 题:dic = {'u1':"v1",'k2':'v2','k3':'v3'}把key中存在k,键值对删除
dic = {'u1':"v1",'k2':'v2','k3':'v3'}
# 不要在循环当前字典的过程中,修改当前字典大小
错误方式:
for key in dic:
    if 'k' in key:
        del dic[key]
正确方式 :
dic_key_list = []
for key in dic:
    dic_key_list.append(key)
for row in dic_key_list:
    if 'k' in row:
        del dic[row]
print(dic)    

十二、集合set

集合(set)是一个无序的不重复元素序列。

可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。

1 list1 = [] #等价于list1 = list()
2 tuple1 = () #等价于tuple1 = tuple()
3 dict1 = {}  #等价于dict1 = dict()
4 #所以创建集合是 set()

集合里的元素必须是不可变的

set1 = {“1”,“zrh”,[1,2,3]}这样就会报错,因为列表是可变的

不可变类型:整型、字符串、元组

可变类型:字典、列表

集合也可以for循环,集合不可以通过索引来取值,因为集合无序。

创建格式:

1 parame1 = {"one","two","three"}    #创建方法1
2 a = set("apple")     #创建方法2
3 print(parame1,a)
4 #打印结果{'two', 'three', 'one'}集合无序的; 
5 #{'l', 'p', 'a', 'e'}因为是不能重复的,所以只有一个a

Set内置方法:

方法

描述

add()

为集合添加元素(无返回值)

clear()

移除集合中的所有元素(无返回值)

copy()

拷贝一个集合(无返回值)

difference()

返回多个集合的差集(返回一个新的集合)

difference_update()

方法用于移除两个集合中都存在的元素(无返回值)

discard()

删除集合中指定的元素(无返回值)删除元素不存在不会报错

intersection()

返回集合的交集(返回一个新的集合)

intersection_update()

更新指定集合为指定集合和参数集合的交集(无返回值)

isdisjoint()

判断两个集合是否无交集,如果没有返回 True,否则返回 False(返回布尔值 )

issubset()

判断指定集合是否为该方法参数集合的子集(返回布尔值 )

issuperset()

判断该方法的参数集合是否为指定集合的子集(返回布尔值 )

pop()

随机移除元素(返回移除的元素)

remove()

移除指定元素(返回移除的元素)删除的元素不存在会报错

symmetric_difference()

返回两个集合中不重复的元素集合(返回一个新的集合)

symmetric_difference_update()

移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中(无返回值)

union()

返回两个集合的并集(返回一个新的集合)

update()

给集合添加元素(无返回值)

 

Set内置方法部分应用举例:

#1.add() 添加  参数必须是字符串
name = {'one','two','three','four','five'}
a = name.add('six')  #括号内的元素只能填一个,并且要维护集合元素永不重复
print(a)       #输出结果:None 说明add不可返回值,直接修改的是集合
print(name)   #输出结果:{'four', 'five', 'three', 'six', 'one', 'two'}
#2.update() 添加更新  参数可以是列表,元组,字典,集合等
name = {'one','two','three','four','five'}
a = name.update(['six','seven'])
print(a)       #输出结果:None 说明update不可返回值,直接修改的是集合
print(name)   #输出结果:{'three', 'seven', 'four', 'six', 'one', 'two', 'five'}
#3. difference()  用于计算差集
#difference() 方法用于返回集合的差集,即返回的集合元素包含在第一个集合中,但不包含在第二个#集合(方法的参数)中。
name = {'one','two','three','four','five'}
name1 = {'five','six','seven'}
a = name.difference(name1)   #name中存在,name1中不存在,创建新变量,name name1值不变
print(a)       #输出结果:{'three', 'four', 'one', 'two'}
#4. difference_update() 方法用于移除两个集合中都存在的元素。
#difference_update() 方法与 difference() 方法的区别在于 difference() 方法返回一个移除相同元素的新集合,
而 difference_update() 方法是直接在原来的集合中移除元素,没有返回值。
name = {'one','two','three','four','five'}
name1 = {'five','six','seven'}
a = name.difference_update(name1)   #在name中删除name1中存在的值
print(a)       #输出结果:None 没有返回值
print(name)   #输出结果:{'four', 'two', 'three', 'one'}
快速去重:利用集合元素不重复的方法
name = ['one','two','five','three','four','five']
val = set(name)  #将列表转换为集合格式
print(val)   #{'four', 'two', 'five', 'one', 'three'}

set集合也可以进行> < 的比较:

#判断b是不是a集合的子集
a = {1,2,3,4,5}
b = {4,5}
print(a>b)
# 结果为True

a = {1,2,3,4,5}
b = {1,2,3,4,5}
print(a1!=b) !=不等于的意思
#结果为False,代表a,b两个集合相同

十三、文件操作

文件操作三要素

1. 路径:D:\\name.txt

2. 编码:utf-8或gbk等

3. 模式:

x

写模式,新建一个文件,如果该文件已存在则会报错。

b

二进制模式。即bytes

+

打开一个文件进行更新(可读可写)

r

以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。

rb

以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。

r+

打开一个文件用于读写。文件指针将会放在文件的开头。常用

rb+

以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。

w

打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。

wb

以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。

w+

打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。

wb+

以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。

a

打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

ab

以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

a+

打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。

ab+

以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

1.只读模式r:

obj = open('D:\\name.txt',encoding='utf-8',mode='r')  #\\中的第一个\表示转义符
#            文件路径        编码格式        模式
content = obj.read() #此时的content是str类型,str在内存上又是Unicode类型
# 所以mode = 'r' python内部会把utf-8数据转换成Unicode类型
obj.close()
obj = open('D:\\name.txt',mode='rb')
#          文件路径    模式
content = obj.read() #此时的content是bytes类型,打印出来是bytes的表现形式
obj.close()

总结:

1.文件在硬盘上存储一定是UTF-8或者GBK等编码的01

2.rb=原封不动的拿数据,数据此时是某种编码的01,为了显示方便,便会显示bytes的表现形式

3.r=内部会有转换,但是必须记住要加编码格式encoding = ‘utf-8’等

4.encoding是文件之前用什么编码保存,就用什么编码打开

5.一般情况下mode = ‘rb’,用bytes的很少,一般用于上传,下载文件时才用到

只写模式w:

写之前会清空里面的内容再写

1.open(文件路径,mode='wb')

count = open('name.txt',mode='wb')
count.write("dooble".encode('utf-8'))  
#wb模式下,往里存的必须是utf-8等编码格式,字符串默认是Unicode,所以要转换成utf-8
count.close()

2.open(文件路径,mode='w',encoding='utf-8')

count = open('name.txt',encoding='utf-8',mode='w')
count.write('123')        #会先清空,再写,只能写不能读
count.close()

3.writelines()  将列表的内容写入文件,参数是个列表

只追加模式a:

追加模式不清空原来文件的内容

1.open(文件路径,mode='ab')

count = open('name.txt',mode='a',encoding='utf-8')
count.write("name1")  
count.close()

2.open(文件路径,mode='a',encoding='utf-8')

count = open('name.txt',mode='ab')
count.write("name1".encode('utf-8'))  
#ab模式下,往里存的必须是utf-8等编码格式,字符串默认是Unicode,所以要转换成utf-8
count.close()

r+模式:

count = open('name.txt',mode='r+',encoding='utf-8') #r+可读可写 w+可写可读,写之前会清空原文件内容,读的是你写的内容
#此时指针在第一个位置,不跳指针继续写会从第一个位置覆盖
count.write("name1")  #这样就直接覆盖了
count.read() #读到最后,指针此时在最后了
count.write("name1")   #指针在最后,于是就添加到最后了
#要想在第二个位置覆盖,那需要调整指针
count.seek(0) #将指针调整到0位置
count.write("2")  #此时2就覆盖了原来在0位置的内容
count.close()  #关闭文件

r+模式注意事项:

file文件内容:

 注意事项一:

with open("file",'r+',encoding='utf-8') as file_1:  #打开文件时候不清空文件
file_1.readline()        #读第一行,指针现在在第一行末尾
file_1.write("good")     #在执行写操作的时候,是在文件末尾追加

输出结果:

注意事项二:

当不执行读操作的时候,再写的话默认从开始的位置覆盖

with open("file",'r+',encoding='utf-8') as file_1:  #打开文件时候不清空文件
    file_1.write("good")    #当不执行读操作的时候,再写的话默认从开始的位置覆盖

输出结果:

所以在以后的操作中,不要同时读写操作一个文件,因为会乱,所以不用“R+”,就单独的用 r、w、a

文件的功能:

read

obj = open('美女.txt',mode='r+',encoding='utf-8')
data = obj.read()  # 读取所有文件内容
data = obj.read(2) # 在r模式中读取的2是2个字符;在rb模式中读取的2是2个字节
obj.write('字节或字符串')

seek

obj = open('美女.txt',mode='r+',encoding='utf-8') #打开文件时注意该文件是不是用utf-8编码的
obj.seek(2)         # 参数2永远是字节,用来指定指针的位置 utf-8一个中文3个字节

 tell等

obj.tell()          # 读取当前指针的位置,读取到的是字节数
obj.writable()   #是否可写,r模式下就不可写,可以用变量接收返回值
obj.readable()   #是否可读,w模式下就不可读,可以用变量接收返回值

flush将内存中内容刷到硬盘

count = open('name.txt',mode='r+',encoding='utf-8')
while True:
    val = input(">>>")
    count.write(val)    #给文件里写内容
    count.flush()       #强行把内容刷到硬盘,不然文件在循环里永远关闭不了
count.close()

readline()从文本文件中读取一行内容作为结果返回,结果为字符串类型

file_name文件内容:

with open('file_name','r',encoding='utf-8') as file:
    val = file.readline()
    print(type(val))
    print(val)
    # 在读第二行的时候,第一行内容是 君不见黄河之水天上来\n,其中的\n也会被读出来,所以打印的时候中间会多一行间隙
    val = file.readline()
    print(val)

输出结果:

readline常用的一种方法:

with open('file_name','r',encoding='utf-8') as file:
    for line in file:
        print(line)  ##即使文件有80个G,for循环的垃圾回收体制会即时节省内存

readlines()将文本文件中的每行文本作为一个字符串存入列表中,返回该列表,对于大文件会占很多内存,不建议使用

truncate()

obj.truncate()  #截取文件内容,根据指针位置,只保留指针之前数据

注意:写文件的时候一定记着关闭文件,这里有一种自动关闭的方法:

with open("name.txt",mode="r+",encoding="utf-8") as count:   #as 后面是接收打开文件对象的变量名
    #在缩进里写代码内容
#等待运行完代码后会自动跳出缩进,就自动关闭了

总结:

with open("file",'r+',encoding='utf-8') as file_1: #打开文件时候不清空文件
   pass
import os
os.remove('file')   #删除file的文件
os.rename('file','file_new')  #将文件名file修改为file_new

文件内容的修改:

步骤:

1.先遍历文件

2.str.replace或者str.split

3.将修改后的所有文件重新写入一个新文件

4.删除原来文件

5.将新文件重命名为原来文件的名字

举例:

file文件的内容:

需求1:给每一项的第一个 | 前的字母加上  _good

import os   #导入os模块
file_2 = open("file_new",'w',encoding='utf-8')   #以写模式打开file_new文件(无此文件则会创建),打开之前会清空原文件内容
with open("file",'r',encoding='utf-8') as file_1:  #以读模式打开file文件
    for line in file_1:         
        list_1 = line.split("|")     
        list_1[0] = list_1[0]+"_good"
        content = '|'.join(list_1) 
        file_2.write(content)           #每遍历一个内容,修改后就写到file_new里面
file_2.close()
os.remove('file')     #删除原来的file文件
os.rename('file_new','file')  #将file_new文件重命名为file

输出结果:

需求2:给zcx后面加上 _good ,其他保持不变

import os   #导入os模块
file_2 = open("file_new",'w',encoding='utf-8')   #以写模式打开file_new文件(无此文件则会创建),打开之前会清空原文件内容
with open("file",'r',encoding='utf-8') as file_1:  #以读模式打开file文件
    for line in file_1:
        list_1 = line.split("|")
        if list_1[0] == 'zcx':    #判断是不是zcx
            list_1[0] = list_1[0]+"_good"
        content = '|'.join(list_1)
        file_2.write(content)           #每遍历一个内容,修改后就写到file_new里面
file_2.close()
os.remove('file')     #删除原来的file文件
os.rename('file_new','file')  #将file_new文件重命名为file

输出结果:

Json文件解析:

Json本质上是—种嵌套字典格式,但键所对应的值,往往更加复杂,不仅是数字,还可以是字符串,数组,列表等

import json
with open('F:\pycharm\data\case.json',mode='r',encoding='utf-8-sig') as file:
    file_case = file.read()
    print(type(file_case))   #<class 'str'>
    data = json.loads(file_case)  #将file_case文件解析成json格式,参数的对应的文件内容必须是字符串格式
    print(type(data))  #<class 'dict'>
    print(data)
with open('F:\pycharm\data\case_write.json',mode='w',encoding='utf-8') as filr:
    json.dump(data,filr,indent=0)  #将data数据写入到filr对应的json文件里,indent=0表示空格为0

十四、变量指向和深浅拷贝

1.变量指向:

name = "zrh"
name1 = name
print(name,name1)
name = "zrh1"
print(name,name1)
#输出结果
#zrh zrh
#zrh1 zrh

内部原理:

name1通过name指向zrh,此时name1的值就是zrh后面即使name改变为zrh1,name1的值也不会改变。

2.列表指向:

list1 = [1,2,3]
list2 = list1
list1.append(4)
print(list1,list2)
#输出结果:[1, 2, 3, 4] [1, 2, 3, 4]

内部原理:

list2通过list1指向【1,2,3】,此时list2的值就是【1,2,3】,append直接改变的是值,所以list1和list2都改变了。

3.深浅拷贝

浅拷贝:只拷贝第一层,其他都指向同一数据

深拷贝:不管里面有多少嵌套,都会拷贝下来

深浅拷贝只有存在嵌套时才会有异同

内存原理:

公式格式:

list1 = [1,[2,3],4]
#浅拷贝
list2 = list1.copy()
#深拷贝
import copy
list3 = copy.deepcopy(list1)

注意:

list3最后一层是python为了节省内存才直接指向list1的数据,所以list1改变数据,是从新开辟出一块新的内存让list1指向,list3不变。

list1 = [1,[2,3],4]
#深拷贝
import copy
list3 = copy.deepcopy(list1)
list1[0] = 0
print(list3[0])   
#输出结果: 1

 

posted @ 2019-09-30 00:49  CentKiller  阅读(1555)  评论(0编辑  收藏  举报