Python3 从零单排1_列表&字典&集合&字符串方法&深浅拷贝

  1.列表

  前面我们了解了str、int、float等数据类型,比如人名用str,name='大雷',那如果我们一个部门呢?还用字符串存数据么,names='大雷,云云,星星'这样存数据,在调用的时候岂不是很麻烦,比如我们想取到星星,还要用到字符串方法,会比较麻烦,或者你想每个人取一个字符串的变量名,这样也麻烦啊,有多少个人,岂不是就要顶一个多少个变量了?为了解决这些麻烦,就有了列表,顾名思义,就是一个表,里面存放一系列数据,python里的列表定义比其他语言要简单,中括弧[]括起来就是列表了,当然在python里列表也叫数组,大家不要因为名字不同而困惑,都一个概念,列表增删改查如下:

#列表
names=['小刚','小红','小明','小小','猛犸']    #列表命名,列表名=[元素1,元素2,元素3],元素用英文逗号隔开,元素如果是字符串需要加引号
        #0      #1      #2      #3      #4
#列表里的元素是有排序的,所以每个元素都有一个数字编号,计算机是从0开始的,所以['小刚','小红','小明','小小','猛犸']这些元素对应的索引依次为:01234,当然在python里除了索引这个叫法,还有下标、角标,都一个意思

#列表取值
print(names[0]) #列表名[元素索引],这个格式就取到索引对应的元素了,这里取到'小刚',列表只有这一种取值方式
print(names[-1]) #负数表示从后往前取元素,这里取到了猛犸

#新增元素
names.append('云云')  #列表名.append(元素),这个方法是在列表最后面加一个元素,这里在列表最后加上'云云'
names.insert(2,'李白')  #列表名.insert(索引值,元素),这个方法是在指定索引位置插入元素,之前该位置及后面的额元素向后移一位,这里是在列表的第三个位置插入'李白'

#修改元素
names[0]='大刚'   #列表名[元素索引]=新元素,这样就修改元素了

#删除元素
names.pop() #默认删除最后一个元素
names.pop(2) #删除指定下标的元素
names.remove('小红')  #和pop不同,删除列表中指定的元素
del names[2]    #删除指定下标的元素
names.clear()   #清空列表

#多维数组
names1=['小刚','小红',['宙斯','火女'],'小明','小小','猛犸']    #数组里再来一个数组就是二维数组了
names2=['小刚','小红',['宙斯',['女王','拉比克'],'火女'],'小明','小小','猛犸']    #组二维数组里再来一个数组就是三维数组了,依次类推
print(names2[2][1][1])    #数组里面的数组就当元素来取,取出来之后,又按数组取值方式取下去就好了,这里取到了'拉比克'

#enumerate  循环枚举可迭代对象的索引与值
names=['小刚','小红','小明','小小','猛犸']
for index,value in enumerate(names):
    print(index,value)
# 0 小刚
# 1 小红
# 2 小明
# 3 小小
# 4 猛犸 

  列表内置方法:

 1 #内置方法:
 2 names=['小刚','小红','小明','小小','猛犸']
 3 names2=['宙斯','火女']
 4 names.extend(names2)    #合并两个list。将names2合并到names里面
 5 names+names2    #合并两个list。但和上面不一样,这里只是把两个列表连接起来,原来的列表不会变化,类似字符串相加
 6 new_name=names+names2   #用+的时候,需要用一个新列表来接收
 7 print(names.count('小小'))    #统计元素出现的次数
 8 print(names.index('小小'))    #查询到元素的索引
 9 names.reverse() #反转数组
