当前位置: 首页 > 面试题库 >

乘法运算符应用于列表(数据结构)

百里沛
2023-03-14
问题内容

我正在阅读《如何像计算机科学家一样思考》,这是“
Python编程”的介绍性文字。

我想弄清楚将乘法运算符(*)应用于列表时的行为。

考虑函数 make_matrix

def make_matrix(rows, columns):
"""
  >>> make_html" target="_blank">matrix(4, 2)
  [[0, 0], [0, 0], [0, 0], [0, 0]]
  >>> m = make_matrix(4, 2)
  >>> m[1][1] = 7
  >>> m
  [[0, 0], [0, 7], [0, 0], [0, 0]]
"""
return [[0] * columns] * rows

实际输出为

[[0, 7], [0, 7], [0, 7], [0, 7]]

make_matrix 的正确版本 是:

def make_matrix(rows, columns):
"""
  >>> make_matrix(3, 5)
  [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
  >>> make_matrix(4, 2)
  [[0, 0], [0, 0], [0, 0], [0, 0]]
  >>> m = make_matrix(4, 2)
  >>> m[1][1] = 7
  >>> m
  [[0, 0], [0, 7], [0, 0], [0, 0]]
"""
matrix = []
for row in range(rows):
    matrix += [[0] * columns]
return matrix

make_matrix的 第一个版本失败的原因(如9.8中的说明)是

…每行是其他行的别名…

我想知道为什么

[[0] * columns] * rows

原因 …每行是其他行的别名…

但不是

[[0] * columns]

即为什么[0]一行中的每个不是其他行元素的别名。


问题答案:

python中的所有对象都是对象,除非明确要求这样做,否则python永远不会复制。

当你做

innerList = [0] * 10

您将创建一个包含10个元素的列表, 所有int 0 元素 都引用同一个 对象

由于整数对象是 不可变的 ,因此当您执行

innerList[1] = 15

您正在更改列表的第二个元素,使其引用另一个整数 15 。由于 int 对象的不变性,这总是可行的。

这就是为什么

outerList = innerList * 5

将创建一个list包含5个元素的对象,每个元素都与上面 相同innerList。但是由于list对象是 可变的

outerList[2].append('something')

是相同的:

innerList.append('something')

因为它们是对
同一list对象的两个引用。因此,该元素以该single结尾list。它似乎是重复的,但事实是只有一个list对象,并且有许多引用。

相反,如果您这样做

outerList[1] = outerList[1] + ['something']

在这里,您将 创建 另一个 list对象+与列表一起使用是一个显式副本),并将对该 对象
的引用分配到的第二个位置outerList。如果以这种方式“添加”元素(不是真正地添加,而是创建另一个列表),innerList则不会受到影响。



 类似资料:
  • 问题内容: 在Python中,如果将对象列表乘以整数,则会得到对该对象的引用列表,例如: 如果我想要的行为是创建原始对象的副本列表(例如,通过“ copy.copy()”方法或某种标准创建的副本),是否有一种 优雅的 方法可以 使用相同的乘法运算符 来做到这一点?我应该坚持列表理解之类的吗? 任何版本的Python都可以。 问题答案: 序列上的乘法运算符表示项目的重复-不会创建项目的副本(浅副本或

  • 本文向大家介绍Javascript数据结构与算法之列表详解,包括了Javascript数据结构与算法之列表详解的使用技巧和注意事项,需要的朋友参考一下 前言:在日常生活中,人们经常要使用列表,比如我们有时候要去购物时,为了购物时东西要买全,我们可以在去之前,列下要买的东西,这就要用的列表了,或者我们小时候上学那段时间,每次考完试后,学校都会列出这次考试成绩前十名的同学的排名及成绩单,等等这些都是列

  • 单链表 单链表就地翻转 递归算法: void reverse(struct list_node *head) { if(NULL == head || NULL == head->next) return; reverse1(head->next); head->next->next = head; head->next = NULL; } 非递归算

  • 也称为跳跃表(Skip List)是一种基于【有序链表】的扩展,简称【跳表】。 存储的数据是有序的。 所以跳表对标的是平衡树(AVL Tree)和二分查找,是一种插入/删除/搜索都是O(log n)的数据结构。 它最大的优势是原理简单、容易实现、方便扩展、效率更高。 定义 增加了向前指针的链表叫作跳表。跳表全称叫做跳跃表,简称跳表。 跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链

  • 链表的概念 逻辑结构上一个挨一个的数据,在实际存储时,并没有像顺序表(数组)那样也相互紧挨着。恰恰相反,数据随机分布在内存中的各个位置,这种存储结构称为线性表的链式存储。 每个元素本身由两部分组成: 本身的信息,称为 数据域 指向直接后继的指针,称为 指针域 内存分布 数据是连续存储的,一个挨着一个,连续的。链表是存储单元不一定是连续的, 主要分类 单向链表 循环链表 双向链表 双向循环链表 单向

  • 我从这个URL刮取了这个表: "https://www.patriotsoftware.com/blog/accounting/average-cost-living-by-state/" 看起来像这样: 然后我编写了这个函数来帮助我将字符串转换成整数: 当我只将函数应用于一列时,它就会工作。我在这里找到了关于在多个列上使用的答案:如何将函数应用于多个列 但我下面的代码不起作用,也不会产生错误: