文章目录

  • 2.5 对序列使用 +和 ×
    • 建立由列表组成的列表
  • 2.6序列的增量赋值(+=和×=)
    • 关于 +=的谜题
      • 补充:extend()方法和+有什么区别呢?
  • 2.7 list.sort方法和内置函数sorted(排序)
  • 2.8 用bisect来管理已排序的序列
    • 2.8.2用bisect.insort插入元素
  • 2.9 当列表不是首选时
    • 2.9.1 数组
    • 2.9.2内存视图
    • 2.9.3 NumPy和SciPy
    • 2.9.4 双向队列和其他的形式的队列

2.5 对序列使用 +和 ×

l = [1,2,3]
print(id(l))
t= l*5
print(id(t))

结果如图:

  • 总结:+ 和 * 都遵循这个规律,不修改原有的操作对象,而是构建一个全新的序列。
  • 注意:如果a*n 这个语句中,序列a里面的元素是对其他可变对象的引用的话,这个结果可能会出乎意料。比如,你想用my_list = [[]]*3 来初始化一个由列表组成的列表,但是你得到的列表里面包含的3个元素其实是3个引用,而且这3个引用指向同一个列表。这显然不是想要的。

建立由列表组成的列表

正确的方式1:

board = [['_'] * 3 for i in range(3)]
print(board)
board[1][2] = 'X'
print(board)

结果如图:

错误的方式1:含有3个指向同一对象的引用的列表是毫无用处的。

weird_board = [['_']*3] *3
print(weird_board)
weird_board[1][2] = '0'
print(weird_board)

结果如图:

错误的方式2:
这个和上一个错误的本质是一样的

row = [' _ ']*3
board = []
for i in range(3):board.append(row)
print(board)
board[1][2] ='0'
print(board)

结果如图:

正确的方式2:
这里的等同于正确的方式1

board = []
for i in range(3):row = ['_']*3 # 每次迭代中都新建了一个列表,作为新的一行添加到boardboard.append(row)
print(board)
board[1][2] ='0'
print(board)

结果如图:

2.6序列的增量赋值(+=和×=)

增量赋值运算符+=和*=的表现取决于它们的第一个操作对象,本次的就集中讨论(+=)。对其他的增量运算符也同样适用。
+=背后的特殊方法是__iadd__(用于‘就地加法’),所谓的‘就地’理解为:不创建新的对象,而是将原来的对象重新赋值。如果一个类没有实现这个方法的话,python会退一步调用__add__.
我们考虑下面这个简单的表达式:

  • a+=b

  • 讨论:
    (1).若a实现了__iadd__方法,就会调用这个方法。同时对于可变序列(list,bytearray和array.array)来说,a会就地变动了,就像调用了a.extend(b)一样
    (2).若a没有实现__iadd__方法,a+=b这个表达式的效果就会根a=a+b一样了;首先计算a+b,得到一个新的对象,然后赋值给a。

  • 总结:
    在这个表达式中,变量名会不会被关联到新的可变对象,完全取决于这个类型有没有实现__iadd__这个方法。总的来说,可变序列一般都实现了__iadd__这个方法,因此+=是就地加法。而不可变序列没有实现这个方法,就会像步骤(2)那样操作。后者相对应的是__imul__.

例子:

l = [1, 2, 3]
print('before id(l):',id(l))
l *=2
print(l)
print('after id(l):',id(l))
t = (1, 2, 3)
print('before id(t):',id(t))
t *= 2
print('after id(t):',id(t)) # 运用增量惩罚后,新的元组被创建

结果如图:

关于 +=的谜题

t = (1, 2, [30,40])
t[2] += [50, 60]
print(t)


结果:t[2]被改动了,但是也有异常出现。但是我们可以写成t[2].extend([50,60])来避免这个异常。

教训:

  • 不要把可变对象放在元组里面
  • 增量赋值不是一个原子操。它虽然会抛出异常,但是还是完成了操作
  • 查看python的字节码并不难,它对我们了解代码背后的运行机制很有帮助。

补充:extend()方法和+有什么区别呢?

a = [1,2,3]
b = [4,5,6]
c = a+bd = [1,2,3]
e = [4,5,6]
d.extend(e)

结果如图:

结论:
结果是一样的,但是+号生成的是一个新的对象,而extend则是在原地的修改对象。
extend()的运算效率比+更高。但是, d.extend(e) 的返回结果是None,而不是合并后的序列。d序列是合并后的序列。
c返回的是新的序列。

