Python 参数传递到底是值传递还是引用传递?从底层模型到实战避坑全面解析

从Python到Go:跨语言理解参数传递的坑(附内存示意图解) 本文深入对比了Python与Go语言在参数传递机制上的核心差异。Python采用基于对象引用的传递方式,行为受对象可变性影响;而Go严格遵循值传递,通过指针实现引用语义。文章通过内存示意图和实战代码,解析了两种语言在处理列表、结构体等类型时的不同行为,并提供了跨语言开发时的避坑指南与性能优化建议。 阅读详情

Python 参数传递到底是值传递还是引用传递?从底层模型到实战避坑全面解析

在 Python 编程中,有一个问题几乎每个开发者都会遇到:

Python 的参数传递,到底是值传递,还是引用传递?

很多初学者会这样理解:

def change(x):
    x = 100

a = 1
change(a)
print(a)  # 1

于是得出结论:Python 是值传递。

但再看下面这段代码:

def add_item(items):
    items.append("Python")

languages = ["Java"]
add_item(languages)
print(languages)  # ['Java', 'Python']

这一次,函数内部修改了外部变量,于是又有人说:Python 是引用传递。

那么问题来了:
为什么有时候函数内部改不了外部变量,有时候又能改?
Python 参数传递到底是哪一种模型?

答案是:

Python 既不是传统意义上的值传递,也不是传统意义上的引用传递,而是“对象引用传递”,也常被称为“共享传参”或“传对象引用”。

更准确地说:

函数调用时,Python 会把实参所绑定的对象引用,赋值给函数的形参。形参和实参最初指向同一个对象,但形参本身是函数内部的局部变量名。

理解这句话,你就能真正理解 Python 的变量、对象、函数参数、可变对象、不可变对象,以及那些常见但隐蔽的 bug。


一、先从 Python 的变量模型讲起

在很多语言里,变量像一个盒子,值被放进盒子里。

但在 Python 中,更合适的理解是:

变量名是标签,对象才是真正的数据实体。

例如:

a = [1, 2, 3]

可以理解为:

变量名 a  --->  列表对象 [1, 2, 3]

当我们写:

b = a

并不是复制了一个新列表,而是让 b 也指向同一个列表对象:

a  ----\
        ---> [1, 2, 3]
b  ----/

所以:

a = [1, 2, 3]
b = a

b.append(4)

print(a)  # [1, 2, 3, 4]
print(b)  # [1, 2, 3, 4]

因为 a 和 b 指向同一个对象。

我们可以用 id() 来验证:

a = [1, 2, 3]
b = a

print(id(a))
print(id(b))
print(a is b)  # True

is 判断两个变量是否引用同一个对象,== 判断两个对象的值是否相等:

x = [1, 2]
y = [1, 2]

print(x == y)  # True,内容相等
print(x is y)  # False,不是同一个对象

这是理解 Python 参数传递的基础。


二、函数调用时到底发生了什么?

看一段简单代码:

def show(value):
    print(value)

name = "Python"
show(name)

当调用 show(name) 时,Python 做的事情可以理解为:

value = name

也就是说,函数形参 value 成为了一个新的局部变量名,它和外部变量 name 指向同一个字符串对象。

示意图如下:

调用前:

name ---> "Python"

调用 show(name) 后:

name  ----\
           ---> "Python"
value ----/

这就是 Python 参数传递的核心:

参数传递不是复制整个对象,而是把对象引用绑定给形参。

但是,形参是一个新的局部变量名。你可以让它重新绑定到别的对象,而不会影响外部变量名。


三、为什么不可变对象看起来像“值传递”?

看这个例子:

def change_number(x):
    x = 100
    print("函数内:", x)

n = 1
change_number(n)
print("函数外:", n)

输出:

函数内: 100
函数外: 1

很多人据此认为 Python 是值传递。其实不是。

调用函数时:

n  ---> 1
x  ---> 1

进入函数后执行:

x = 100

这不是把原来的整数对象 1 改成 100,而是让局部变量 x 重新绑定到整数对象 100。

n  ---> 1

x  ---> 100

外部变量 n 仍然指向 1,所以不会改变。

字符串也是类似:

def change_text(s):
    s += " world"
    print("函数内:", s)

text = "hello"
change_text(text)
print("函数外:", text)

输出:

函数内: hello world
函数外: hello

因为字符串是不可变对象。s += " world" 实际上创建了一个新字符串,并让局部变量 s 指向新对象。

