乐趣区

关于python:Python线性数据结构

python 线性数据结构

[TOC]


<center> 码好 python 的每一篇文章.</center>

1 线性数据结构

本章要介绍的线性构造:list、tuple、string、bytes、bytearray。

  • 线性表:是一种形象的数学概念,是一组元素的序列的形象,由有穷个元素组成(0 个或任意个)。

    线性表又可分为 程序表和链接表。

  • 程序表:一组元素在内存中有序的存储。列表 list 就是典型的程序表。
  • 链接表:一组元素在内存中扩散存储链接起来,彼此晓得连贯的是谁。

对于这两种表,数组中的元素进行查找、减少、删除、批改,看看有什么影响:

  • 查找元素

    对于程序表,是有序的在内存中存储数据,可疾速通过索引编号获取元素,效率高。。

    对于链接表是扩散存储的,只能通过一个个去迭代获取元素,效率差。

  • 减少元素

    对于程序表,如果是在开端减少元素,对于整个数据表来说没什么影响,然而在结尾或是两头插入元素,前面的所有元素都要从新排序,影响很大(想想数百万或更大数据量)。

    对于链接表,不论在哪里退出元素,不会影响其余元素,影响小。

  • 删除元素
    对于程序表,删除元素和减少元素有着一样的问题。
    对于链接表,不论在哪里删除元素,不会影响其余元素,影响小。
  • 批改元素
    对于程序表,可疾速通过索引获取元素而后进行批改,效率高。

    对于链接表,只能通过迭代获取元素而后进行批改,效率低。

总结:程序表对于查找与批改效率最高,减少和删除效率低。链接表则相同。

2. 内建罕用的数据类型

2.1 数值型

  • int 整数类型

    阐明:整数包含负整数、0、正整数(… -2,-1,0,1,2, …)。

    x1 = 1
    x2 = 0
    x3 = -1
    print(type(x1), x1)
    print(type(x2), x2)
    print(type(x3), x3)
    
    # 输入后果如下:<class 'int'> 1
    <class 'int'> 0
    <class 'int'> -1

    int()办法:能够将数字或字符串转为整数,缺省 base=10, 示意 10 进制,无参数传入则返回 0。

    x1 = int()
    x2 = int('1')
    x3 = int('0b10',base=2)  #base=2,表二进制,与传入参数类型统一。x4 = int(3.14)
    print(type(x1), x1)
    print(type(x2), x2)
    print(type(x3), x3)
    print(type(x4), x4)
    
    # 输入后果如下:<class 'int'> 0
    <class 'int'> 1
    <class 'int'> 2
    <class 'int'> 3
  • float 浮点类型
    阐明:由整数和小数局部组成,传入的参数能够为intstrbytesbytearray

    x1 = float(1)
    x2 = float('2')
    x3 = float(b'3')
    print(type(x1), x1)
    print(type(x2), x2)
    print(type(x3), x3)
    
    # 输入后果如下:<class 'float'> 1.0
    <class 'float'> 2.0
    <class 'float'> 3.0
  • complex (复数类型)

    阐明:由实数和虚数局部组成,都是浮点数。

    传入参数能够为intstr,如果传入两参,后面一个为实数局部,后一个参数为虚数局部。

    x1 = complex(1)
    x2 = complex(2,2)
    x3 = complex('3')
    print(type(x1), x1)
    print(type(x2), x2)
    print(type(x3), x3)
    
    # 输入后果如下:<class 'complex'> (1+0j)
    <class 'complex'> (2+2j)
    <class 'complex'> (3+0j)
  • bool (布尔类型)

    阐明:为 int 的子类,返回的是 True 和 False,对应的是 1 和 0。

    x1 = bool(0)
    x2 = bool(1)
    x3 = bool()
    x4 = 2 > 1
    print(type(x1), x1)
    print(type(x2), x2)
    print(type(x3), x3)
    print(type(x4), x4)
    
    # 输入后果如下:<class 'bool'> False
    <class 'bool'> True
    <class 'bool'> False
    <class 'bool'> True