2.7 list.sort方法和内置函数sorted(排序)

list.sort方法会就地排序列表,这也是这个方法返回None的原因,按照python的惯例:如果一个函数或者方法对对象进行的是就地改动,那它就应该返回None.
与list.sort相反的是sorted,它会新建一个列表作为返回值。这个方法可以接受人和形式的可迭代对象作为参数,甚至包括不可变序列或者生成器,但是它总是返回一个列表。
不管list.sort或者sorted函数,都有两个参数,reverse和key

  • reverse:默认为False,就是升序排列,True为降序排列
  • key:对一些字符串进行排序的时候,key=str.lower来实现忽略大小写的排序;key=len来显示根据字符串长度来排序。

例子:

fruits = ['grape', 'raspberry', 'apple', 'banana']
print("未排序:", fruits)
print(sorted(fruits))
print("sorted:", fruits)
print(sorted(fruits,reverse=True))
print(sorted(fruits,key=len))
print(sorted(fruits,key=len,reverse=True))
print(fruits)
fruits.sort()
print(fruits)

结果如下:

可以发现,直到执行了fruits.sort方法,fruits本身才发生了变化。
排好序的序列可以用来进行快速搜索,而标准库的bisect模块给我们提供了二分查找算法。

2.8 用bisect来管理已排序的序列

bisect模块包含类 两个主要函数,bisect和insert,两个函数都利用二分查找算法在有序序列中查找或者插入元素。
在有序序列中用bisect查找某个元素的插入位置。
例子1:

import bisect
import sys
HAYSTACK = [1, 4, 5, 6, 8, 12, 15, 20, 21, 23, 23, 26, 29, 30]
NEEDLES = [0, 1, 2, 5, 8, 10, 22, 23, 29, 30, 31]
ROW_FMT = '{0:2d} @ {1:2d}   {2}{0:2d}'
def demo(bisect_fn):for needle in reversed(NEEDLES):position = bisect_fn(HAYSTACK, needle) #返回插入的位置offset = position * '  |'print(ROW_FMT.format(needle, position, offset))# return bisect_fnif __name__ == '__main__':if sys.argv[-1] == 'left':bisect_fn = bisect.bisect_left  #当碰到相等的元素的时候,会放在它左边(前边) else:bisect_fn = bisect.bisect #或者是bisect_fn = bisect.bisect_right,当碰到相等的元素的时候,会放在它的右边(后边)print('DEMO:', bisect_fn.__name__)print('haystack ->', ' '.join('%2d' % n for n in HAYSTACK))demo(bisect_fn)

例子2:根据分数找到它对应的成绩

import bisect
def grade(score,breakpoint = [60,70,80,90],grades='FDCBA'):i = bisect.bisect(breakpoint,score) # 返回i,匹配gradesreturn grades[i]
t = [grade(score) for score in [33,99,77,70,89,91,10]]
print(t)

输出:

['F', 'A', 'C', 'C', 'B', 'A', 'F']

2.8.2用bisect.insort插入元素

insort(seq,item) 把变量item插入到序列seq中,并能保持seq的升序顺序。

import bisect
import random
SIZE = 7
random.seed(1729)
my_list = []
for i in range(SIZE):new_item = random.randrange(SIZE*2)bisect.insort(my_list, new_item)print('%2d ->' % new_item, my_list)

结果如图:

  • 补充: %和format的区别

参考:https://www.cnblogs.com/zhaopanpan/p/8875765.html (%和format的区别)

2.9 当列表不是首选时

2.9.1 数组

2.9.2内存视图

2.9.3 NumPy和SciPy

科学计算有关的算法

窥探NumPy二维数组的基本操作

import numpy
a = numpy.arange(12)
print(a)
print(type(a))
print(a.shape)#查看维度
a.shape = 3, 4 #变成二维的
print(a)
print(a[2])
print(a[2, 1])
print(a[:, 1])
t = a.transpose() #行列交换,得到**新的数组**
print(t)

结果如下:

可以发现t是一个新的数组。

2.9.4 双向队列和其他的形式的队列

补充:markdown生成目录方式,在开头输出[toc]