所以,不可变对象在函数里被“修改”时,通常表现得像值传递。

但这只是表象。


四、为什么可变对象看起来像“引用传递”?

再看列表:

def add_item(items):
    items.append("Python")

languages = ["Java"]
add_item(languages)

print(languages)

输出:

['Java', 'Python']

调用函数时:

languages  ----\
                ---> ['Java']
items      ----/

形参 items 和实参 languages 指向同一个列表对象。

执行:

items.append("Python")

这不是让 items 重新绑定,而是修改它所指向的那个列表对象本身。

修改后:

languages  ----\
                ---> ['Java', 'Python']
items      ----/

所以函数外部看到的列表也变了。

这就是为什么可变对象看起来像引用传递。

常见可变对象包括:

list
dict
set
bytearray
大多数自定义类实例

常见不可变对象包括:

int
float
bool
str
tuple
frozenset
bytes
None

五、Python 真正的模型:对象共享传参

为了避免“值传递”和“引用传递”带来的误解,建议记住下面这句话:

Python 的参数传递是对象共享传参:函数形参和外部实参共享同一个对象引用,但形参变量名本身可以在函数内部重新绑定。

它有两个关键点。

第一,函数参数接收的是对象引用,不是对象完整副本。

第二,函数内部给形参重新赋值,只会改变局部变量绑定,不会改变外部变量绑定。

看这个例子:

def demo(items):
    print("进入函数:", id(items))
    items.append(3)
    print("append 后:", items, id(items))

    items = ["new"]
    print("重新赋值后:", items, id(items))

data = [1, 2]
print("调用前:", data, id(data))

demo(data)

print("调用后:", data, id(data))

可能输出:

调用前: [1, 2] 1400000001
进入函数: 1400000001
append 后: [1, 2, 3] 1400000001
重新赋值后: ['new'] 1400000999
调用后: [1, 2, 3] 1400000001

解释一下:

items.append(3)

修改的是共享列表对象,所以外部能看到变化。

但:

items = ["new"]

只是让局部变量 items 指向新列表,不会影响外部变量 data。

这段代码是理解 Python 参数传递模型的经典例子。


六、+= 的特殊陷阱:它到底是修改还是重新绑定?

+= 在 Python 中很容易让人误判。

对于不可变对象:

def add_number(x):
    x += 1

n = 10
add_number(n)
print(n)  # 10

整数不可变,x += 1 等价于创建新整数并重新绑定 x,不会影响外部 n。

但对于列表:

def extend_list(items):
    items += [3, 4]

data = [1, 2]
extend_list(data)

print(data)  # [1, 2, 3, 4]

列表的 += 通常是原地扩展,等价于:

items.extend([3, 4])

所以外部列表会被修改。

再对比:

def add_list(items):
    items = items + [3, 4]

data = [1, 2]
add_list(data)

print(data)  # [1, 2]

items = items + [3, 4] 会创建一个新列表,然后让局部变量 items 指向它,因此不影响外部。

这就是 Python 中非常值得注意的区别:

items += other

可能原地修改。

items = items + other

通常创建新对象并重新绑定。

在代码审查中,我经常会特别留意 +=。它不是语法糖那么简单,它背后调用的是对象自己的原地操作协议。


七、默认参数陷阱:参数传递模型的经典事故现场

Python 中最经典的坑,莫过于可变默认参数:

def add_task(task, task_list=[]):
    task_list.append(task)
    return task_list

print(add_task("写文档"))
print(add_task("写测试"))
print(add_task("发布上线"))

你可能以为输出是:

['写文档']
['写测试']
['发布上线']

实际输出却是:

['写文档']
['写文档', '写测试']
['写文档', '写测试', '发布上线']

原因是:函数默认参数在函数定义时只创建一次。

也就是说,task_list=[] 这个列表对象会被多次调用共享。

正确写法是:

def add_task(task, task_list=None):
    if task_list is None:
        task_list = []
    task_list.append(task)
    return task_list

print(add_task("写文档"))
print(add_task("写测试"))
print(add_task("发布上线"))

输出:

['写文档']
['写测试']
['发布上线']

这个问题在 Web 接口、数据处理、任务队列、配置构建中非常常见。尤其是写工具函数时,千万不要把 list、dict、set 作为默认参数。

错误写法:

def create_user(name, tags=[]):
    tags.append("new")
    return {"name": name, "tags": tags}

推荐写法:

