你经常会发现,向函数传递列表很有用,这种列表包含的可能是名字、数字或更复杂的对象(如字典)。将列表传递给函数后,函数就能直接访问其内容。下面使用函数来提高处理列表的效率。

假设有一个前女友列表,我们要怀念其中的每位女友。下面的示例将一个名字列表传递给一个名为regret_persons()的函数,这个函数怀念了列表中的每位前女友:

  1. # regret.py
  2. def regret_persons(lst):
  3. for name in lst:
  4. print(f"虽然分手了,但我还是珍惜曾经与{name}在一起的日子😂!")
  5. names = ['Tang', 'Yang', 'Zhao']
  6. regret_persons(names)

我们将regret_persons()定义成接受一个名字列表,并将其存储在形参names中。这个函数遍历收到的列表,并对其中的每位用户都打印一条问候语。我们定义了一个用户列表——names,然后调用regret_persons(),并将这个列表传递给它:


虽然分手了,但我还是珍惜曾经与Tang在一起的日子😂!
虽然分手了,但我还是珍惜曾经与Yang在一起的日子😂!
虽然分手了,但我还是珍惜曾经与Zhao在一起的日子😂!


输出完全符合预期,每位前女友都看到了一条个性化的说辞。每当你要怀念一组前女友时,都可调用这个函数。

8.4.1 在函数中修改列表

将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效地处理大量的数据。

假设我们有一家奶茶店,我们把用户的订单放进一个列表orders中,然后每做好一杯茶,就把它从订单列表中移到完成列表finished中:

  1. def make_tea(orders):
  2. finished = []
  3. while orders:
  4. tea = orders.pop()
  5. print(f"{tea} is being made...")
  6. print(f"{tea} is done!")
  7. finished.append(tea)
  8. return finished
  9. orders = ['奶茶', '乌龙茶', '果茶']
  10. print('完成订单之前的orders列表:', orders)
  11. finished = make_tea(orders)
  12. print('完成订单之后的orders列表:', orders)
  13. print('返回的finished列表:', finished)

输出:


完成订单之前的orders列表: [‘奶茶’, ‘乌龙茶’, ‘果茶’]
果茶 is being made…
果茶 is done!
乌龙茶 is being made…
乌龙茶 is done!
奶茶 is being made…
奶茶 is done!
完成订单之后的orders列表: []
返回的finished列表: [‘果茶’, ‘乌龙茶’, ‘奶茶’]


8.4.2 禁止函数修改列表

有时候,需要禁止函数修改列表。例如,假设像前一个示例那样,你有一个订单列表,并编写了一个将这些订单移到制作好的列表列表中的函数。你可能会做出这样的决定:即便制作完所有的茶后,也要保留原来的订单列表列表,以供备案。但由于你将所有的订单都移出了orders,这个列表变成了空的,原来的列表没有了。为解决这个问题,可向函数传递列表的副本而不是原件;这样函数所做的任何修改都只影响副本,而丝毫不影响原件。

要将列表的副本传递给函数,可以像下面这样做:

  1. function_name(list_name[:])

切片表示法[:]创建列表的副本。在make_tea()中,如果不想清空订单列表,可像下面这样调用make_tea():

  1. finished = make_tea(orders[:])

这样函数make_tea()依然能够完成其工作,因为它获得了所有订单的名称,但它使用的是列表orders的副本,而不是列表orders本身。像以前一样,列表finished也将包含制作完的茶的名称,但函数所做的修改不会影响到列表orders。

虽然向函数传递列表的副本可保留原始列表的内容,但除非有充分的理由需要传递副本,否则还是应该将原始列表传递给函数,因为让函数使用现成列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。