10 names.sort()    #数组排序,升序
11 names.sort(reverse=True)    #数组排序,降序
12 print(names)
13 for index,value in enumerate(names):
14     print(index,value)
15 # 0 猛犸
16 # 1 火女
17 # 2 小红
18 # 3 小明
19 # 4 小小
20 # 5 小刚
21 # 6 宙斯

 

  列表切片,顾名思义,就是把列表切成我们想要的片段。上面了解到,列表是有下标、索引的,那么切片就是根据这个下标来进行切片的,比如我想去第一个元素到第三个元素,那么这样写:names[0:3],这样就取到前面三个元素了,但是你会发现,3的下标是第四个元素,为啥切片要切到3呢,因为python切片里,顾头不顾尾,意思就是从开始下标取到结束下标的前一位元素。另外如果是从0下标开始取值,那么可以省略不写,直接写[:3]即可;如果是取值到最后,那么可以省略不写最后的索引,直接写[3:]即可,显然[:]这样就是取所有的了。还有一个步长的概念,就是每走几步取一个元素,比如列表num=[1,2,3,4,5,6,7,8,9],num[0:10:2],这里就是每两个元素取一个,取的结果是:[1,3,5,7,9]。代码如下:

1 #列表切片
2 nums=[1,2,3,4,5,6,7,8,9]
3 print(nums[1:3])  #取第二个元素到第三个元素,也就是2,3
4 print(nums[3:])  #取所有的元素,一直取到最后,后面的下标可以省略不写
5 print(nums[:6])  #取所有的元素,从头开始取,前面的下标可以不写
6 print(nums[0:10:2])  #步长2,每两个元素取一个,这里取到1,3,5,7,9
7 print(nums[::1])  #取所有的元素,1就是每个元素都取
8 print(nums[::-1])  #步长为负数的情况下是从后往前取
9 print(nums[7:1:-2])  #步长为负数时,这里的下标必须是前面的下标大于后面的下标,因为他是从后往前取的

 

  2.元祖

  元祖,跟列表的定义是一样的,只是元祖是用小括弧(),列表用的是中括弧[],在命名上就这一点区别,那为什么有了列表,还来一个元祖,列表就够用了啊,反正都差不多,这里是因为元祖比列表更特殊一些,元祖命名后就不能增、删、改,就已经写死了,不能动他,你只能从里面取元素,只有读取的权限。有什么用呢?像我们在开发的时候,有一些基础数据,比如数据库连接信息,这些事定死的,你改了就连接不上了,所以这里用到元祖,避免后面调试啥的误操作,增删改了数据库连接信息,导致连接失败。元祖只有三个方法(其他方法都不适用):

#元祖
num=(1,2,3,4,5,6,6)
print(num[0])   #通过下标取值
print(num.count(6)) #统计元素出现的次数
print(num.index(6)) #查询到元素的索引

  既然说到了元祖,这里了解下可变变量和不可变变量,可变变量就是命名之后,还可以对他的内容进行增、删、改等操作,不可变变量就是,命名之后就不可以增、删、改他的内容了,像这里的元祖就是不可变变量,一旦命名就不可以对他的内容进行增、删、改等操作,只有读取的操作权限,所以元祖只有上面的三个方法,列表里的增删改都不适用于元祖,用的话会报错。类似于元祖这样的不可变变量还有字符串,字符串的内容是不可以增、删、改的,只可以读取。

   

  3.字典

  字典的概念大家再熟悉不过了,上小学就用到字典了,每天书包里都揣一字典,遇到不懂的就查一下不懂的这个关键字,然后后面跟很多解释,举例啥的。就像这个字典的需求,用列表可以实现吗?可以,但是很麻烦,比如这样存:

