02.python线性数据结构
阅读原文时间:2023年07月08日阅读:1

分类

数值型

  • int、float、complex、bool

序列sequence

  • 字符串str、字节序列bytes、bytearray
  • 列表list、元组tuple

键值对

  • 集合set、字典dict

  • int、float、complex、bool都是class,1、5.0、2+3j都是对象即实例

  • int:python3的int就是长整型,且没有大小限制,受限于内存区域的大小

  • float:由整数部分和小数部分组成。支持十进制和科学计数法表示。C的双精度型实现

  • complex:有实数和虚数部分组成,实数和虚数部分都是浮点数,3+4.2J

  • bool:int的子类,仅有2个实例True、False对应1和0,可以和整数直接运算

类型转换

  • int、float、complex、bool也可以当做内建函数对数据进行类型转换
  • int(x) 返回一个整数
  • float(x) 返回一个浮点数
  • complex(x)、complex(x,y) 返回一个复数
  • bool(x) 返回布尔值,前面讲过False等价的对象

取整

math模块的floor()、ceil()函数;内建函数int()、round();运算符//

# 整除
print(3//2, 5//2, 7//2)
print(-3//2, -5//2, -7//2)
print(7//2, 7//-2, -7//2, -(7//2))
# int
print('int ------------')
print(int(1.4), int(1.5), int(1.6))
print(int(-1.4), int(-1.5), int(-1.6))
# ceil floor
print('ceil floor ------------')
import math
print(math.floor(2.5), math.floor(-2.5))
print(math.ceil(2.5), math.ceil(-2.5))
# round
print('round ------------')
print(round(1.4), round(-1.4), round(-1.6), round(1.6))
  • round(),四舍六入五取偶
  • math.floor()向下取整
  • math.ceil()向上取整
  • int() 取整数部分
  • // 整除且向下取整

常用数值处理函数

  • min()、max()

  • abs()

  • pow(x, y) 等于 x ** y

  • math.sqrt() 等于 x ** 0.5

  • 进制函数,返回值是字符串

    • bin()、oct()、hex()
  • math模块

    • math.pi π
    • math.e 自如常数
    • math模块中还有对数函数、三角函数等

    type(123) # 返回的是类型int
    isinstance(456, int)
    isinstance(True, (str, int, bool))
    type(1 + True)
    type(1 + True + 2.0) # 什么类型?

即使是强类型语言,也会有隐式类型转换。

线性表

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

  • 顺序表:使用一大块连续的内存顺序存储表中的元素,这样实现的表称为顺序表,或称连续表

    在顺序表中,元素的关系使用顺序表的存储顺序自然地表示

  • 链接表:在存储空间中将分散存储的元素链接起来,这种实现称为链接表,简称链表

列表如同地铁站排好的队伍,有序,可以插队、离队,可以索引。

链表如同操场上手拉手的小朋友,有序但空间排列随意。或者可以想象成一串带线的珠子,随意盘放在桌上。也可以离队、插队,也可以索引。

对比体会一下,这两种数据结构的增删改查。

  • 一个排列整齐的队伍,Python采用顺序表实现
  • 列表内的个体称作元素,由若干元素组成列表
  • 元素可以是任意对象(数字、字符串、对象、列表等)
  • 列表内元素有顺序,可以使用索引
  • 线性的数据结构
  • 使用 [ ] 表示
  • 列表是可变的

列表是非常重要的数据结构,对其内存结构和操作方法必须烂熟于心。

初始化

  • list() -> new empty list
  • list(iterable) -> new list initialized from iterable's items
  • []
  • 列表不能一开始就定义大小

索引

  • 索引,也叫下标
  • 正索引:从左至右,从0开始,为列表中每一个元素编号
  • 如果列表有元素,索引范围[0, 长度-1]
  • 负索引:从右至左,从-1开始
  • 如果列表有元素,索引范围[-长度, -1]
  • 正、负索引不可以超界,否则引发异常IndexError
  • 为了理解方便,可以认为列表是从左至右排列的,左边是头部,右边是尾部,左边是下界,右边是上界
  • 列表通过索引访问,list[index] ,index就是索引,使用中括号访问

使用索引定位访问元素的时间复杂度为O(1),这是最快的方式,是列表最好的使用方式。

查询

  • index(value,[start,[stop]])

    • 通过值value,从指定区间查找列表内的元素是否匹配
    • 匹配第一个就立即返回索引
    • 匹配不到,抛出异常ValueError
  • count(value)

    • 返回列表中匹配value的次数
  • 时间复杂度

    • index和count方法都是O(n)
    • 随着列表数据规模的增大,而效率下降
  • 如何返回列表元素的个数?如何遍历?如何设计高效?

    len()

修改

  • 索引定位元素,然后修改。注意索引不能超界

    ls1 = [1,2,3,4]
    ls1[2] = 200

增加单个元素

  • append(object) -> None

    • 列表尾部追加元素,返回None
    • 返回None就意味着没有新的列表产生,就地修改
    • 定位时间复杂度是O(1)
  • insert(index, object) -> None

    • 在指定的索引index处插入元素object
    • 返回None就意味着没有新的列表产生,就地修改
    • 定位时间复杂度是O(1)
  • 索引能超上下界吗?

    • 超越上界,尾部追加
    • 超越下界,头部追加

增加多个元素

  • extend(iteratable) -> None

    • 将可迭代对象的元素追加进来,返回None
    • 就地修改,本列表自身扩展
  • + -> list

    • 连接操作,将两个列表连接起来,产生新的列表,原列表不变
    • 本质上调用的是魔术方法__add__()方法
  • * -> list

    • 重复操作,将本列表元素重复n次,返回新的列表

    ls1 = [1] * 5
    ls2 = [None] * 6
    ls3 = [1,2] * 3
    ls4 = [[1]] * 3

这个重复操作看似好用,如果原理掌握不好,但非常危险

x = [1] * 3
x[0] = 100
print(x) # 结果是什么


y = [[1]] * 3
print(y) # 结果是什么
y[0] = 100
print(y) # 结果是什么
y1 = 200
print(y) # 结果是什么

在Python中一切皆对象,而对象都是引用类型,可以理解为一个地址指针指向这个对象。

但是,字面常量字符串、数值等表现却不像引用类型,暂时可以称为简单类型。

而列表、元组、字典,包括以后学习的类和实例都可以认为是引用类型。

你可以认为简单类型直接存在列表中,而引入类型只是把引用地址存在了列表中。

删除

  • remove(value) -> None

    • 从左至右查找第一个匹配value的值,找到就移除该元素,并返回None,否则ValueError
    • 就地修改
    • 效率?低
  • pop([index]) -> item

    • 不指定索引index,就从列表尾部弹出一个元素
    • 指定索引index,就从索引处弹出一个元素,索引超界抛出IndexError错误
    • 效率?指定索引的的时间复杂度?不指定索引呢?
  • clear() -> None

    • 清除列表所有元素,剩下一个空列表

反转

  • reverse() -> None

    • 将列表元素反转,返回None
    • 就地修改

这个方法最好不用,可以倒着读取,都不要反转。

排序

  • sort(key=None, reverse=False) -> None

    • 对列表元素进行排序,就地修改,默认升序
    • reverse为True,反转,降序
    • key一个函数,指定key如何排序,lst.sort(key=function)

如果排序是必须的,那么排序。排序效率高吗?

in成员操作

'a' in ['a', 'b', 'c']
[3,4] in [1, 2, 3, [3,4]]
for x in [1,2,3,4]:
    pass

列表复制

a = list(range(4))
b = list(range(4))
print(a == b) c = a c[2] = 10
print(a)
print(a == b) # 还相等吗?
print(a == c) # 相等吗?

问题:

  1. 最终a 和 b相等吗?a和b分别存着什么元素
  2. a 和 c 相等吗?为什么? c = a 这一句有复制吗?

下面的程序a和b相等吗?

a = list(range(4))
b = a.copy()
print(a == b) a[2] = 10
print(a == b)


a = [1, [2, 3, 4], 5] b = a.copy()
print(a == b) a[2] = 10
print(a == b) a[2] = b[2]
print(a == b) a[1][1] = 100
print(a == b) # 还相等吗?
print(a)
print(b)

列表的内存模型和深浅拷贝

  • shadow copy

    • 影子拷贝,也叫浅拷贝。遇到引用类型数据,仅仅复制一个引用而已
  • deep copy

    • 深拷贝,往往会递归复制一定深度

一般情况下,大多数语言提供的默认复制行为都是浅拷贝。

import copy
a = [1, [2, 3], 4] b = copy.deepcopy(a)
print(a == b) a[1][1] = 100
print(a == b) # 还相等吗?
print(a)
print(b)

Python内建数据类型,内部都实现了 == ,它的意思是内容比较

random模块

  • randint(a, b) 返回[a, b]之间的整数

  • randrange ([start,] stop [,step]) 从指定范围内,按指定基数递增的集合中获取一个随机数,基数缺省值为1。 random.randrange(1,7,2)

  • choice(seq) 从非空序列的元素中随机挑选一个元素,比如

    • random.choice(range(10)),从0到9中随机挑选一个整数
    • random.choice([1,3,5,7])
  • 3.6开始提供choices,一次从样本中随机选择几个,可重复选择,可以指定权重

  • random.shuffle(list) ->None 就地打乱列表元素

  • sample(population, k) 从样本空间或总体(序列或者集合类型)中随机取出k个不同的元素,返回一个新的列表

    • random.sample(['a', 'b', 'c', 'd'], 2)
    • random.sample(['a', 'a'], 2) 会返回什么结果
    • 每次从样本空间采样,在这一次中不可以重复抽取同一个元素

    import random
    for i in range(10):
       print(random.randint(1, 5))
    print('-' * 30)
    for i in range(10):
       print(random.randrange(1, 5))
    print('-' * 30) x = [1, 2, 3, 4, 5]
    for i in range(10):
       print(random.choice(x))
    print('-' * 30)

    观察下面的0和1的比例

    for i in range(10):
       print(random.choices([0, 1], k=6))
    print('-' * 30)
    for i in range(10):
       print(random.choices([0, 1], [10, 1], k=6)) # 10比1权重
    x = [1, 2, 3, 4, 5]

    采样

    for i in range(5):
       print(random.sample(x, 5)) # k能不能是6?

  • 一个有序的元素组成的集合

  • 使用小括号 ( ) 表示

  • 元组是不可变对象

初始化

  • tuple() -> empty tuple

  • tuple(iterable) -> tuple initialized from iterable's items

    t1 = () # 空元组
    t2 = (1,) # 必须有这个逗号
    t3 = (1,) * 5
    t4 = (1, 2, 3)
    t5 = 1, 'a'
    t6 = (1, 2, 3, 1, 2, 3)
    t7 = tuple() # 空元组
    t8 = tuple(range(5))
    t9 = tuple([1,2,3])

索引

索引和列表规则一样,不可以超界

查询

方法和列表一样,时间复杂度也一样。index、count、len等

增删改

元组元素的个数在初始化的时候已经定义好了,所以不能为元组增加元素、也不能从中删除元素、也不能修改元素的内容。

但是要注意下面这个例子

t1 = ([1]) * 3
t1[1] = 100 # ?
# 注意下面的例子
t2 = ([1],) * 3
print(t2)
t2[1] = 100
t2[0][0] = 100
print(t2)

上例说明t2是可变的吗?不是说元组不可变吗?到底什么不可变

  • 一个个字符组成的有序的序列,是字符的集合
  • 使用单引号、双引号、三引号引住的字符序列
  • 字符串是不可变对象,是字面常量

Python3起,字符串都是Unicode类型

初始化

s1 = 'string'
s2 = "string2"
s3 = '''this's a "String" '''
s4 = 'hello \n magedu.com'
s5 = r"hello \n magedu.com"
s6 = 'c:\windows\nt'
s7 = R"c:\windows\nt"
s8 = 'c:\windows\\nt'
name = 'tom'; age = 20 # python代码写在一行,使用分号隔开,不推荐
s9 = f'{name}, {age}' # 3.6支持f前缀
sql = """select * from user where name='tom' """

r前缀:所有字符都是本来的意思,没有转义

f前缀:3.6开始,使用变量插值

索引

字符串是序列,支持下标访问。但不可变,不可以修改元素。

sql = "select * from user where name='tom'"
print(sql[4]) # 字符串'c'
sql[4] = 'o' # 不可以

连接

  • 加号

    • 将2个字符串连接起来
  • 返回一个新的字符串

  • join方法

    • sep.join(iterable)
    • 使用指定字符串作为分隔符,将可迭代对象中字符串使用这个分隔符拼接起来
    • 可迭代对象必须是字符串
    • 返回一个新的字符串

字符查找

  • find(sub[, start[, end]]) -> int

    • 在指定的区间[start, end),从左至右,查找子串sub
    • 找到返回正索引,没找到返回-1
  • rfind(sub[, start[, end]]) -> int

    • 在指定的区间[start, end),从右至左,查找子串sub
    • 找到返回正索引,没找到返回-1

    s = 'magedu.edu'
    print(s.find('edu'))
    print(s.find('edu', 3))
    print(s.find('edu', 4))
    print(s.find('edu', 6, 9))
    print(s.find('edu', 7, 20))
    print(s.find('edu', 200))
    s = 'magedu.edu'
    print(s.rfind('edu'))
    print(s.rfind('edu', 3))
    print(s.rfind('edu', 4))
    print(s.rfind('edu', 6, 9))
    print(s.rfind('edu', 7, 20))
    print(s.rfind('edu', 200))

这两个方法只是找字符串的方向不同,返回值一样。找到第一个满足要求的子串立即返回。特别注意返

回值,找不到返回的是负数-1。

这两个方法效率高吗?要不要用?

这两个方法效率真不高,都是在字符串中遍历搜索,但是如果找子串工作必不可少,那么必须这么做,

但是能少做就少做。

  • index(sub[, start[, end]]) -> int

    • 在指定的区间[start, end),从左至右,查找子串sub
    • 找到返回正索引,没找到抛出异常ValueError
  • rindex(sub[, start[, end]]) -> int

    • 在指定的区间[start, end),从左至右,查找子串sub
    • 找到返回正索引,没找到抛出异常ValueError

index方法和find方法很像,不好的地方在于找不到抛异常。推荐使用find方法。

s = 'magedu.edu'
print(s.index('edu'))
print(s.index('edu', 3))
print(s.index('edu', 4))
#print(s.index('edu', 6, 9)) # 抛异常
print(s.index('edu', 7, 20))
#print(s.index('edu', 200)) # 抛异常
  • count(sub[, start[, end]]) -> int

    • 在指定的区间[start, end),从左至右,统计子串sub出现的次数

    s = 'magedu.edu'
    print(s.count('edu'))
    print(s.count('edu', 4))

  • 时间复杂度

    • find、index和count方法都是O(n)
    • 随着字符串数据规模的增大,而效率下降
  • len(string)

    • 返回字符串的长度,即字符的个数

分割

  • split(sep=None, maxsplit=-1) -> list of strings

    • 从左至右
    • sep 指定分割字符串,缺省的情况下空白字符串作为分隔符
    • maxsplit 指定分割的次数,-1 表示遍历整个字符串
    • 立即返回列表
  • rsplit(sep=None, maxsplit=-1) -> list of strings

    • 从右向左开始切,但是输出的字符串字符不会反
    • sep 指定分割字符串,缺省的情况下空白字符串作为分隔符
    • maxsplit 指定分割的次数,-1 表示遍历整个字符串
    • 立即返回列表
  • splitlines([keepends]) -> list of strings

    • 按照行来切分字符串
    • keepends 指的是是否保留行分隔符
    • 行分隔符包括\n、\r\n、\r等

    s = ','.join('abcd')
    print(s.split(','))
    print(s.split())
    print(s.split(',', 2))
    s1 = '\na b \tc\nd\n' # 注意下面3个切割的区别
    print(s1.split())
    print(s1.split(' '))
    print(s1.split('\n'))
    print(s1.split('b'))
    print(s1.splitlines())

  • partition(sep) -> (head, sep, tail)

    • 从左至右,遇到分隔符就把字符串分割成两部分,返回头、分隔符、尾三部分的三元组
    • 如果没有找到分隔符,就返回头、2个空元素的三元组
    • sep 分割字符串,必须指定
  • rpartition(sep) -> (head, sep, tail)

    • 从右至左,遇到分隔符就把字符串分割成两部分,返回头、分隔符、尾三部分的三元组
    • 如果没有找到分隔符,就返回2个空元素和尾的三元组

    s = ','.join('abcd')
    print(s.partition(','))
    print(s.partition('.'))
    print(s.rpartition(','))
    print(s.rpartition('.'))

替换

  • replace(old, new[, count]) -> str

    • 字符串中找到匹配替换为新子串,返回新字符串
    • count表示替换几次,不指定就是全部替换

    s = ','.join('abcd')
    print(s.replace(',', ' '))
    print(s.replace(',', ' ', 2))
    s1 = 'www.magedu.edu'
    print(s1.replace('w', 'a'))
    print(s1.replace('ww', 'a'))
    print(s1.replace('ww', 'w')) # 返回什么?
    print(s1.replace('www', 'a'))

移除

  • strip([chars]) -> str

    • 在字符串两端去除指定的字符集chars中的所有字符
    • 如果chars没有指定,去除两端的空白字符
  • lstrip([chars]) -> str ,从左开始

  • rstrip([chars]) -> str,从右开始

    s = '\t\r\na b c,d\ne\n\t'
    print(s.strip())
    print('-' * 30)
    print(s.strip('\t\n'))
    print('-' * 30)
    print(s.strip('\t\ne\r'))

首尾判断

  • endswith(suffix[, start[, end]]) -> bool

    • 在指定的区间[start, end),字符串是否是suffix结尾
  • startswith(prefix[, start[, end]]) -> bool

    • 在指定的区间[start, end),字符串是否是prefix开头

    s = "www.magedu.edu"
    print(s.startswith('ww'))
    print(s.startswith('e', 7))
    print(s.startswith('e', 10))
    print(s.startswith('edu', 11))
    print(s.endswith('edu'))

其它函数

  • upper()大写
  • lower()小写
  • swapcase() 交换大小写
  • isalnum() -> bool 是否是字母和数字组成
  • isalpha() 是否是字母
  • isdecimal() 是否只包含十进制数字
  • isdigit() 是否全部数字(0~9)
  • isidentifier() 是不是字母和下划线开头,其他都是字母、数字、下划线
  • islower() 是否都是小写
  • isupper() 是否全部大写
  • isspace() 是否只包含空白字符

其他格式打印函数中文几乎不用,大家自行查看帮助

简单的使用+或者join也可以拼接字符串,但是需要先转换数据到字符串后才能拼接。

C风格printf-style

  • 占位符:使用%和格式字符,例如%s、%d

  • 修饰符:在占位符中还可以插入修饰符,例如%03d

  • format % values

    • format是格式字符串,values是被格式的值
    • 格式字符串和被格式的值之间使用%
    • values只能是一个对象,可以是一个值,可以是一个元素个数和占位符数目相等的元组,也可以是一个字典

    "I am %03d" % (20,)
    'I like %s.' % 'Python'
    "%3.2f%% 0x%x %#X" % (89.7654, 10, 256) # 宽度为3,小数点后2位
    "I am %-5d" % (20,)
    "%(host)s.%(domain)s" % {'domain':'magedu.com', 'host':'www'} # 靠名字对应

format函数

Python2.5之后,字符串类型提供了format函数,功能更加强大,鼓励使用。

"{} {xxx}".format(*args, **kwargs) -> str

  • args是可变的位置参数

  • kwargs是可变关键字参数,写作a=100

  • 使用花括号作为占位符

  • {}表示按照顺序匹配位置参数,{n}表示取位置参数索引为n的值

  • {xxx}表示在关键字参数中搜索名称一致的

  • {{}} 表示打印花括号

    位置对应

    "{}:{}".format('127.0.0.1', 8080)

    位置或关键字对应

    "{server} {1}:{0}".format(8080, '127.0.0.1', server='Web Server Info: ')

    访问元素

    "{0[0]}.{0[1]}".format(('magedu', 'com'))

    进制

    "{0:d} {0:b} {0:o} {0:x} {0:#X}".format(31)

    浮点数

    print("{}".format(30.5)) # 1.7320508075688772 print("{:f}".format(30.5)) # 1.732051,精度默认6
    print("{:10f}".format(30.5)) # 右对齐,宽度10 print("{:2}".format(102.231)) # 宽度为2数字 print("{:2}".format(1))     # 宽度为2数字 print("{:.2}".format(30.5)) # 1.7 2个数字
    print("{:.2f}".format(30.5)) # 1.73 小数点后2位 print("{:3.2f}".format(30.5))  # 1.73 宽度为3,小数点后2位
    print("{:20.3f}".format(0.2745)) # 0.275
    print("{:3.3%}".format(1/3)) # 33.333%

    注意宽度可以被撑破

    对齐

    print("{}{}={}".format(5, 6, 56))
    print("{}{}={:2}".format(5, 6, 56))
    print("{1}{0}={2:3}".format(5, 6, 56))
    print("{1}{0}={2:0>3}".format(5, 6, 56))
    print("{}{}={:#<3}".format(4, 5, 20)) print("{:#^7}".format('' * 3))

Python3 引入两个新的类型bytes、bytearray。

bytes不可变字节序列;bytearray是可变字节数组。

编码与解码

  • 编码:str => bytes,将字符串这个字符序列使用指定字符集encode编码为一个个字节组成的序列bytes

  • 解码:bytes或bytearray => str,将一个个字节按照某种指定的字符集解码为一个个字符串组成的字符串

    print("abc".encdoe())        # 缺省为utf-8编码
    print("啊".encode('utf-8'))
    print("啊".encode('gbk'))
    print(b'abc'.decode('utf8'))
    print(b'\xb0\xa1'.decode('gbk'))

ASCII

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套单字节编码系统

基本ASCII码

前128个称为基本ASCII码,从二进制角度来看,它们的最高位bit[7]=0,只使用了低7位bit[6,0]来进行编码。

0~31 之间的ASCII码常用于控制像打印机一样的外围设备。

十进制DEC

八进制OCT

十六进制HEX

二进制BIN

符号Symbol

HTML实体编码

中文解释Description

0

000

00

00000000

NUL

空字符

1

001

01

00000001

SOH

标题开始

2

002

02

00000010

STX

正文开始

3

003

03

00000011

ETX

正文结束

4

004

04

00000100

EOT

传输结束

5

005

05

00000101

ENQ

询问

6

006

06

00000110

ACK

收到通知

7

007

07

00000111

BEL

8

010

08

00001000

BS

退格

9

011

09

00001001

HT

水平制表符

10

012

0A

00001010

LF

换行键

11

013

0B

00001011

VT

垂直制表符

12

014

0C

00001100

FF

换页键

13

015

0D

00001101

CR

回车键

14

016

0E

00001110

SO

移出

15

017

0F

00001111

SI

移入

16

020

10

00010000

DLE

数据链路转义

17

021

11

00010001

DC1

设备控制 1

18

022

12

00010010

DC2

设备控制 2

19

023

13

00010011

DC3

设备控制 3

20

024

14

00010100

DC4

设备控制 4

21

025

15

00010101

NAK

拒绝接收

22

026

16

00010110

SYN

同步空闲

23

027

17

00010111

ETB

传输块结束

24

030

18

00011000

CAN

取消

25

031

19

00011001

EM

介质中断

26

032

1A

00011010

SUB

替换

27

033

1B

00011011

ESC

换码符

28

034

1C

00011100

FS

文件分隔符

29

035

1D

00011101

GS

组分隔符

30

036

1E

00011110

RS

记录分离符

31

037

1F

00011111

US

单元分隔符

32~127 之间的ASCII码表示的符号,在我们的键盘上都可以被找到。其中:32表示空格,127表示删除命令。

十进制DEC

八进制OCT

十六进制HEX

二进制BIN

符号Symbol

HTML实体编码

中文解释Description

32

040

20

00100000

空格

33

041

21

00100001

!

!

感叹号

34

042

22

00100010

"

"

双引号

35

043

23

00100011

#

#

井号

36

044

24

00100100

$

$

美元符

37

045

25

00100101

%

%

百分号

38

046

26

00100110

&

&

39

047

27

00100111

'

'

单引号

40

050

28

00101000

(

(

左括号

41

051

29

00101001

)

)

右括号

42

052

2A

00101010

*

*

星号

43

053

2B

00101011

+

+

加号

44

054

2C

00101100

,

,

逗号

45

055

2D

00101101

-

-

连字号或减号

46

056

2E

00101110

.

.

句点或小数点

47

057

2F

00101111

/

/

斜杠

48

060

30

00110000

0

0

0

49

061

31

00110001

1

1

1

50

062

32

00110010

2

2

2

51

063

33

00110011

3

3

3

52

064

34

00110100

4

4

4

53

065

35

00110101

5

5

5

54

066

36

00110110

6

6

6

55

067

37

00110111

7

7

7

56

070

38

00111000

8

8

8

57

071

39

00111001

9

9

9

58

072

3A

00111010

:

:

冒号

59

073

3B

00111011

;

;

分号

60

074

3C

00111100

<

<

小于

61

075

3D

00111101

=

=

等号

62

076

3E

00111110

>

>

大于

63

077

3F

00111111

?

?

问号

64

100

40

01000000

@

@

电子邮件符号

65

101

41

01000001

A

A

大写字母 A

66

102

42

01000010

B

B

大写字母 B

67

103

43

01000011

C

C

大写字母 C

68

104

44

01000100

D

D

大写字母 D

69

105

45

01000101

E

E

大写字母 E

70

106

46

01000110

F

F

大写字母 F

71

107

47

01000111

G

G

大写字母 G

72

110

48

01001000

H

H

大写字母 H

73

111

49

01001001

I

I

大写字母 I

74

112

4A

01001010

J

J

大写字母 J

75

113

4B

01001011

K

K

大写字母 K

76

114

4C

01001100

L

L

大写字母 L

77

115

4D

01001101

M

M

大写字母 M

78

116

4E

01001110

N

N

大写字母 N

79

117

4F

01001111

O

O

大写字母 O

80

120

50

01010000

P

P

大写字母 P

81

121

51

01010001

Q

Q

大写字母 Q

82

122

52

01010010

R

R

大写字母 R

83

123

53

01010011

S

S

大写字母 S

84

124

54

01010100

T

T

大写字母 T

85

125

55

01010101

U

U

大写字母 U

86

126

56

01010110

V

V

大写字母 V

87

127

57

01010111

W

&#087

大写字母 W

88

130

58

01011000

X

X

大写字母 X

89

131

59

01011001

Y

Y

大写字母 Y

90

132

5A

01011010

Z

Z

大写字母 Z

91

133

5B

01011011

[

[

左中括号

92

134

5C

01011100

\

\

反斜杠

93

135

5D

01011101

]

]

右中括号

94

136

5E

01011110

^

^

音调符号

95

137

5F

01011111

_

_

下划线

96

140

60

01100000

`

`

重音符

97

141

61

01100001

a

a

小写字母 a

98

142

62

01100010

b

b

小写字母 b

99

143

63

01100011

c

c

小写字母 c

100

144

64

01100100

d

d

小写字母 d

101

145

65

01100101

e

e

小写字母 e

102

146

66

01100110

f

f

小写字母 f

103

147

67

01100111

g

g

小写字母 g

104

150

68

01101000

h

h

小写字母 h

105

151

69

01101001

i

i

小写字母 i

106

152

6A

01101010

j

j

小写字母 j

107

153

6B

01101011

k

k

小写字母 k

108

154

6C

01101100

l

l

小写字母 l

109

155

6D

01101101

m

m

小写字母 m

110

156

6E

01101110

n

n

小写字母 n

111

157

6F

01101111

o

o

小写字母 o

112

160

70

01110000

p

p

小写字母 p

113

161

71

01110001

q

q

小写字母 q

114

162

72

01110010

r

r

小写字母 r

115

163

73

01110011

s

s

小写字母 s

116

164

74

01110100

t

t

小写字母 t

117

165

75

01110101

u

u

小写字母 u

118

166

76

01110110

v

v

小写字母 v

119

167

77

01110111

w

w

小写字母 w

120

170

78

01111000

x

x

小写字母 x

121

171

79

01111001

y

y

小写字母 y

122

172

7A

01111010

z

z

小写字母 z

123

173

7B

01111011

{

{

左大括号

124

174

7C

01111100

|

|

垂直线

125

175

7D

01111101

}

}

右大括号

126

176

7E

01111110

~

~

波浪号

127

177

7F

01111111

删除

扩展ASCII码

后128个称为扩展ASCII码。许多基于x86的系统都支持使用扩展(或“高”)ASCII。扩展ASCII码允许将每个字符的第8 位用于确定附加的128 个特殊符号字符、外来语字母和图形符号

十进制DEC

八进制OCT

十六进制HEX

二进制BIN

符号Symbol

HTML实体编码

中文解释Description

128

200

80

10000000

欧盟符号

129

201

81

10000001

130

202

82

10000010

单低 9 引号

131

203

83

10000011

ƒ

带钩的拉丁小写字母f

132

204

84

10000100

双低 9 引号

133

205

85

10000101

水平省略号

134

206

86

10000110

剑号

135

207

87

10000111

双剑号

136

210

88

10001000

ˆ

修正字符抑扬音符号

137

211

89

10001001

千分号

138

212

8A

10001010

Š

带弯音号的拉丁大写字母 S

139

213

8B

10001011

左单书名号

140

214

8C

10001100

Œ

拉丁大写组合 OE

141

215

8D

10001101

142

216

8E

10001110

Ž

带弯音号的拉丁大写字母 z

143

217

8F

10001111

144

220

90

10010000

145

221

91

10010001

左单引号

146

222

92

10010010

右单引号

147

223

93

10010011

左双引号

148

224

94

10010100

右双引号

149

225

95

10010101

150

226

96

10010110

半长破折号

151

227

97

10010111

全长破折号

152

230

98

10011000

˜

小波浪线

153

231

99

10011001

154

232

9A

10011010

š

带弯音号的拉丁小写字母 s

155

233

9B

10011011

右单书名号

156

234

9C

10011100

œ

拉丁小写组合 oe

157

235

9D

10011101

158

236

9E

10011110

ž

带弯音号的拉丁小写字母 z

159

237

9F

10011111

Ÿ

带弯音号的拉丁大写字母 Y

160

240

A0

10100000

 

161

241

A1

10100001

¡

¡

反向感叹号

162

242

A2

10100010

¢

¢

分币符号

163

243

A3

10100011

£

£

英磅符号

164

244

A4

10100100

¤

¤

165

245

A5

10100101

¥

¥

人民币符号

166

246

A6

10100110

¦

¦

167

247

A7

10100111

§

§

章节符号

168

250

A8

10101000

¨

¨

通用货币符号

169

251

A9

10101001

版权符号

170

252

AA

10101010

ª

ª

阴性顺序指示符号

171

253

AB

10101011

«

«

左角引号

172

254

AC

10101100

¬

¬

173

255

AD

10101101

­

­

174

256

AE

10101110

175

257

AF

10101111

¯

¯

176

260

B0

10110000

°

°

温度符号

177

261

B1

10110001

±

±

加/减号

178

262

B2

10110010

²

²

上标 2

179

263

B3

10110011

³

³

上标 3

180

264

B4

10110100

´

´

181

265

B5

10110101

µ

µ

微符号

182

266

B6

10110110

段落符号,pilcrow

183

267

B7

10110111

·

·

中点

184

270

B8

10111000

¸

¸

185

271

B9

10111001

¹

¹

上标 1

186

272

BA

10111010

º

º

阳性顺序指示符

187

273

BB

10111011

»

»

右角引号

188

274

BC

10111100

¼

¼

分数四分之一

189

275

BD

10111101

½

½

分数二分之一

190

276

BE

10111110

¾

¾

191

277

BF

10111111

¿

¿

反向问号

192

300

C0

11000000

À

À

带重音符的大写字母 A

193

301

C1

11000001

Á

Á

带尖锐重音的大写字母 A

194

302

C2

11000010

Â

Â

带音调符号的大写字母 A

195

303

C3

11000011

Ã

Ã

带代字号的大写字母 A

196

304

C4

11000100

Ä

Ä

带元音变音(分音符号)的大写字母 A

197

305

C5

11000101

Å

Å

带铃声的大写字母 A

198

306

C6

11000110

Æ

Æ

大写字母 AE双重元音

199

307

C7

11000111

Ç

Ç

带变音符号的大写字母 C

200

310

C8

11001000

È

È

带重音符的大写字母 E

201

311

C9

11001001

É

É

带尖锐重音的大写字母 E

202

312

CA

11001010

Ê

Ê

带音调符号的大写字母 E

203

313

CB

11001011

Ë

Ë

带元音变音(分音符号)的大写字母 E

204

314

CC

11001100

Ì

Ì

带重音符的大写字母 I

205

315

CD

11001101

Í

Í

带尖锐重音的大写字母 I

206

316

CE

11001110

Î

Î

带音调符号的大写字母 I

207

317

CF

11001111

Ï

Ï

带元音变音(分音符号)的大写字母 I

208

320

D0

11010000

Ð

Ð

209

321

D1

11010001

Ñ

Ñ

带代字号的大写字母 N

210

322

D2

11010010

Ò

Ò

带重音符的大写字母 O

211

323

D3

11010011

Ó

Ó

带尖锐重音的大写字母 O

212

324

D4

11010100

Ô

Ô

带音调符号的大写字母 O

213

325

D5

11010101

Õ

Õ

带代字号的大写字母 O

214

326

D6

11010110

Ö

Ö

带元音变音(分音符号)的大写字母 O

215

327

D7

11010111

×

×

大写字母OE 连字

216

330

D8

11011000

Ø

Ø

带斜杠的大写字母 O

217

331

D9

11011001

Ù

Ù

带重音符的大写字母 U

218

332

DA

11011010

Ú

Ú

带尖锐重音的大写字母 U

219

333

DB

11011011

Û

Û

带音调符号的大写字母 U

220

334

DC

11011100

Ü

Ü

带元音变音(分音符号)的大写字母 U

221

335

DD

11011101

Ý

Ý

带元音变音(分音符号)的大写字母 Y

222

336

DE

11011110

Þ

Þ

223

337

DF

11011111

ß

ß

德语高调小写字母 s

224

340

E0

11100000

à

à

带重音符的小写字母 a

225

341

E1

11100001

á

á

带尖锐重音的小写字母 a

226

342

E2

11100010

â

â

带音调符号的小写字母 a

227

343

E3

11100011

ã

ã

带代字号的小写字母 a

228

344

E4

11100100

ä

ä

带元音变音(分音符号)的小写字母 a

229

345

E5

11100101

å

å

带铃声的小写字母 a

230

346

E6

11100110

æ

æ

小写字母 ae双重元音

231

347

E7

11100111

ç

ç

带变音符号的小写字母 c

232

350

E8

11101000

è

è

带重音符的小写字母 e

233

351

E9

11101001

é

é

带尖锐重音的小写字母 e

234

352

EA

11101010

ê

ê

带音调符号的小写字母 e

235

353

EB

11101011

ë

ë

带元音变音(分音符号)的小写字母 e

236

354

EC

11101100

ì

ì

带重音符的小写字母 i

237

355

ED

11101101

í

í

带尖锐重音的小写字母 i

238

356

EE

11101110

î

î

带音调符号的小写字母 i

239

357

EF

11101111

ï

ï

带元音变音(分音符号)的小写字母 i

240

360

F0

11110000

ð

ð

241

361

F1

11110001

ñ

ñ

带代字号的小写字母 n

242

362

F2

11110010

ò

ò

带重音符的小写字母 o

243

363

F3

11110011

ó

ó

带尖锐重音的小写字母 o

244

364

F4

11110100

ô

ô

带音调符号的小写字母 o

245

365

F5

11110101

õ

õ

带代字号的小写字母 o

246

366

F6

11110110

ö

ö

带元音变音(分音符号)的小写字母 o

247

367

F7

11110111

÷

÷

小写字母 oe连字

248

370

F8

11111000

ø

ø

带斜杠的小写字母 o

249

371

F9

11111001

ù

ù

带重音符的小写字母 u

250

372

FA

11111010

ú

ú

带尖锐重音的小写字母 u

251

373

FB

11111011

û

û

带音调符号的小写字母 u

252

374

FC

11111100

ü

ü

带元音变音(分音符号)的小写字母 u

253

375

FD

11111101

ý

ý

带元音变音(分音符号)的小写字母 y2

254

376

FE

11111110

þ

þ

255

377

FF

11111111

ÿ

ÿ

重点

  1. \x00是ASCII表中第一项,C语言中的字符串结束符
  2. \t、\x09,表示tab字符
  3. \r\n是\x0d\x0a
  4. \x30~\x39 字符0~9,\x31是字符1
  5. \x41对应十进制65,表示A
  6. \x61对应十进制97,表示a

注意:这里的1指定是字符1,不是数字1

UTF-8、GBK都兼容了ASCII

'a\x09b\x0d\x0ac \x31\x41\x61' # 表示什么?
'A' > 'a' # 谁大?

Bytes初始化

  • bytes() 空bytes
  • bytes(int) 指定字节的bytes,被0填充
  • bytes(iterable_of_ints) -> bytes [0,255]的int组成的可迭代对象
  • bytes(string, encoding[, errors]) -> bytes 等价于string.encode()
  • bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer 从一个字节序列或者buffer复制出一个新的不可变的bytes对象
  • 使用b前缀定义
    • 只允许基本ASCII使用字符形式b'abc9'
    • 使用16进制转义表示b"\x41\x61"

bytes类型和str类型类似,都是不可变类型,操作方法类似。

print(b'abcd'[2]) # 返回int,指定是本字节对应的十进制数
x = b'\t\x09'
print(x, len(x))
y = br'\t\x09'
print(y, len(y))

bytearray初始化

  • bytearray() 空bytearray
  • bytearray(int) 指定字节的bytearray,被0填充
  • bytearray(iterable_of_ints) -> bytearray [0,255]的int组成的可迭代对象
  • bytearray(string, encoding[, errors]) -> bytearray 近似string.encode(),不过返回可变对象
  • bytearray(bytes_or_buffer) 从一个字节序列或者buffer复制出一个新的可变的bytearray对象

b前缀表示的是bytes,不是bytearray类型

由于bytearray类型是可变数组,所以,类似列表。

  • append(int) 尾部追加一个元素

  • insert(index, int) 在指定索引位置插入元素

  • extend(iterable_of_ints) 将一个可迭代的整数集合追加到当前bytearray

  • pop(index=-1) 从指定索引上移除元素,默认从尾部移除

  • remove(value) 找到第一个value移除,找不到抛ValueError异常

  • 注意:上述方法若需要使用int类型,值在[0, 255]

  • clear() 清空bytearray

  • reverse() 翻转bytearray,就地修改

    b = bytearray()
    b.append(97) b.append(99) b.insert(1,98) b.extend([65,66,67])
    b.remove(66) b.pop()
    b.reverse()
    print(b) # 输出什么
    b.clear()

线性结构特征:

  • 可迭代 for … in
  • 有长度,通过len(x)获取,容器
  • 通过整数下标可以访问元素。正索引、负索引
    • 可以切片

已经学习过的线性结构:list、tuple、str、bytes、bytearray

切片

sequence[start:stop]
sequence[start:stop:step]
  • 通过给定的索引区间获得线性结构的一部分数据

  • start、stop、step为整数,可以是正整数、负整数、零

  • start为0时,可以省略

  • stop为末尾时,可以省略

  • step为1时,可以省略

  • 切片时,索引超过上界(右边界),就取到末尾;超过下界(左边界),取到开头

    x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(x[:])
    print(x[:-1]) #
    print(x[0:])
    print(x[3:])
    print(x[3:-1]) #
    print(x[9:])
    print(x[:9])
    print(x[9:-1])
    print(x[:100])
    print(x[-100:])
    print(x[4:-2])
    print(x[-4:-2])
    print('0123456789'[-4:8])
    print(b'0123456789'[-4:8])
    print(bytearray(b'0123456789')[-10:5])

    步长

    x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(x[::])
    print(x[::2])
    print(x[2:8:3])
    print(x[:9:3])
    print(x[1::3])
    print(x[-10:8:2])

    起止和方向

    x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(x[-10:])
    print(x[-5:6])
    print(x[-5:-6])
    print(x[6:5])
    print(x[5:5])
    print(x[1:9:-2])
    print(x[::-2])
    print(x[8::-2]) # 表示索引8到左尽头,包含0
    print(x[8:0:-2]) # 表示索引8到索引1,不含0
    print(x[8:-10:2])
    print(x[8:-10:-2])
    print(x[-5:4:-1])
    print(x[-5:5:-1])

在序列上使用切片[start:stop],子区间索引范围[start, stop),相当于从start开始指向stop的方向上获取数据

默认step为1,表示向右;步长为负数,表示向左

如果子区间方向和步长方向不一致,直接返回当前类型的"空对象"

如果子区间方向和步长方向一致,则从起点间隔步长取值

内建函数

函数签名

说明

id

id(object)

CPython中返回对象的内存地址 可以用来判断是不是同一个对象

# 使用id看地址,要注意地址回收复用问题
print(id([1,2,3]))
print(id([4,5,6,7]))
# 上下两句可能内存地址一样,但是上面那个[1,2,3]没有意义,因为它用完之后,引用计数为0了,没
人能再次访问到,释放了内存
# 如果2个存在在内存中的对象,地址一样一定是同一个对象

本质

x = [0, 1, 2] y = x[:]
print(x, y)
print(id(x), id(y))
x[0] = 100
print(x, y) x = [[1]]
y = x[:]
print(x, y)
print(x == y)
print(id(x), id(y), x is y) x[0][0] = 100
print(x, y)
print(x == y)
print(x is y) x[0] = 200
print(x == y) # ?
print(x, y)

上例可知,实际上切片后得到一个全新的对象。 [:] 或 [::] 相当于copy方法。

99乘法表

if __name__ == '__main__':
    for x in range(1,10):
        for y in range(1,x+1):
            print("{} * {} = {:<10}".format(x,y,x*y), end='' if x>y else '\n')

100奇数和

if __name__ == '__main__':
    sum=0
    for i in range(1,100,2):
        sum+=i
    print(sum)
#或者
print(sum(range(1,100,2)))