2.2 序列(sequence)

2.2.1 list 列表

阐明: 列表是由若干元素对象组成,且是 有序可变 的线性数据结构,应用中括号 [] 示意。

  • 初始化

    lst = []  # 空列表形式 1
    #或者
    lst = list()  # 空列表形式 2
    print(type(lst),lst)
    
    # 输出后果如下:<class 'list'> []
  • 索引

    阐明: 应用正索引 (从左至右)、负索引(从右至左) 拜访元素,工夫复杂度为O(1),效率极高的应用形式。

    依照给定区间获取到数据,叫做切片。

    正索引:

    从左至右,从 0 开始索引,区间为[0,长度 -1],左包右不包。

    lst = ['a','b','c','d']
    print(lst[0])  # 获取第一个元素
    print(lst[1:2])  # 获取第二个元素, 左包右不包,切片
    print(lst[2:])  # 获取第三个元素到最初一个元素,切片
    print(lst[:])  # 获取所有元素,切片
    
    # 输入后果如下:a
    ['c']
    ['c', 'd']
    ['a', 'b', 'c', 'd']

    负索引:

    从右至左,从 - 1 开始索引,区间为[- 长度,-1]

    lst = ['a','b','c','d']
    print(lst[-1])
    print(lst[-2:])
    
    # 输入后果如下:d
    ['c', 'd']
  • 查问

    index()办法:L.index(value, [start, [stop]]) -> integer

    返回的是索引 id,要迭代列表,工夫复杂度为 O(n)。

    lst = ['a','b','c','d']
    print(lst.index('a',0,4))  # 获取区间 [0,4] 的元素 'a' 的索引 id
    
    # 输入后果如下:0

    备注:如果查问不到元素,则抛出ValueError

    count() 办法:L.count(value) -> integer

    返回的是元素呈现的次数,要迭代列表,工夫复杂度为 O(n)。

    lst = ['a','b','a','b']
    print(lst.count('a'))
    
    # 输入后果如下:2

    len() 办法:返回的是列表元素的个数,工夫复杂度为 O(1)。

    lst = ['a','b','c','d']
    print(len(lst))
    
    # 输入后果如下:4

    备注:所谓的 O(n) 是指随着数据的规模越来越大,效率降落,而 O(1)则相同,不会随着数据规模大而影响效率。

  • 批改

    列表是有序可变,所以可能对列表中的元素进行批改。

    lst = ['a','b','c','d']
    lst[0] = 'A'
    print(lst)
    
    # 输入后果如下:['A', 'b', 'c', 'd']
  • 减少

    append() 办法:L.append(object) -> None

    尾部追加元素,就地批改,返回 None。

    lst = ['a','b','c','d']
    lst.append('e')
    print(lst)
    
    # 输入后果如下:['a', 'b', 'c', 'd', 'e']

    insert()办法:L.insert(index, object) -> None ,

    在指定索引地位插入元素对象,返回 None。

    lst = ['a','b','c','d']
    lst.insert(0,'A')  # 在索引 0 地位插入 'A', 原有的元素全副往后移,减少了复杂度
    print(lst)
    
    # 输入后果如下:['A', 'a', 'b', 'c', 'd']

    extend()办法: L.extend(iterable) -> None

    能够减少多个元素,将可迭代对象的元素追加进去,返回 None。

    lst = ['a','b','c','d']
    lst.extend([1,2,3])
    print(lst)
    
    # 输入后果如下:['a', 'b', 'c', 'd', 1, 2, 3]

    还能够将列表通过 +*,拼接成新的列表。

    lst1 = ['a','b','c','d']
    lst2 = ['e','f','g']
    print(lst1 + lst2)
    print(lst1 * 2)  # 将列表外面的元素各复制 2 份
    
    # 输入后果如下:['a', 'b', 'c', 'd', 'e', 'f', 'g']
    ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd']

    这里还有一个特地要留神状况如下:

    lst1 = [[1]] * 3  # 后果:[[1], [1], [1]]
    print(lst1)
    lst1[0][0] = 10  # 后果:[[10], [1], [1]],是这样嘛??print(lst1)
    
    # 输入后果如下:[[1], [1], [1]]
    [[10], [10], [10]]  # 为什么后果会是这个?请往下看列表复制章节,找答案!
  • 删除

    remove()办法:L.remove(value) -> None

    从左至右遍历查找,找到就删除该元素,返回 None,找不到则抛出ValueError

    lst = ['a','b','c','d']
    lst.remove('d')
    print(lst)
    
    # 输入后果如下:['a', 'b', 'c']  # 元素 'd' 曾经被删除

    pop() 办法:L.pop([index]) -> item

    缺省删除尾部元素,可指定索引删除元素,索引越界抛出IndexError

    lst = ['a','b','c','d']
    lst.pop()
    print(lst)
    
    # 输入后果如下:['a', 'b', 'c']

    clear() 办法:L.clear() -> None

    清空列表所有元素,慎用。

    lst = ['a','b','c','d']
    lst.clear()
    print(lst)
    
    # 输入后果如下:[]  # 空列表了
  • 反转

    reverse() 办法:L.reverse()

    将列表中的元素反转,返回 None。

    lst = ['a','b','c','d']
    lst.reverse()
    print(lst)
    
    # 输入后果如下:['d', 'c', 'b', 'a']
  • 排序

    sort() 办法:L.sort(key=None, reverse=False) -> None

    对列表元素进行排序,缺省为升序,reverse=True 为降序。

    lst = ['a','b','c','d']
    lst.sort(reverse=True)
    print(lst)
    
    # 输入后果如下:['d', 'c', 'b', 'a']
  • in 成员操作

    判断成员是否在列表外面,有则返回 True、无则返回 False。

    lst = ['a','b','c','d']
    print('a' in lst)
    print('e' in lst)
    
    # 输入后果如下:True
    False
  • 列表复制

    阐明: 列表复制指的是列表元素的复制,可分为浅 copy 和深 copy 两种。列表元素对象如列表、元组、字典、类、实例这些归为援用类型(指向内存地址),而数字、字符串先归为简略类型,好让大家了解。

    示例一:这是属于拷贝嘛?

    lst1 = [1,[2,3],4]
    lst2 = lst1
    print(id(lst1),id(lst2),lst1 == lst2, lst2)  # id() 查看内存地址
    
    # 输入后果如下:1593751168840 1593751168840 True [1, [2, 3], 4]

    显然不是属于任何 copy,说白了都是指向同一个内存地址。

    示例二:浅拷贝 copy

    阐明: 浅拷贝对于 援用类型 对象是不会 copy 的,地址指向仍是一样。

    lst1 = [1,[2,3],4]
    lst2 = lst1.copy()
    print(id(lst1),id(lst2),lst1 == lst2, lst2)
    print('=' * 30)
    lst1[1][0] = 200  # 批改列表的援用类型,所有列表都会扭转
    print(lst1, lst2)
    
    # 输入后果如下:1922175854408 1922175854344 True [1, [2, 3], 4]
    ==============================
    [1, [200, 3], 4] [1, [200, 3], 4]

    示例三:深拷贝 deepcopy

    阐明: 深拷贝对于 援用类型 对象也会 copy 成另外一份,地址指向不一样。

    import copy
    
    lst1 = [1,[2,3],4]
    lst2 = copy.deepcopy(lst1)
    print(id(lst1),id(lst2),lst1 == lst2, lst2)
    print('=' * 30)  
    lst1[1][0] = 200  # 批改列表的援用类型,不会影响其余列表
    print(lst1, lst2)
    
    # 输入后果如下:2378580158344 2378580158280 True [1, [2, 3], 4]
    ==============================
    [1, [200, 3], 4] [1, [2, 3], 4]

