Bootstrap

Python序列结构

Python序列结构

一、概述

分类:

  • 有序序列
    • 可变序列
      • 列表
    • 不可变序列
      • 元组
      • 字符串
  • 无序列表
    • 可变序列
      • 字典
      • 集合
    • 不可变序列

可见,其实常用序列就是分三类,有序可变序列,有序不可变序列,无序可变序列

有序序列:可以通过索引去访问,支持使用切片

可变序列:可以修改其中的值,可以增加新元素或者减少已有的元素

生成器对象和range、map、enumerate、filter、zip等对象也部分支持类似于序列的操作

二、列表-有序可变序列

标准格式:

[元素1, 元素2,元素3,...... ]

特点:

  1. 同一个列表中元素的数据类型可以各不相同(同时包含多种数据类型的元素)
  2. 没有任何元素表示空列表

使用:

1)列表的创建与删除
赋值创建

使用 “ = ”将列表常量赋值给变量即可创建列表对象

a_list = ['a' , 'b', 'c']
a_list = []                     #创建空列表
转换其他对象进行创建

使用list() 函数把元组、range对象、字符串、字典、集合或者 其他可迭代对象转换成列表

a = list((3,5,7,9,11))   #将元组转换为列表
print(a)
a = list(range(1,10,2))  #将range对象转换为列表
print(a)
a = list('hello world')  #将字符串转换为列表
print(a)
a = list({3,7,5})            #将集合转换为列表,集合中的元素是无序的
print(a)
a = list({'a':3, 'b':9, 'c':11})  #将字典的键转换为列表
print(a)
a = list({'a':3, 'b':9, 'c':11}.items())   #将字典的元素转换为列表
print(a)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jRb0v6jL-1607835631220)(C:%5CUsers%5C%E7%99%BD%E6%98%BC%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20201124113512566.png)]

关于字典.items 方法解释:

把字典中每对 key 和 value 组成一个元组,并把这些元组放在列表中返回。

a = {'a':3, 'b':9, 'c':11}.items()
print(type(a))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4R0pBexB-1607835631228)(C:%5CUsers%5C%E7%99%BD%E6%98%BC%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20201124115452072.png)]

当一个列表不再使用时,可以使用del函数将其删除,删除之后列表无法再访问就会报错

x = [1,2,3]
del x              #删除列表对象
print(x[1])     #通过索引进行访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-deDwYZ20-1607835631230)(C:%5CUsers%5C%E7%99%BD%E6%98%BC%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20201124141447633.png)]

2)列表元素的访问

使用整数作为下标来随机访问其中任意位置上的元素,0作为第一个元素,-1代表最后一个元素,依次类推

x = list("Hello world")
print(x[1])
print(x[-1])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cFaxcRqH-1607835631231)(C:%5CUsers%5C%E7%99%BD%E6%98%BC%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20201124142238985.png)]

3)列表的常用方法
  1. 操作列表元素的方法

    1. append()方法

      • 向列表尾部追加一个元素

      • x = [1,2,3]
        x.append(0)
        print(x)
        
      • 单参数方法

    2. insert()方法

      • 向列表中的指定位置添加一个元素,其他元素顺移

      • x = [1,2,3]
        x.insert(0,1)
        print(x)
        
      • 双参数方法,参数一为指定位置索引,参数二位增加的元素

    3. extend()方法

      • 将另一个列表中的所有元素追加到当前列表的尾部

      • x = [1,2,3]
        x.extend([5,6,7])
        print(x)
        
      • 单参数方法,参数类型为列表

  2. 删除列表元素的方法

    1. pop()

      • 用于删除并返回指定位置上的元素,默认无参数则删除最好一个

      • x = [1,2,3]
        x.pop(0)
        print(x)
        
      • 单参数方法,参数类型为空或者索引值,也就是整形,满足索引值为负数的条件

    2. remove()

      • 用于删除列表中的第一个值与指定值相等的元素

      • x = [1,2,3]
        x.remove(2)
        print(x)
        
      • 单参数方法,参数为列表中的元素,特点是删除值相等的第一个

    3. del “命令”

      • 用于删除列表中指定位置的元素

      • x = [1,2,3]
        del x[2]
        print(x)
        
      • 命令而非方法着重注意

  3. 其他方法

    1. count()

      • 返回列表中指定元素出现的次数

      • x = [1,2,3,4,5,6,6,6,6]
        print(x.count(6))
        
      • 单参数方法,对列表中元素进行计数,进行值的比较,列表中不存在这个元素则抛出异常

    2. index()

      • 返回指定元素在列表中首次出现位置的索引

      • x = [1,2,3,4,5,6,6,6,6]
        print(x.index(1))
        
      • 单参数方法,参数值为元素值,获取第一次出现参数的索引

    3. sort()

      • 按照指定的规则对列表中的元素进行排序

      • import random
        x = list(range(11))   #取0~11的数作为列表的元素
        random.shuffle(x)     #打乱列表顺序
        print(x)
        x.sort(key=lambda  item:len(str(item)),reverse=True)
                                #安装换成字符串以后的长度降序排序
        print(x)
        
      • 用于列表排序,可只当排序规则

    4. reverse()

      • 将所有的元素进行翻转,第一个和倒数第一个交换位置,第二个和倒数第二个交换位置,依次类推

      • x = [10,2,3,4,5,6]
        x.reverse()
        print(x)
        
      • reverse属于对象成员方法,没有返回值