def create_user(name, tags=None):
    if tags is None:
        tags = []
    return {"name": name, "tags": tags}

这不是“风格问题”,而是稳定性问题。


八、实战案例:清洗用户数据时,函数应该修改原数据吗?

假设我们有一批用户数据:

users = [
    {"name": " alice ", "email": "ALICE@example.com"},
    {"name": " bob ", "email": "BOB@example.com"},
]

现在要清洗数据:去掉姓名两边空格,把邮箱转小写。

第一种写法:原地修改。

def normalize_users_inplace(users):
    for user in users:
        user["name"] = user["name"].strip().title()
        user["email"] = user["email"].lower()

normalize_users_inplace(users)

print(users)

优点是节省内存,适合数据量很大、明确允许修改原数据的场景。

缺点是副作用明显,调用者如果不知道函数会修改原数据,就可能踩坑。

第二种写法:返回新数据。

def normalize_users(users):
    result = []

    for user in users:
        normalized = {
            "name": user["name"].strip().title(),
            "email": user["email"].lower(),
        }
        result.append(normalized)

    return result

new_users = normalize_users(users)

print(users)
print(new_users)

这种写法更安全,函数没有悄悄修改传入对象。

在真实项目中,我建议遵循一个原则:

默认不要修改传入参数;如果要原地修改,必须在函数名、文档或注释中明确表达。

例如:

def sort_records_inplace(records):
    """原地排序 records,会修改传入列表。"""
    records.sort(key=lambda item: item["created_at"])

而如果函数返回新对象,可以这样命名:

def sorted_records(records):
    """返回排序后的新列表,不修改原 records。"""
    return sorted(records, key=lambda item: item["created_at"])

清晰的命名,本质上是在降低团队沟通成本。


九、浅拷贝与深拷贝:避免“我明明复制了,怎么还会变?”

参数传递和对象共享还会引出另一个问题:复制。

def update_first(items):
    items[0].append(99)

data = [[1, 2], [3, 4]]
copied = data.copy()

update_first(copied)

print(data)
print(copied)

输出:

[[1, 2, 99], [3, 4]]
[[1, 2, 99], [3, 4]]

为什么 data 也变了?

因为 copy() 是浅拷贝,只复制外层列表,内层列表仍然共享。

data   ---> 外层列表 A ---> 内层列表 [1, 2]
copied ---> 外层列表 B ----/

如果需要完全隔离嵌套对象,可以使用深拷贝:

import copy

data = [[1, 2], [3, 4]]
copied = copy.deepcopy(data)

copied[0].append(99)

print(data)    # [[1, 2], [3, 4]]
print(copied)  # [[1, 2, 99], [3, 4]]

但深拷贝不是万能药。它可能带来性能开销,也可能在复杂对象、文件句柄、数据库连接等场景中产生意料之外的问题。

实践建议是:

简单一层数据:浅拷贝通常足够
嵌套可变数据:考虑深拷贝
配置和常量:优先设计为不可变对象
大型数据:避免盲目复制,明确所有权

十、面向对象中的参数传递:self 也是一个引用

很多人学类的时候会问:self 到底是什么?

看代码:

class Counter:
    def __init__(self):
        self.value = 0

    def increase(self):
        self.value += 1

counter = Counter()
counter.increase()

print(counter.value)  # 1

调用:

counter.increase()

可以粗略理解为:

Counter.increase(counter)

也就是说,self 是指向当前实例对象的局部变量名。

counter  ----\
              ---> Counter 实例对象
self     ----/

在方法内部:

self.value += 1

修改的是实例对象的属性,所以外部的 counter.value 会变化。

但如果你在方法内部写:

class Counter:
    def reset_wrong(self):
        self = Counter()

这并不会让外部对象被替换,只是让局部变量 self 重新绑定到了一个新对象。

正确的重置应该是:

class Counter:
    def __init__(self):
        self.value = 0

    def reset(self):
        self.value = 0

这再次说明:
重新绑定局部变量不会影响外部绑定,修改共享对象本身才会影响外部。


十一、进阶视角:参数传递与不可变设计

当项目变大后,最可怕的不是代码报错,而是状态被悄悄改掉。

例如:

def apply_discount(order):
    order["price"] *= 0.8
    return order

这个函数会修改传入的订单字典。如果调用方还在其他地方使用原订单对象,就可能出现难以追踪的问题。

更稳妥的写法是返回新对象:

def apply_discount(order):
    return {
        **order,
        "price": order["price"] * 0.8,
    }