python (第二章)数据结构相关推荐

  1. 简学Python第二章__巧学数据结构文件操作

    Python第二章__巧学数据结构文件操作 欢迎加入Linux_Python学习群  群号:478616847 目录: 列表 元祖 索引 字典 序列 文件操作 编码与文件方法 本站开始将引入一个新的概 ...

  2. Python第二章相关知识补充

    经过这周的Python课堂,第二章的知识点可以说是被彻头彻尾地讲了一下,所以我在此将上一篇发布的博客内容也加以完善. 2.1.3 列表元素的删除 在学习了列表元素的增加以后,删除列表元素的方法也可以进 ...

  3. Python 第二章-列表和元组

    第二章-列表和元组 2.0       在Python中,最基本的数据结构是序列(sequence).序列中的每个元素被分配一个序列号-即元素的位置, 也称为索引.第一个索引是0,第二个是1,以此类推 ...

  4. Python第二章课后总结

    最近的教学进度进入了第二章,这一章主要讲述了Python中常用的序列结构:列表.元组.字典.字符串.集合等.通过这些序列的学习在今后可以有效实现一些复杂的数据结构和模拟基本操作.那么接下来就给出我个人 ...

  5. 第二章 数据结构 【完结】

    栈那节表达式求值,并查集食物链还没做 堆,哈希表不熟,比赛的时候也很少遇到,故没有经常的练习. 目录 单链表[静态] 双链表[静态] 栈 队列 单调栈 单调队列 KMP Trie 并查集 堆 哈希表 ...

  6. 2的32次方减1用python,第二章python入门

    2.1 环境的安装 解释器:py2.py3 开发工具:pycharm 2.2编码 2.2.1编码基础 初识编码 ASCII码 :英文 8位表示一个东西 2**8 ,8位等于一个字节 Unicode:( ...

  7. 斗地主AI算法——第二章の数据结构

    上一章我们已经确立了基本的业务逻辑处理流程.从本章开始,我们便进入开发阶段. 首先就是明确我们都需要哪些数据,且它们以怎样的形式存储. 首先从上一章反复提到的手牌权值结构说起,也就是F()的返回值,他 ...

  8. 流畅的python第二章, 列表和元组和数组

    概述 这一张标题其实是序列构成的数组,其实也无所谓了, 站在小白的角度来讲,就是讲了讲列表, 元组, 数组的一些用法,这里站在我的角度上说说我的看法好了. 目录 列表推导,原则和一些问题, 和一些扩展 ...

  9. machine learn in python 第二章2.1.1

    1大约 sklearn.datasets from sklearn.datasets import load_iris import numpy as np data = load_iris() da ...

最新文章

  1. DataRabbit 轻量的数据访问框架(13)--DataRabbit 3.0 ORM性能大幅度提升!
  2. android中常用的下拉刷新加载更多_如何设计“加载流程”
  3. xfce4的主题PenOSmaster使用xfce4-screenshooter截屏会全屏幕都是紫色的问题-解决方案
  4. 排错“未能封送类型,因为嵌入数组实例的长度与布局中声明的长度不匹配”...
  5. Python的bool类型
  6. IO复用\阻塞IO\非阻塞IO\同步IO\异步IO
  7. Ags 9.3 文档逐步上线
  8. [Ext JS 7]7.4 样式主题(Theme)
  9. 怎么在html mui中找到下拉刷新,HelloMUI例子中的下拉刷新
  10. extjs Ext.XTemplate
  11. Java设计模式应用——工厂模式
  12. NPDP第四章 文化、组织与团队
  13. 批量下载css文件中的图片
  14. 怎么看台式计算机内存条,内存条型号,详细教您怎么查看内存条型号
  15. 推荐几款拍证件照的小程序
  16. 求指点如何使用dynami类型的变量
  17. 测试最常见的21个故障模型
  18. Module not found: Error: Can‘t resolve ‘vue‘ in ‘C:\Users\86135\Desktop\webpack-vue\Vue\src\js‘
  19. #私藏项目实操分享#Python爬虫实战,requests+xpath模块,Python实现爬取豆瓣影评
  20. 游戏平台搭建之安卓资源优化

热门文章

  1. mysql设置token有效期_记住我 token保存到数据库
  2. serialversionuid的作用_为什么阿里Java规约要求谨慎修改serialVersionUID字段
  3. C++标准库与Java基础类对照表
  4. face alignment by 3000 fps系列学习总结
  5. 漫游飞行_手机“飞行模式”为何没被淘汰?内行人坦言:其实是你不会用!
  6. js高级编程_这位设计师用Processing把创意编程玩到了极致!
  7. javascript 在对象中使用 定时器_如何使用JavaScript 面向对象编程
  8. RE validation in Java EE
  9. 2019 GDUT Rating Contest II : A. Taming the Herd
  10. 洛谷 题解 P2312 【解方程】