4)列表对象支持的运算符
  • 加法运算符+可以连接两个列表,返回一个新的列表

    • x = [1,2,3]
      x = x + [5,6]
      print(x)
      
  • 乘法运算符*用于列表和整数相乘,表示序列重复,返回新列表

    • x = [1,2,3]
      x = x * 3
      print(x)
      
  • 成员运算符in用于测试列表中是否包含某个元素

    • x = [1,2,3]
      print(3 in x)
      
    • 返回布尔类型

  • 关系运算符可以用于比较两个列表的大小

    • x = [1,2,4]
      y = [1,2,3,5]
      print(x > y)
      
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yU7W31d5-1607835631233)(C:%5CUsers%5C%E7%99%BD%E6%98%BC%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20201124154239224.png)]

    • 比较根据,逐个比较对应位置上的元素,直到某个元素能比较出大小,则作为整体比较的结果

5)内置函数对列表的操作
import random
x = list(range(11))  #生成【0,11)的列表,step默认是1
random.shuffle(x)    #将列表打乱
print(all(x))        #测试是否所有的列表元素都等价于True
print(any(x))        #测试是否存在等价于True的元素
print(max(x))               #返回最大值
print(max(x,key=str))       #根据指定规则返回最大值(这里的规则是字符串)
print(min(x))               #返回最小值
print(sum(x))               #求所有元素之和
print(len(x))               #返回列表元素个数
print(list(zip(x,[1]*11)))        #多个列表元素重新组合
print(zip(range(1,4)))      #zip也可用于一个序列或者迭代对象
list(zip(['a','b','c'],[1,2]))  #如果两个列表不等长,以短的为标准
list(enumerate(x))          #把enumerate对象转换成列表
                            #也可以转换成元组、集合等

关于zip()内置函数:

作用:将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,返回这些元组组成的列表。

如果各个迭代器的元素不一致,则返回列表长度与最短的对象相同,利用*号操作符,可以将元组解压为列表。

需要注意的是,zip返回的是一个对象

print(zip(x,[1]*11))        #多个列表元素重新组合
print(type(zip(x,[1]*11)))

zip函数

返回的是一个zip类型的对象,如果需要展示列表则需要手动的调用list()内置函数进行转换

print(list(zip(x,[1]*11)))

zip

内置函数对列表的操作

三、元组-有序不可变

在Python中定义了另一种有序列表交作元组:tuple。tuple和list非常相似,但是tuple一旦初始化就不能被修改

tuple的不可变性

示例:

classmate = ('Susa','Max','lily')
classmate[1] = 'hahah'
print(classmate[1])

分析:这里的代码的含义是将元组inde为1的元素的值修改为‘hahah’,但是由于元组的不可变性(一旦初始化了就不能被修改)

结果:

这里就会报’tuple’ obejct does not support item assignment

也就是tuple类型不支持被修改

tuple不可变就意味着代码更加的安全,如果可能,能用tuple代替list就尽量用tuple

当定义一个tuple的时候,tuple元素就必须被确定下来

因为它的不变性,相应的它也不存在那些增删改的方法

tuple的陷阱:

在定义只有一个元素的tuple,如果这样去定义:

t = (1)

那么这里定义的并不是tuple,而是1这个数,这是因为括号()既可以表示tuple,又可以表示数学公示中的小括号,这里这样就产生了起义。

所有在定义只有一个元素的元组的时候应该:

t = (1,)

添加一个逗号来消除歧义

tuple的可变性:

tuple中存储的是对象的地址,而对于基本数据类型的对象来说,数值是不可以更改的,但是如果是存储的列表或者其他对象,数值具有可变性

示例:

t = ('a','b',['A','B'])
t[2][0] = 'X'
t[2][1] = 'Y'

分析:在元组t中存储了字符串和列表,列表中存储了字符串,对于元组t来说是存储了对象的地址,但是对于列表中的元素地址并没有存储,所以可以修改列表中元素的值,这样的使用效果属于元组的可变性