2.2.2 tuple 元组

阐明: 元组是由若干元素对象组成,且是 有序不可变 的数据结构,应用小括号 () 示意。

  • 初始化

    t1 = ()  # 空元素形式 1,一旦创立将不可扭转
    t2 = tuple()  # 空元素形式 2,一旦创立将不可扭转
    t3 = ('a',)  # 元组只有一个元素,肯定要加逗号 ','
    t4 = (['a','b','c'])  # 空列表形式 2 

    备注: 元组如果只有一个元素对象,肯定 要在前面加逗号, 否则变为其余数据类型。

  • 索引
    同列表一样,不再过多举例。

    t = ('a','b','c','d')
    print(t[0])
    print(t[-1])
    # 输入后果如下:a
    d
  • 查问

    同列表一样,不再过多举例。

    t = ('a','b','c','d')
    print(t.index('a'))
    print(t.count('a'))
    print(len(t))
    
    # 输入后果如下:0
    1
    4
  • 增删改

    元组是 不可变 类型,不能增删改元素对象。

    然而要留神如下场景:

    元组中的元素对象 (内存地址) 不可变,援用类型可变。—- 这里又呈现援用类型的状况了。

    # 元组的元组不可批改(即内存地址)
    t = ([1],)
    t[0]= 100
    print(t)
    # 后果报错了
    TypeError: 'tuple' object does not support item assignment
        
    ############################################
    
    # 元组外面的援用类型对象能够批改(如嵌套了列表)t = ([1],2,3)
    t[0][0] = 100  # 对元组援用类型对象的元素作批改
    print(t)
    
    # 输入后果如下:([100], 2, 3)

2.2.3 string 字符串

阐明: 字符串是由若干字符组成,且是 有序不可变 的数据结构,应用引号示意。

  • 初始化
    多种花色,应用单引号、双引号、三引号等。

    name = 'tom'
    age = 18
    str1 = 'abc'  # 单引号字符串
    str2 = "abc"  # 双引号字符串
    str3 = """I'm python"""  # 三引号字符串
    str4 = r"c:\windows\note"  # r 前缀,没有本义(转义字符不失效)
    str5 = f'{name} is {age} age.'  # f 前缀,字符串格式化,v3.6 反对
    print(type(str1), str1)
    print(type(str2), str2)
    print(type(str3), str3)
    print(type(str4), str4)
    print(type(str5), str5)
    
    # 输入后果如下:<class 'str'> abc
    <class 'str'> abc
    <class 'str'> I'm python
    <class 'str'> c:\windows\note
    <class 'str'> tom is 18 age.
  • 索引

    同列表一样,不再过多举例。

    str = "abcdefg"
    print(str[0])
    print(str[-1])
    
    # 输入后果如下:a
    g
  • 连贯

    通过加号 + 将多个字符串连接起来,返回一个新的字符串。

    str1 = "abcd"
    str2 = "efg"
    print(str1 + str2)
    
    # 输入后果如下:abcdefg

    join() 办法:S.join(iterable) -> str

    s 示意分隔符字符串,iterable 为可迭代对象 字符串,后果返回字符串。

    str = "abcdefg"
    print('->'.join(str))
    
    # 输入后果如下:a->b->c->d->e->f->g
  • 字符查找

    find() 办法:S.find(sub[, start[, end]]) -> int

    从左至右查找子串 sub,也可指定区间,找到返回正索引,找不到则返回 -1

    str = "abcdefg"
    print(str.find('a',0,7))
    print(str.find('A'))
    
    # 输入后果如下:0
    -1

    rfind() 办法:S.rfind(sub[, start[, end]]) -> int

    从右至左查找子串 sub,也可指定区间,找到返回正索引,找不到则返回 -1

    str = "abcdefg"
    print(str.rfind('a'))
    print(str.rfind('A'))
    
    # 输入后果如下:0
    -1

    还有 index()find() 相似,不过找不到会抛异样,不倡议应用。

    s.count() 还能够统计字符呈现的次数。

    len(s) 还能够统计字符串的长度。

  • 宰割

    split() 办法:S.split(sep=None, maxsplit=-1) -> list of strings

    sep 示意分隔符,缺省为空白字符串,maxsplit=- 1 示意遍历整个字符串,最初返回列表。

    str = "a,b,c,d,e,f,g"
    print(str.split(sep=','))
    
    # 输入后果如下:['a', 'b', 'c', 'd', 'e', 'f', 'g']

    rsplit() 办法与下面不同就是,从右至左遍历。

    splitlines() 办法: S.splitlines([keepends]) -> list of strings

    按行来切割字符串,keepends 示意是否保留行分隔符,最初返回列表。

    str = "a\nb\nc\r\nd"
    print(str.splitlines())
    print(str.splitlines(keepends=True))
    
    # 输入后果如下:['a', 'b', 'c', 'd']
    ['a\n', 'b\n', 'c\r\n', 'd']

    partition() 办法S.partition(sep) -> (head, sep, tail)

    从左至右查问分隔符,遇到就宰割成头、分隔符、尾的三元组,返回的是一个元组 tuple。

    str = "a*b*c*d"
    print(str.partition('*'))
    # 输入后果如下:('a', '*', 'b*c*d')

    rpartition() 办法S.rpartition(sep) -> (head, sep, tail)

    与上办法不同,就是从右至左,不过这个比拟罕用,能够获取后缀局部信息。

    str1 = "http://www.python.org:8843"
    str2 = str1.rpartition(':')
    port = str2[-1]
    print(port)
  • 替换

    replace() 办法:S.replace(old, new[, count]) -> str

    遍历整个字符串,找到全副替换,count 示意替换次数,缺省替换全副,最初返回一个 新的字符串

    str = "www.python.org"
    print(str.replace('w','m'))  # 返回的是一个新的字符串
    print(str)  # 字符串不可变,放弃原样
    
    # 输入后果如下:mmm.python.org
    www.python.org
  • 移除

    strip() 办法:S.strip([chars]) -> str

    在字符串两端移除指定的 字符集 chars , 缺省移除空白字符。

    str = "* www.python.org  *"
    print(str.strip("*"))  # 去掉字符串首尾带有星号 '*' 和 空白 ' '
    
    # 输入后果如下:www.python.org

    还有lstrip()rstrip 别离是移除字符串右边和左边字符集。

  • 首尾判断

    startswith() 办法:S.startswith(prefix[, start[, end]]) -> bool

    缺省判断字符串结尾是否有指定的字符 prefix, 也可指定区间。

    str = "www.python.org"
    print(str.startswith('www',0,14))
    print(str.startswith('p',0,14))
    # 输入后果如下:True
    False

    endswith() 办法:S.endswith(suffix[, start[, end]]) -> bool

    缺省判断字符串结尾是否有指定的字符 suffix, 也可指定区间。

    str = "www.python.org"
    print(str.startswith('www',0,14))
    print(str.startswith('p',0,14))
    # 输入后果如下:True
    False
    str = "www.python.org"
    print(str.endswith('g',11,14))
    # 输入后果如下:True
  • 格式化

    c 格调格式化:

    格局字符串:应用 %s(对应值为字符串),%d(对应值为数字)等等,还能够在两头插入修饰符 %03d。

    被格局的值:只能是一个对象,能够是元组或是字典。

    name = "Tom"
    age = 18
    print("%s is %d age." % (name,age))
    # 输入后果如下:Tom is 18 age.

    format 格式化:

    格局字符串:应用花括号{}, 花括号外面能够应用修饰符。

    被格局的值:args 为可变地位参数,*kwargs 为可变关键字参数。

    # 地位传参
    print("IP={} PORT={}".format('8.8.8.8',53))  # 地位传参
    print("{Server}: IP={1} PORT={0}".format(53, '8.8.8.8', Server='DNS Server'))  # 地位和关键字传参传参
    
    # 输入后果如下:IP=8.8.8.8 PORT=53
    DNS Server: IP=8.8.8.8 PORT=53
    # 浮点数
    print("{}".format(0.123456789))
    print("{:f}".format(0.123456789))    #  小数点默认为 6 位
    print("{:.2f}".format(0.123456789))  # 取小数点后两位
    print("{:15}".format(0.123456789))   # 宽度为 15,右对齐
    
    # 输入后果如下:0.123456789
    0.123457     # 为什么是这个值?大于 5 要进位
    0.12
        0.123456789  # 右边有 4 个空格
  • 其余罕用函数

    str = "DianDiJiShu"
    print(str.upper())  # 字母全副转化为大写
    print(str.lower())  # 字母全副转化为小写
    
    # 输入后果如下:DIANDIJISHU
    diandijishu