words=['菜鸟','奋斗','努力']  #中文
comments=['newbie','fight','effot'] #翻译

  如上述代码,但刚遇到这样的需求时,我们首先要找到中文words里的的下标,然后根据下标再去comments里找对应的英文,这样是可以满足字典的需求,但是词典那么多,这样找效率特别低,因为list在找元素是从前面一直找到后面,当有几万个词的时候,计算机要找很久才找的到,而且,这样存起来也不直观,看小学时候字典里那种存的多直观,前面是词,后面跟解释,所以python仿照字典弄了一个字典的样式,然后你在找词的时候,他直接找这个词,不会从前往后一个个的找,直接就找到了,他是无需的,很大程度上提高了效率。

  字典的特性:

  1.字典是无序的,因为它没有下标,用key来当索引,所以是无序的;

  2.字典的key必须是唯一的,因为它是通过key来进行索引的,所以key不能重复,所以字典里不会产生重复数据。

  字典命名也很直观,字典名={key1:value1,key2:value2},用大括号{},里面的格式是key:value,然后用逗号隔开各个元素,这样就直接定义好了一个字典并且赋值,代码如下:

 1 #字典
 2 informations={'星星':['江西',18,'',180],'大雷':['合肥',16,'',190]} #定义字典
 3 #
 4 #新增
 5 informations['人马']=['近卫',128,'未知',156]  #新增,直接指定key=value就新增了
 6 informations.setdefault('宙斯',['天灾',1280,'未知',152])  #这里的新增,如果这个key存在的话,就不修改他,不存在的话,就添加
 7 
 8 #修改
 9 informations['星星']=['湖南',22,'未知',150]  #修改,直接指定key=value就修改了,就是说如果字典存在这个key,就修改value,不存在就新增,因为字典是不能重复key的
10 informations.update(大雷=['天灾',1280,'未知',152])    #update也可以修改,但是注意,这里的key如果是字符串的话不需要加引号
11 
12 #删除
13 del informations['星星']  #删除,和list一样,list是删除指定下标的元素,这里是删除指定key的value
14 informations.pop('人马')  #删除,和list一样,list是删除指定下标的元素,这里是删除指定key的value
15 informations.popitem()  #随机删除一个值
16 
17 #查询,直接取和通过get取的区别是,当key不存在时,get方法取值不会报错,返回None;而直接取会报错,就这一个区别
18 print(informations['人马'])   #通过key取value
19 print(informations.get('人马'))   #用字典的get方法通过key取value
20 
21 #字典内置方法
22 print(informations.keys())    #获取字典的所有key
23 print(informations.values())    #获取字典的所有value
24 print(list(informations.keys()))    #强制类型转换为列表
25 print(list(informations.values()))    #强制类型转换为列表
26 print(informations.items()) #将字典转换成一个列表,一般不这样用,字典本来就快于list,还转换成list,没必要
27 additional={1:'a','大雷': ['火星', 16, '', 190]}
28 informations.update(additional) #update方式是更新字典,没有的key直接新增,有可以key的话,更新value
29 print(informations)

  可能会好奇为啥字典就比列表查询要快?可以肯定的是快太多,这里先了解一个数据类型,hash,一个函数,可以把所有不可变的对象压缩成一个特定长度的数字,好比把气体液化,缩小存储空间。基本每一个不同的对象hash后都能得到一个唯一的数字,但也存在特殊情况,可能不唯一。但是已经够我们用了,因为那种情况一般不会发生,那么hash有什么用呢?

  字典里的key就采用了hash函数来存储数据,key的定义是一个不可变对象(数字、字符串、元祖),在存储的时候(key-value),对key进行hash得到一个数字存起来,就变成了key-hash数字-value。

  我们已经学了列表,列表在查询一个值的时候,是循环列表所有元素,那么这个查询速度是很低的,复杂度是N,后面会讲到,好比你要去图书馆找一本书,那么图书馆那几十万本一本本找去,如果索引靠前还好,如果索引在最后,那么需要找几十万次才能找到。字典不一样,字典存的时候是这样的关系:key-hash数字-value,那么当你要找某个key的value时,是先把key进行hash,得到一个数字,然后根据这个数字去找value,那为什么通过数字去找value就变得很快了呢?因为字典hash过后的key可以进行排序,在一个有序的数字集合里找一个数字,可以用二分查找,算法的时候会讲,二分查找比for循环查找快的是指数级别。这样就能很快找到value了。

  字典嵌套,这个也很常用,就拿上述例子来说,首先是人名,然后是这个人的一些描述,描述内容少还好,但是,内容多的话呢,比如有身高、体重、爱好等等,太多了,用list存是不是又存在之前的问题,效率低,而且不方便取,每次取的时候还要要确定我要取得这个属性的下标然后才取得到。这里就引进了字典嵌套,用法也比较简单,如下:

