Python:复制列表,禁止函数修改列表(副本,切片表示法[:])(篇1:浅拷贝)

本篇博客主要讲的是浅拷贝方法,只适用于一维数组中,在多维数组中使用时如果修改复制的数组,原数组也会随之改变。下篇博客python中对列表的复制操作(浅拷贝与深拷贝)讲解浅拷贝与深拷贝之间的区别和用法。

复制列表:

我们经常需要根据既有列表创建全新的列表。下面来介绍复制列表的工作原理,以及复制列表可提供极大帮助的一种情形。

要复制列表,可创建一个包含整个列表的切片,方法是同时省略起始索引和终止索引([:])。这让Python 创建一个始于第一个元素、终止于最后一个元素的切片,即整个列表的副本。

例如,假设有一个列表包含你最喜欢的四种食品,而你想再创建一个列表,并在其中包含一位朋友喜欢的所有食品。不过,你喜欢的食品,这位朋友也都喜欢,因此可通过复制来创建这个列表:

输入一:


```python
my_foods =['pizza','falafel','carrot cake']
friend_foods = my_foods[:]

print("My favorite foods are:")
print(my_foods)

print("\nMy friend's favorite foods are:")
print(friend_foods)

首先,创建一个你喜欢的食品列表,名为my_foods。然后创建一个名为friend_foods的新列表。在不指定任何索引的情况下从列表my foods中提取一个切片,从而创建这个列表的副本,并将该副本赋给变量 friend_foods。打印这两个列表后,我们发现其包含的食品相同:

结果一:

My favorite foods are:
['pizza', 'falafel', 'carrot cake']

My friend's favorite foods are:
['pizza', 'falafel', 'carrot cake']

为核实确实有两个列表,下面在每个列表中都添加一种食品,并核实每个列表都记录了相应人员喜欢的食品:

输入二:

# my_foods = ['pizza','falafel','carrot cake']
# friend_foods = my_foods[:]

my_foods.append('cannoli') # 新增
friend_foods.append('ice cream') # 新增

# print("My favorite foods are:")
# print(my_foods)

# print("\nMy friend's favorite foods are:")
# print(friend_foods)

与前一个示例一样,首先将my_foods的元素复制到新列表friend_foods中。接下来,在每个列表中都添加一种食品:在列表 my_foods 中添加’cannoli’,而在 friend_foods中添加’ice cream’。最后,打印这两个列表,核实这两种食品分别包含在正确的列表中。

结果二:

My favorite foods are: # 1
['pizza', 'falafel', 'carrot cake', 'cannoli']

My friend's favorite foods are: # 2
['pizza', 'falafel', 'carrot cake', 'ice cream']

1处的输出表明,’cannoli’包含在你喜欢的食品列表中,而’ice cream‘不在。2处的输出表明,'ice cream’包含在你朋友喜欢的食品列表中,而’cannoli‘不在。如果只是将my_foods赋给friend foods,就不能得到两个列表。例如,下面演示了在不使用切片的情况下复制列表的情况:

输入三:

# my_foods = ['pizza','falafel','carrot cake']
# friend_foods = my_foods[:]

# 这行不通  
# 1
friend_foods = my_foods

# my_foods.append('cannoli') # 新增
# friend_foods.append('ice cream') # 新增

# print("My favorite foods are:")
# print(my_foods)

# print("\nMy friend's favorite foods are:")
# print(friend_foods)

这里将my_foods 赋给friend foods,而不是将my_foods的副本赋给friend foods(见1)。这种语法实际上是让 Python将新变量friend_foods关联到已与my_foods相关联的列表,因此这两个变量指向同一个列表。有鉴于此,当我们将“cannoli’添加到 my_foods 中时,它也将出现在friend_foods 中。同样,虽然’ice cream’好像只被加入到了friend_foods中,但它也将出现在这两个列表中。
输出表明,两个列表是相同的,这并非我们想要的结果:

结果三:

My favorite foods are:
['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']

My friend's favorite foods are:
['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']

注意:暂时不要考虑这个示例中的细节。当试图使用列表的副本时结果出乎意料,基本上都要
确认你是否像第一个示例那样使用切片复制了列表。

禁止函数修改列表(刷题时经常会遇到这种问题):

示例:

def print_models(unprinted_designs, completed_models):
	'''
	模拟打印每个设计,直到没有未打印的设计为止。
	打印每个设计后,都将其移到列表completed_models中。
	'''
	while unprinted designs:
		current_design = unprinted_designs.pop()
		print(f"Printing model: {current_design}")
		completed models.append(current_design)
		
def show_completed_models(completed_models):
	'''显示打印好的所有模型。'''
	print("\nThe following models have been printed:")
	for completed_model in completed_models:
		print(completed_model)
		
unprinted_designs = ['phone case', 'robot pendant', 'dodecahedron']
completed_models = []

print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)

有时候,需要禁止函数修改列表。例如,像示列那样,你有一个未打印的设计列表,并编写了一个函数将这些设计移到打印好的模型列表中。你可能会做出这样的决定:即便打印好了所有设计,也要保留原来的未打印的设计列表,以供备案。但由于你将所有的设计都移出了 unprinted_designs,这个列表变成了空的,原来的列表没有了。为解决这个问题,可向函数传递列表的副本而非原件。这样,函数所做的任何修改都只影响副本,而原件丝毫不受影响。
要将列表的副本传递给函数,可以像下面这样做:

function_name(list_name[:])

切片表示法[:]创建列表的副本。在 示列中,如果不想清空未打印的设计列表,可像下面这样调用 print_models():

print_models(unprinted_designs[:], completed_models)

这样函数print_models()依然能够完成工作,因为它获得了所有未打印的设计的名称,但使用的是列表unprinted_designs的副本,而不是列表unprinted_designs本身。像以前一样,列表completed_models也将包含打印好的模型的名称,但函数所做的修改不会影响到列表unprinted_designs。
虽然向函数传递列表的副本可保留原始列表的内容,但除非有充分的理由,否则还是应该将原始列表传递给函数。这是因为让函数使用现成的列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不染_是非

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值