2.2.4 bytes 字节

bytes bytearray从 python3 引入的两种数据类型。

在计算机的世界里,机器是以 01 组成的,也叫二进制(字节) 来通信的,这套编码咱们叫做 ASCII 编码。

所以机器通信的语言就叫做机器语言。然而咱们人类想要跟机器通信,那么须要怎么做呢?

  • 把人类的语言编码成机器可能辨认的语言,通常叫做编码(字符串转换为 ASCII 码)。
  • 把机器的语言解码成人类可能辨认的语言,通常叫做解码(ASCII 码转换为字符串)。

至今古代编码的发展史过程大略是这样的:ASCII(1 字节) -> unicode(2~4 字节) -> utf-8(1~6 字节),utf8 是多字节编码,个别应用 1~3 字节,非凡应用 4 字节(个别中文应用 3 字节),向下兼容 ASCII 编码。

中国也有属于本人的编码:gbk

ASCII 码表罕用的必须牢记(整顿局部):

具体 ASCII 码下载链接:

链接:https://pan.baidu.com/s/1fWVl57Kqmv-tkjrDKwPvSw 提取码:tuyz

所以,机器上的进制就是字节,1 字节等于 8 位,例如:十进制 2,用 2 进制和 16 进制示意:

# 二进制
0000 0010  # 一个字节 bytes