informations={
    '星星':{
        '地址':'江西',
        'age':18,
        'sex':'',
        'heights':180
    },
    '大雷':{
        '地址':'合肥',
        'age':22,
        'sex':'未知',
        'heights':190}
}

  这样就直观很多了,不管你有多少属性,这样加下去就行了,取值方法参考字典的取值和多维数组的取值,这里不赘述了。

   

  4.集合

  集合也是数据类型,,一个类似列表东西,它的特点是无序的,不重复的,也就是说集合中是没有重复的数据,作用如下:

  1、它可以把一个列表中重复的数据去掉,而不需要你再写判断
  2、可以做关系比较,比如数学里的交集、并集等

  集合的操作和列表差不多:

lis=[1,2,3,4,4,5,5,6,7,8,9]
myset=set(lis)  #这就定义了一个集合
print(myset)    #去掉了重复数据,4,5,这里只显示一次
myset.add(888)#添加元素
myset.update([777,666,666]) #添加值
myset.remove(777)#删除元素,如果元素不存在会报错
myset.pop()#删除一个随机的元素,并返回删除的元素
myset.discard('dddd')#如果删除的元素存在,删除,不存在不做处理

  集合操作方法:

set1 = {1, 2, 3, 4, 5, 6, 7,8,9}
set2 = {1, 2, 3, 4, 6}
set3 = {1, 2}
print(set1.intersection(set2))  # 取交集,也就是取set1和set2中都有的
print(set1 & set2)# 取交集
print(set1.union(set2))  # 取并集,也就是把set1和set2合并了,然后去除重复的
print(set1 | set2)# 取并集
print(set1.difference(set2))  #取差集 在list中存在,在set2中没有的
print(set1 - set2)
print(set3.issubset(set1))#判断set3是不是set1的子集
print(set3<set1)
print(set1.issuperset(set3))#判断set1是不是set3的父集
print(set1>set3)
print(set1.isdisjoint(set3))#判断set1和set3是否有交集
print(set1.symmetric_difference(set2))#对称差集,输出两个列表中都没有的值,也就是把两个集合中相同的去掉
print(set1 ^ set2)

 

  5.字符串方法

  这里没什么技巧,记住这些方法就可以了,以后要用到,常用的有下面几种方法(一定要记住有这些方法,具体怎么用可以再查):

 1 #常用的字符串方法:
 2 file_name='D:\1自动化\day2\day2笔记.txt'
 3 name='名字:{name},年龄:{age}'
 4 print(file_name.startswith('D'))  # 判断是否以x结尾
 5 print(file_name.endswith('.txt'))  # 判断是否以x结尾
 6 name.format(name='niuniu', age=18)  # 这个是格式字符串
 7 print('122'.isdigit())  # 是否是数字
 8 print(''.join(['hehe', 'haha', 'ee']))  # 拼接字符串
 9 # 1、把list转成字符串
10 # 2、把list里面每个元素连起来
11 print('adbefF'.lower())  # 变成小写
12 print('adbefF'.upper())  # 变成大写
13 print('\nmysql \n'.strip())  #清除字符串前后空格
14 print('mysql is db.'.replace('mysql', 'oracle'))    #替换,将字符串里所有的mysql替换成oracle
15 print('1+2+3+4'.split('+'))  # 切割字符串,返回一个list
16 print('1+2+3\n1+2+3+4'.splitlines())  # 按照换行符分割,返回一个list

  其他不常用字符串方法:

 1 print(name.capitalize())#首字母大写
 2 print(name.center(50,'\t'))#把字符长度加到50个,如果元字符长度大于50,则字符不变,若大于50,则字符不做改变
 3 print(name.find('n'))#查找字符的索引,当查不到的时候会返回-1,
 4 print(name.index('w'))#查找字符的索引,当查不到的时候会报错
 5 print('a'.isalnum())#判断是否只包含数字或字母
 6 print('sdSD'.isalpha())#判断是否英文字母
 7 print('ads'.isidentifier())#判断是一个合法变量名
 8 print('aaa'.islower())#是否都是小写字母
 9 print('AAA'.isupper())#是否都是大写字母