换句话说,tuple的元素确实变了,但是变的不是tuple的元素,是list的元素,所以tuple所谓的不变是说,tuple的每个元素,指向永远不变,不难指向其他的对象,指向list 的地址也没变,变的是list本身

tuple的访问:

通过下标进行访问,可以二维访问

比如说

t = 'a','b',['a','b'];
print(t[2][1])

四、字典-无序可变性

dict全程dictionary,在其他语言中成为map,使用键值对进行存储,有很快的查找速度

构造方式和访问方式:

dictionary = {'lala':95,"jaja":85,"sese":66}
print(dictionary['lala'])

判断key 是否在 dict中的方法:

通过使用in关键字:

dictionary = {'lala':95,"jaja":85,"sese":66}
print('lala' in dictionary)

通过使用get方法:

如果key不存在,则会返回None,或者是自己指定的报错值,也就是get的第二个参数

dictionary = {'lala':95,"jaja":85,"sese":66}
a = dictionary.get('lalaa')
print(a)
a = dictionary.get('lalaa',-1)
print(a)

删除一个key:

通过调用pop(key) 方法,对应的value也会从dict中删除

dictionary = {'lala':95,"jaja":85,"sese":66}
dictionary.pop("lala")

优劣:

和list相比,dict有以下几个特点:

  1. 查找和插入的速度极快,不会随着key的增多而变慢
  2. 需要占用大量的内存,内存浪费比较多

list的对应特点:

  1. 占用和插入的时间会随着元素的增加而增加
  2. 占用空间小,浪费内存很少

所以dict可以说是一种用空间来换取时间效率的一种方式。

注意:

dict可以用在需要告诉查找的地方,需要注意的是dict的key是不可变对象

这是因为dict根据key来计算value 的存储未知,如果每次计算相同的key得出不同的结果,那么dict的内部就完全的混乱了,这个通过key计算未知的算法称之为哈希算法

要保证hash 的正确性,作为key的对象就不能变,而在Python中不可变的数据类型比如:整数,字符串,但是list就是可变的,所以不能作为key

五、集合-无序可变性

存储一组不能重复的key,因为key不能重复。

set的创建

s = set([1,2,3])

分析:

创建一个set需要一个list作为输入集合,需要注意的是,传入的参数是一个list,而显示{1,2,3}也不表示set是有序的。

示例:

s = set([1,2,3])
print(s)
s = set([1,2,3,3,4])
print(s) #重复的元素在set的创建过程中会自动被过滤
s.add(5)
print(s) #通过add(key)的方式可以向set中添加元素
s.remove(5)
print(s) #通过remove(key)的方式可以从set中移除元素

set 可以看成数学意义上的无序和无重复元素的集合,因此set可以做数学意义上交集、并集等操作:

s1 = set([1,2,3])
s2 = set([2,3,4])
print(s1 & s2)
print(s1 | s2)

set和dict的唯一区别就在于没有存储相应的value,但是set的原理和dict一样,所以同样不可以方式可变对象,因为无法判断可变对象是否相等,也就是无法符合哈希算法,更无法保证set中不会有重复的元素。

把list放入set:

s1 = set([[1,2,3],2,3]

这个错误翻译过来就是无法匹配哈希的类型 list,也就是在set中不能放入list,因为list是可变的

理解不可变性:

为什么说字符串是不可变的对象,明明他有replace方法,会修改字符串的值

示例:

补充:

id() 内置函数将会返回对象在内存中的地址

a = 'abc'
print(id(a))
a = a.replace('a','A')
print(id(a))

效果:

对于同一变量a来说,它的值先是对象‘abc’ 然后是‘Abc’,这里a只是一个变量而并不是一个对象,它指向的对象的内容是‘abc’

当调用str.replace方法时,这个方式其实没有改变‘abc’这个对象的内容,而是创建了一个新的字符串‘Abc’并把地址返回,所以字符串对象是具有不可变性的

对于不可变对象来说,调用对象本身的任意方法,也不会改变对象自身的内容,相反这些方法会创建

理解:

写一个理解代码:

tuple = ('a','b','c')
print(tuple)
# tuple[1] = tuple[1].replace('b','A')
tuple[1].replace('b','A')
print(tuple)

分析这段代码第一步我是想看看直接调用replce方法是否能修改tuple中的值,这时我以为是字符串直接调用replace函数就能修改本身对象的地址,结果也是没修改,我就先测试了replce函数

a = 'abcd'
a.replace('a','A')
print(a)
a = a.replace('a','A')
print(a)

结果:

理解replace方法的机制就是读取对象值然后返回一个新的对象,直接调用不接收不会改变本身对象的值

所以replace方法就无法直接改变值

这时候我就用tuple去接收,就报错了,值不能被修改,进一步证明了不变性的本质就是存储的指向不能被修改,这个时候我就好奇Python的内存存储方式是什么。

;