对于业务核心数据,还可以使用不可变数据模型:

from dataclasses import dataclass, replace

@dataclass(frozen=True)
class Order:
    id: int
    price: float

def apply_discount(order: Order) -> Order:
    return replace(order, price=order.price * 0.8)

order = Order(id=1, price=100)
new_order = apply_discount(order)

print(order)      # Order(id=1, price=100)
print(new_order)  # Order(id=1, price=80.0)

不可变对象的好处是:

更容易推理
更适合缓存
更适合并发
更少出现隐藏副作用
更方便测试

这也是为什么很多现代编程范式都强调“少修改共享状态”。


十二、与装饰器结合:观察函数是否修改了参数

在调试复杂项目时,我们可以写一个简单装饰器,观察函数调用前后参数的变化。

import copy
import functools

def watch_mutation(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        before_args = copy.deepcopy(args)
        before_kwargs = copy.deepcopy(kwargs)

        result = func(*args, **kwargs)

        if before_args != args or before_kwargs != kwargs:
            print(f"[警告] {func.__name__} 修改了传入参数")

        return result

    return wrapper

使用示例:

@watch_mutation
def add_item(items):
    items.append("new")

data = []
add_item(data)

输出:

[警告] add_item 修改了传入参数

这类工具在排查副作用问题时非常有用。不过要注意,deepcopy 有性能成本,不建议在线上高频路径中随意使用,更适合作为调试工具或测试辅助工具。


十三、单元测试:把“是否修改参数”写进测试

优秀的 Python 最佳实践,不只是写出功能,还要明确函数边界。

假设我们希望 normalize_users() 不修改原始数据,可以这样测试:

def normalize_users(users):
    return [
        {
            "name": user["name"].strip().title(),
            "email": user["email"].lower(),
        }
        for user in users
    ]

def test_normalize_users_does_not_mutate_input():
    users = [
        {"name": " alice ", "email": "ALICE@example.com"}
    ]

    original = [user.copy() for user in users]

    normalize_users(users)

    assert users == original

这个测试看似简单,但它保护的是函数设计契约:

调用这个函数不会改变传入参数。

在团队协作中,这类测试非常有价值,因为它能防止后续重构时无意引入副作用。


十四、性能视角:复制更安全,但不是越多越好

既然修改传入参数容易出问题,那是不是所有函数都应该复制数据?

也不是。

对于小型数据,复制通常没问题。
但对于大型列表、数据表、图结构、机器学习样本、实时流数据,盲目复制会带来明显的内存和性能压力。

比较合理的做法是:

业务核心对象:优先安全,避免隐式修改
性能敏感路径:允许原地修改,但必须明确约定
工具函数:默认返回新对象
底层算法:可提供 inplace 参数

例如很多数据处理库会采用这样的设计:

def normalize(records, inplace=False):
    if not inplace:
        records = [record.copy() for record in records]

    for record in records:
        record["name"] = record["name"].strip().title()

    return records

调用方可以明确选择:

new_records = normalize(records)
normalize(records, inplace=True)

这比函数偷偷修改参数要清晰得多。


十五、常见面试题:下面代码输出什么?

例 1:整数重新绑定

def f(x):
    x += 1

a = 10
f(a)
print(a)

答案:

10

整数不可变,x += 1 重新绑定局部变量。


例 2:列表原地修改

def f(x):
    x.append(1)

a = []
f(a)
print(a)

答案:

[1]

列表可变,append() 修改共享对象。


例 3:列表重新绑定

def f(x):
    x = x + [1]

a = []
f(a)
print(a)

答案:

[]

x + [1] 创建新列表,x = ... 只重新绑定局部变量。


例 4:列表原地扩展

def f(x):
    x += [1]

a = []
f(a)
print(a)

答案:

[1]

列表的 += 会原地扩展。


例 5:字典修改

def f(d):
    d["lang"] = "Python"

config = {}
f(config)
print(config)

答案:

{'lang': 'Python'}

字典是可变对象,函数内部修改会影响外部。


十六、最佳实践清单

在真实项目中,建议记住这些原则:

  1. 不要简单说 Python 是值传递或引用传递。
    更准确的说法是对象共享传参,或者对象引用按赋值传递。

  2. 区分“重新绑定”和“修改对象”。
    x = new_obj 是重新绑定;x.append()、x.update() 是修改对象。

  3. 警惕可变默认参数。
    不要写 def func(items=[]),优先写 def func(items=None)。

  4. 函数是否修改参数,要通过命名和文档说清楚。
    例如 normalize() 返回新对象,normalize_inplace() 原地修改。

  5. 嵌套结构复制时,区分浅拷贝和深拷贝。
    copy() 只复制外层,deepcopy() 递归复制内部对象。

  6. 业务核心数据尽量不可变。
    可以使用 tuple、frozenset、dataclass(frozen=True) 等方式降低副作用。

  7. 性能敏感场景允许原地修改,但要显式声明。
    例如提供 inplace=True 参数,让调用者自己选择。

  8. 用测试保护函数边界。
    如果函数承诺不修改输入,就应该写测试验证。


十七、总结:理解参数传递,就是理解 Python 的对象世界

Python 的参数传递问题,看似只是基础语法,背后却连接着变量模型、对象模型、可变性、函数设计、面向对象、测试、性能优化和工程实践。

一句话总结:

Python 函数调用时,形参会绑定到实参所引用的对象。函数内部如果修改这个共享对象,外部能看到变化;如果只是让形参重新绑定到新对象,外部不会受影响。

所以,Python 不是传统意义上的值传递,也不是 C++ 那种典型引用传递。它更像是:

对象引用被传入函数;
函数形参成为新的局部名字;
局部名字和外部名字最初共享同一个对象;
修改对象会影响共享者;
重新绑定名字只影响当前作用域。

当你真正理解这一点,很多 Python 行为都会变得清晰:

为什么列表参数会被函数修改?
为什么整数参数不会变?
为什么默认参数里的列表会被复用?
为什么 copy 后嵌套列表还会互相影响?
为什么 self 改属性有效,self = NewObject() 却无效?

Python 的魅力,恰恰在于它表面简洁,内部统一。
你越理解它的对象模型,就越能写出稳定、优雅、可维护的代码。

最后留给你两个问题:

你在项目中是否遇到过函数意外修改参数导致的 bug?
在你的团队里,是否会明确区分“返回新对象”和“原地修改”的函数命名?

欢迎在评论区分享你的经历。真正的 Python 成长,往往不是从背语法开始,而是从理解这些“看似简单却影响深远”的细节开始。

编程中的参数传递:值传递与引用传递详解 参数传递是编程语言中的基础概念,主要分为值传递和引用传递两种机制。值传递创建参数的独立副本,保证函数内部修改不影响外部变量,适合基本类型和小型数据;引用传递则直接操作原始变量,常用于需要修改外部状态或处理大型对象的场景。理解这两种机制的区别对避免常见编程错误至关重要,特别是在处理对象引用和集合类型时容易产生误解。从工程实践角度看,现代语言如Java和Python采用对象引用值传递的方式,既能保持值传递的安全性,又能通过引用操作对象内容。合理选择参数传递方式可以提升代码性能,同时确保程序逻辑的正确性。 阅读详情

相关推荐

Python函数参数传递机制深度解析:值传递与引用传递的真相

所有传递都是对象引用的传递不可变对象通过创建新对象模拟值传递可变对象提供直接的内存操作接口副作用管理需要开发者显式控制编写更高效的代码(避免不必要的拷贝)预防难以调试的副作用在函数式/命令式风格间自如切换设计出更健壮的API接口最终,参数传递机制的选择应基于具体场景:当需要保留原始状态时使用防御性拷贝,当追求性能时利用引用传递,当强调函数纯度时返回新对象。这种灵活性与控制力的平衡,正是Python动态特性的魅力所在。

这家伙很懒,什么都没有留下 1060

【Python基础】Python中参数传递,实际上是对象的引用传递

在 Python 中,万物皆对象。 因此,和其他语言不同的是,Python 中参数的传递既不是值传递,也不是引用传递,而是赋值传递,或者叫对象的引用传递。 需要注意的是,这里的赋值传递或对象的引用传递,不是指向一个具体的内存地址,而是指向一个具体的对象,只是让新变量与原变量指向相同的对象而已。也就是说,Python 里的对象可以被多个变量所指向或引用。 对于可变对象(列表,字典,集合等等),当其改变时,所有指向这个对象的变量都会改变。 对于不可变对象(字符串、整型、元组等等),简单的赋值只能改变其中一个变

Mr_SCX的博客 514

基于STM32的智能衣柜系统开发实战(附完整源码与硬件设计)

本文详细介绍了基于STM32的智能衣柜系统开发实战,包括硬件设计、软件架构和云端功能实现。系统具备实时温湿度监控、自动加热除湿、紫外线杀菌等核心功能,通过STM32F103C8T6主控芯片和ESP8266无线模块实现智能控制。附完整源码与硬件设计,适合科技爱好者和开发者参考。

peach的博客 779

Python值传递还是引用传递

Python值传递还是引用传递 Python作为一门动态语言,变量本身的类型是不固定的,因此更加灵活。那Python到底是值传递还是引用传递呢? 问题引出 本人在本周写代码时,遇到这么一个让我注意的问题,问题可以抽象如下: def func(val1): val2 = val1 val2.append(1) ... a = [] ...(一系列对a的操作) b = a func(a) print(b) 当我执行上述后,发现“b”的值也发生了改变。由此引发了我对Python...

团长的专栏 2009

如何在高版本的ubuntu系统里安装gcc4.1.2

1、下载安装包,一共五个http://archive.ubuntu.com/ubuntu/pool/universe/g/gcc-4.1/,根据计算机系统位数   进行下载,64位下载amd64结尾的。开头分别是cpp-4.1_4.1.2、g++-4.1_4.1.2、gcc-4.1-base_4.1.2、gcc-     4.1_4.1.2、libstdc++6-4.1 2、使用sudo d

lsr_fighting的博客 1929

MinIO vs 华为云OBS:成本、性能与兼容性深度对比(含实测数据)

本文深度对比了开源对象存储MinIO与华为云OBS在成本、性能、兼容性及运维方面的核心差异。通过实测数据与全生命周期成本分析,为技术决策者提供选型依据。文章指出,MinIO在长期成本控制、性能深度优化及S3 API兼容性方面优势显著,而华为云OBS则提供开箱即用的便利性。

kmeans3miner的博客 593

26. Python中函数参数的按对象传递

《Python编程的术与道:Python语言入门》视频课程 《Python编程的术与道:Python语言入门》视频课程链接:https://edu.youkuaiyun.com/course/detail/27845 函数参数的按对象传递 如何将函数调用中的参数传递给函数的参数(即函数参数的自变量的评估策略),因编程语言而异。 最常见的评估策略是“按值调用”(“Call by Value” )和“按引用调用”(“Call by Reference”): 按值调用(Call by Value ) 最常见的策略是按值调用评

bai666ai的博客 3003

060、模型蒸馏:把扩散模型压进单步的魔法

《端侧文生图模型蒸馏实战:从32步到1步的优化之道》摘要:针对边缘设备部署难题,本文分享了扩散模型蒸馏的核心经验。通过重构损失函数(感知损失+对抗训练+KL散度)、优化采样轨迹截取策略和改造学生模型架构,成功将Stable Diffusion压缩至单步推理。关键发现包括:小批量训练更有效、标签平滑保障生成多样性、双模型策略平衡质量与速度。在Cortex-A53芯片上实现300ms内生成,内存占用控制在200MB以下。特别强调工业部署需权衡压缩率与稳定性,建议保留迭代模式开关以适配不同场景需求。

2601_95651806的博客 149

python中参数传递

在编程语言中,函数的参数传递有两种情况: 按值类型传递 num = 10 def double(arg): arg=arg*2 print(arg) double(num) 复制代码 调用该函数,传入一个变量,其实传入的是该变量的一个副本,该变量在函数中发生变化,不影响函数外面该变量。 按引用类型(地址)传递 def change(arg): arg.a...

weixin_34248849的博客 972

31、车载通信中的可见光通信(VLC)技术解析

本文详细解析了车载通信中可见光通信(VLC)技术的应用背景、优势及发展前景。对比传统RF通信技术(如DSRC),VLC利用LED照明设备实现高效、安全的车辆与车辆、车辆与基础设施之间的通信,具有频谱资源丰富、安全性高、无电磁干扰等优势。文章还探讨了VLC在交叉口交通控制、高速公路通信、自动驾驶等场景的应用潜力,展望了其在未来智能交通系统中的重要作用。

hill8的博客 315

openharmony之启动恢复子系统详解

需求: 添加一个名为my_service的自定义服务步骤1: 创建服务配置],],"env": [步骤2: 添加到主配置],"jobs": ["cmds": [步骤3: 验证配置# ✅ 检查配置格式 jq . /system/etc/init/my_service.cfg # 🔄 重新加载配置 begetctl reload # 📊 验证服务状态 begetctl dump_service my_serviceOpenHarmony init进程的完整生命周期。🔄 三阶段启动模型⚙️ 配置体系。

m0_67505153的博客 597

python函数传递对象_如何在python中的函数中传递对象的实例作为参数?

我刚刚开始学习python,我对如何传递一个对象的实例作为一个函数的参数感到困惑,下面是我为练习做的一些代码,基本的想法是有一个车库,这个车库不包含汽车,您可以将车辆添加到车库并查看其详细信息.class Garage:cars = []def add_car(self, car):cars.append(car)class Car:car_name, car_price, car_colour,...

weixin_36238073的博客 1873

STM32G431的 FDCAN使用5M加速时,出现奇葩问题,如何解决?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 1635

一文读懂 Python 值传递和引用传递

在编程语言中,值传递(pass by value)和引用传递(pass by reference)是两个重要的概念。它们涉及到变量在函数调用中的传递方式,对于理解函数调用和参数传递的机制至关重要。在本文中,我们将深入探讨 Python 中的值传递和引用传递,并通过代码示例进行说明。

weixin_68789096的博客 1万+

qq对接openclaw,通过qq发送命令

把 OpenClaw 接入 QQ 和微信,目前主流的微信文章和教程主要提供了两种截然不同的路径。我为你梳理了它们的核心区别和关键步骤,你可以根据自己的需求来选择。

suny8的专栏 270

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Python(15)Python参数传递与拷贝机制完全解析:从值传递到深拷贝实战

Python参数传递与拷贝机制完全解析:从值传递到深拷贝实战 背景介绍 在Python编程中,‌参数传递机制‌和‌对象拷贝操作‌是影响程序行为的关键因素。错误理解这些机制会导致以下典型问题: 函数意外修改外部变量(占Bug总数的‌27%‌) 嵌套数据结构出现幽灵修改 多线程环境下数据竞争 本文将通过‌内存模型图解‌、‌30+个代码案例‌,系统讲解: ‌值传递 vs 引用传递的本质区别‌ ‌浅拷贝与深拷贝的底层实现‌ ‌可变/不可变对象的行为差异‌ ‌5种典型场景的避坑指南‌

优快云博客专家,领域包括但不限于:AI、大数据、Python、架构师,有合作、课程、问题、疑惑请私信博主 1631

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Python函数参数:按值传递和按引用传递

首先简单说明一下,Python中按值传递与按引用传递的区别: 按值参数传递是指一个变量的值来取代一个函数参数的做法。 如果这个值在函数代码组中改变,对于调用这个函数的代码来说,其中相应的变量值并不会受到任何影响,可以把这个参数认为是原变量值的一个副本。 按引用参数传递是指对于调用这个函数的代码,会维护这个代码中变量的一个链接(引用)。 如果函数代码组中的变量改变,那么在调用这个函数的代码中...

weixin_41798450的博客 2万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Python对象引用(传对象引用)(python值传递、python引用传递、python传值、python传引用、python引用)不可变数据类型、python传参、深拷贝、浅拷贝、id()函数

值传递指的是在调用函数时,实际传递的是变量的副本(拷贝),而不是变量本身。这意味着在函数内部对参数的修改不会影响到原始数据。引用传递则相反,传递的是变量的引用,而不是副本。这样,函数内部对参数的任何修改都会直接影响到原始数据。通过以上的探讨和示例,可以看出 Python 中的参数传递虽然表面上简单,实则包含了丰富的细节和深层次的理解。掌握了这些知识,可以帮助开发者更有效地管理内存使用,设计更安全和高效的函数。

Dontla的博客 2693

Python 参数传递机制揭秘:值传递?引用传递?真相在这里

Python 的参数传递机制不仅仅是“值传递”或“引用传递”的简单选择,而是“传递对象的引用”,但这一机制的具体表现会根据对象的可变性有所不同。了解这一机制,可以帮助我们更好地设计函数,避免不必要的副作用,并优化代码的可读性和可维护性。不可变对象:Python 表现得像是“值传递”。可变对象:Python 表现得像是“引用传递”。重新赋值:无论是可变还是不可变对象,重新赋值都不会影响原对象。理解和掌握 Python 的参数传递机制,是写出高效、清晰和易于维护的 Python 代码的基础。

测试者家园 943

16 | 值传递,引用传递or其他,Python里参数是如何传递的?

如果接触过其他的编程语言,比如 C/C++,很容易想到,常见的参数传递有 2 种:值传递和引用传递。所谓值传递,通常就是拷贝参数的值,然后传递给函数里的新变量。这样,原变量和新变量之间互相独立,互不影响。// 交换2个变量的值int temp;temp = x;// 交换x和y的值x = y;y = temp;return;int a = 1;int b = 2;swap(a, b);return 0;

qq_37756660的博客 1102

面试|Python|函数传参是值传递还是引用传递?

Python函数传参的本质是“传递对象引用的副本”。如果对象是可变的,函数内对其内容的修改会反映到外部。如果对象是不可变的,任何“修改”都会创建新对象,不影响外部。重新赋值只会改变局部变量的指向,不会影响外部变量。Python的参数传递机制看似复杂,实则遵循其“一切皆对象”的简洁设计。理解“传递对象引用”这一核心概念,结合对象的可变性分析,就能从容应对各种传参场景。“都不是,它是传递对象引用。掌握这一点,你不仅解决了参数传递的疑惑,也向深入理解Python的内存模型迈出了重要一步。

Aerkui的博客 1321

python:值传递与引用传参

接下来主程序开始调用 swap() 函数,在调用 swap() 函数时,dw 变量作为参数传入 swap() 函数,这里依然采用值传递方式:把主程序中 dw 变量的值赋给 swap() 函数的 dw 形参,从而完成 swap() 函数的 dw 参数的初始化。值得指出的是,主程序中的 dw 是一个引用变量(也就是一个指针),它保存了字典对象的地址值,当把 dw 的值赋给 swap() 函数的 dw 参数后,就是让 swap() 函数的 dw 参数也保存这个地址值,即也会引用到同一个字典对象。

OceanStar的博客 2060

一文搞懂Python函数参数传递机制:值传递与引用传递

Python参数传递本质:对象引用传递(传对象引用,不是传值也不是传引用)不可变对象:函数内修改会创建新对象,不影响原始数据可变对象:函数内修改会影响原始数据重要区别重新绑定变量(=操作):不影响外部原地修改对象(append/extend等):影响外部最佳实践如果函数需要修改输入参数,应该明确说明除非明确需要修改,否则避免直接修改传入的可变对象对可变默认参数使用None惯用法必要时创建副本来保护原始数据。

m0_74107848的博客 1048

python 值传递还是引用传递_Python 到底是值传递还是引用传递

我们平时写的 Python 程序中充斥着大量的函数,包括系统自带函数和自定义函数,当我们调用函数时直接将参数传递进去然后坐等接收返回值即可,简直不要太好用。那么你知道函数的参数是怎么传递的么,是值传递还是引用传递呢,什么又是值传递和引用传递呢?这个问题对于很多初学者还是比较有难度的,看到这里你可以稍加停顿,自己思考一下,看看自己是否真正理解了。很多人只是知道概念但是让他说他又说不清楚,思考过后如果...

weixin_39664746的博客 83

值传递和引用传递

代码中使用是为了**“传引用”**。如果不加:函数删了半天,外面的链表纹丝不动(或者只改了局部副本),删除失败。加了:函数能直接“动手术”,真正把节点从原链表上摘除。补充提示:这种Type &Name的写法是C++的语法。如果是纯 C 语言,要实现同样的效果,通常需要写成二级指针。特性值传递引用传递传递内容参数的副本参数的引用(别名)内存空间独立的内存空间与实参共享内存空间修改影响不影响实参直接影响实参适用类型基本数据类型、不可变对象对象、可变数据结构Java实现基本类型。

qq_39697468的博客 385

python 中的值传递和引用传递

python中的参数传递和java等其他语言实现有点区别,python中对象有两种,不可变对象(基本类型,int,string,布尔等),对于这一部分的对象作为参数传递时,是值传递,在函数里面值修改了,外面不影响;另外一种可变对象(字典,列表,集合),对于这样的对象作为参数传递时,是引用传递,在内部函数修改了值,外面的值也会变化。 1、值传递,如: def add(a): a =...

qq_30966497的博客 903
上一篇: Python 可变对象与不可变对象深度解析:为什么 `tuple` 里可以放 `list`?
下一篇: Python 经典陷阱深度解析:为什么 `def f(x=[])` 会“记住”上一次调用
铭渊老黄
铭渊老黄 新星创作者: Python技术领域 新星创作者: Python技术领域
博客等级 码龄7年 1万+粉丝 2218原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

铭渊老黄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值