# 16 进制,机器根本都是显示 16 进制
0x2

bytes 是不可变类型

bytes()     # 空 bytes,一旦创立不可扭转
bytes(int)  # 指定字节的大小,用 0 填充
bytes(iterable_of_ints)  # [0.255]整数的可迭代对象
bytes(string, encoding[, errors])  # 等价于 string.encoding(), 字符串编码成字节
bytes(bytes_or_buffer)  # 复制一份新的字节对象
  • 初始化

    b1 = bytes()
    b2 = bytes(range(97,100))
    b3 = bytes(b2)
    b4 = bytes('123',encoding='utf-8')
    b5 = b'ABC'
    b6 = b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode('utf-8')
    print(b1, b2, b3, b4, b5, b6, sep='\n')
    
    # 输入后果如下:b''b'abc'b'abc'b'123'b'ABC'
    你好

2.2.5 bytearray 字节数组

bytearray 是可变数组,能够进行增删改操作,相似列表。

bytearray()  # 空 bytearray, 可扭转
bytearray(iterable_of_ints)  # [0.255]整数的可迭代对象
bytearray(string, encoding[, errors])  # 等价于 string.encoding(), 字符串编码成字节
bytearray(bytes_or_buffer)   # 复制一份新的字节数组对象
bytearray(int)  # 指定字节的大小,用 0 填充
  • 增删改

    # 初始化
    b = bytearray()
    print(b)
    # 输入后果如下:bytearray(b'')
    #--------------------------
    # 减少元素对象
    b.append(97)
    print(b)
    b.extend([98,99])
    print(b)
    # 输入后果如下:bytearray(b'a')
    bytearray(b'abc')
    #--------------------------
    # 插入元素对象
    b.insert(0,65)
    print(b)
    # 输入后果如下:bytearray(b'Aabc')
    #--------------------------
    # 删除元素对象
    b.pop()
    print(b)
    # 输入后果如下:bytearray(b'Aab')

明天就到这了,下一回合咱再接着唠嗑 set (汇合) dict (字典),敬请急躁期待。

如果喜爱的我的文章,欢送关注我的公众号:点滴技术,扫码关注,不定期分享

退出移动版