跳转至

Python参数传递 - 快递小包裹!

1. 什么是参数传递?让我们一起想象...

想象你是一个快递员!当你送快递时,有时送的是一张照片(不能改变的东西),有时送的是一个玩具箱(可以往里面加东西)。Python的参数传递就像送快递: - 有些东西送过去后不能改变(数字、字符串) - 有些东西送过去后可以改变(列表、字典)

2. 让我们玩个快递游戏!

2.1. 送照片 - 不可变参数

def change_number(num):
    print(f"收到的数字是:{num}")
    num = 100  # 试图改变数字
    print(f"尝试改变后:{num}")

# 寄出一个数字
my_number = 42
print(f"原始数字是:{my_number}")
change_number(my_number)
print(f"送回来的数字还是:{my_number}")  # 数字没有改变!

2.2. 送玩具箱 - 可变参数

def add_toy(toy_box):
    print(f"收到的玩具箱里有:{toy_box}")
    toy_box.append("小熊")  # 往玩具箱里加东西
    print(f"加了新玩具后:{toy_box}")

# 准备一个玩具箱
my_toys = ["积木", "小车"]
print(f"原始玩具箱:{my_toys}")
add_toy(my_toys)
print(f"送回来的玩具箱:{my_toys}")  # 玩具箱里多了东西!

3. 不同类型的快递

3.1. 不能改变的快递(不可变类型)

def try_change_values(number, text, point):
    print("试图改变收到的快递...")
    number = 200
    text = "新文字"
    point = (3, 3)
    print(f"在函数里:number={number}, text={text}, point={point}")

# 寄出不同类型的快递
my_number = 100
my_text = "你好"
my_point = (1, 1)

try_change_values(my_number, my_text, my_point)
print(f"原来的东西都没变:")
print(f"number={my_number}, text={my_text}, point={my_point}")

3.2. 可以改变的快递(可变类型)

def modify_collections(list_box, dict_box, set_box):
    print("修改收到的快递...")
    list_box.append("新玩具")
    dict_box["新key"] = "新value"
    set_box.add("新元素")
    print(f"在函数里改变后:")
    print(f"list_box={list_box}")
    print(f"dict_box={dict_box}")
    print(f"set_box={set_box}")

# 准备可以改变的快递
my_list = ["旧玩具"]
my_dict = {"旧key": "旧value"}
my_set = {"旧元素"}

modify_collections(my_list, my_dict, my_set)
print(f"快递送回来后都变了:")
print(f"my_list={my_list}")
print(f"my_dict={my_dict}")
print(f"my_set={my_set}")

4. 特殊的快递方式

4.1. 复制一份再送(使用切片或copy)

def safe_add_toy(toy_box):
    # 复制一份玩具箱
    new_box = toy_box.copy()
    new_box.append("新玩具")
    return new_box

# 原始玩具箱
my_toys = ["玩具1", "玩具2"]
print(f"原始玩具箱:{my_toys}")

# 获得一个新的玩具箱
new_toys = safe_add_toy(my_toys)
print(f"原来的玩具箱:{my_toys}")
print(f"新的玩具箱:{new_toys}")

4.2. 深度复制(使用deepcopy)

from copy import deepcopy

def modify_nested_box(box):
    # 深度复制一个盒子
    new_box = deepcopy(box)
    new_box["外层"]["里层"].append("新玩具")
    return new_box

# 准备一个有内外层的盒子
my_box = {
    "外层": {
        "里层": ["玩具1", "玩具2"]
    }
}

print(f"原始盒子:{my_box}")
new_box = modify_nested_box(my_box)
print(f"原来的盒子:{my_box}")
print(f"新的盒子:{new_box}")

5. 有趣的例子

5.1. 魔法糖果盒

def magic_candy_box(candies, new_candy):
    print(f"魔法糖果盒里现在有:{candies}")
    if isinstance(new_candy, str):
        # 如果是字符串(不可变),变成大写也不会影响原来的
        new_candy = new_candy.upper()
        candies.append(new_candy)
    print(f"加入新糖果后:{candies}")

# 准备糖果盒
my_candies = ["巧克力", "棒棒糖"]
new_candy = "果冻"

print(f"原始糖果盒:{my_candies}")
magic_candy_box(my_candies, new_candy)
print(f"送回的糖果盒:{my_candies}")
print(f"原始新糖果还是:{new_candy}")  # 新糖果没变

5.2. 彩虹画板

def add_colors(palette):
    print(f"画板上现在的颜色:{palette}")
    # 往画板上加颜色
    palette["红色"] = "鲜红"
    palette["蓝色"] = "天蓝"
    print(f"加了新颜色后:{palette}")

# 准备画板
my_palette = {"黄色": "金黄"}
print(f"原始画板:{my_palette}")
add_colors(my_palette)
print(f"画板变成了:{my_palette}")

6. 小贴士

  1. 记住参数传递的规则
  2. 不可变类型:就像照片,送过去后不能改变原件
  3. 可变类型:就像玩具箱,可以往里面加东西
  4. 想要保护原件,就要复制一份再送

  5. 不可变类型有

  6. 数字(整数、浮点数)
  7. 字符串
  8. 元组
  9. 布尔值

  10. 可变类型有

  11. 列表
  12. 字典
  13. 集合

记住:参数传递就像送快递,要知道什么快递可以改变,什么快递不能改变。这样就能写出更好的程序啦!

进一步学习