10 print('\n   mysql   \n'.lstrip())#默认去掉左边的空格和换行
11 print('\n   mysql   \n'.rstrip())#默认去掉右边的空格和换行
12 print('\n   my\nsql   \n'.strip())#默认去掉左右两边的空格和换行,中间的空行去不掉
13 print('asdfdsfsfa'.strip('a'))#去掉首尾两端的字符'a'
14 p=str.maketrans('123','abc')#前面的字符串和后面的字符串做映射
15 print('123'.translate(p))#输出按照上面maketrans做映射后的字符串
16 print('asd gd gfd'.replace(' ','',1))#替换字符串,替换一次,不写数字表示全部替换
17 print('mysql is is db'.find('is'))#返回最左边字符的下标
18 print('mysql is is db'.rfind('is'))#返回最右边字符的下标
19 print('AAAaaa'.swapcase())#字母大小写反转

 

  6.深浅拷贝&三元运算&进度条&format 格式化传字典

# -*- coding:utf-8 -*-
# __author__="X1gang"
# Date:2018/11/19


#进度条
import time
for i in range(10):
    time.sleep(1)
    print('*',end='',flush=True)
# end默认参数是‘\n’,所以没有传值的话是默认换行的;
# flush在这里的意义是循环一次打印一次,默认参数是'False',如果指定为True,这里会10秒后一起打印10个*
# 现在上述代码打印结果为每秒钟打印一个*

# 赋值
a=b=c='haha'
print(id(a),id(b),id(c))    #字符串,内存地址都一样
c='xixi'
print(id(a),id(b),id(c))    #c内存地址不一样了
e=f=g=['haha',123]
print(id(e),id(f),id(g))    #列表,内存地址都一样
g.append('xixi')
print(id(e),id(f),id(g))    #内存地址还是都一样,也就是赋值的列表,一个列表变了,其他的表都一起变化,因为内存地址是一样的
# 浅拷贝(字符串没有copy方法)
lis=[1,2,3,[4,5,6]]
clis=lis.copy()    
print(id(lis),id(clis))    #内存地址不一样,完全复制了一份新的内存地址来存clis
print(id(lis[-1]),id(clis[-1]))    #嵌套列表内存地址一样,也就是两个列表的嵌套列表其中一个修改内容,另一个也会跟着一起变化
# 深拷贝(字符串也有深拷贝) 不管列表/字符串有多大,所有内容都完整的复制一份,生成新的内存地址,互不影响,一般不建议这样做,因为会占更懂的空间
import copy
dclis=copy.deepcopy(lis)
print(id(lis),id(clis),id(dclis))    #内存地址不一样,完全复制了一份新的内存地址来存clis
print(id(lis[-1]),id(clis[-1]),id(dclis[-1]))    #嵌套列表内存地址也不一样了,也就是两个列表的嵌套列表其中一个修改内容,另一个不会跟着一起变化

#三元运算
a=8
b=2
c=b if b>a else a   #这就是三元运算
print(c)

#format 传字典
print('{name},{age}'.format(age=18,name='xg'))
dic={'age':18,'name':'xg'}
print('{name},{age}'.format_map(dic))   #format_map这个方法后面传一字典即可
#上述输出的结果一样

 

posted @ 2017-12-14 12:28  毛斯钢  阅读(617)  评论(0编辑  收藏  举报