You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python方法与函数如何实现原地修改传入对象本身的值

Python 原地修改传入对象的函数/方法实现原理

核心底层逻辑

Python的参数传递规则是传对象引用,既不是把整个对象拷贝一份传值,也不是其他语言里的传变量指针:

  • 你把列表这类可变对象传给函数/方法时,传进去的是指向原对象的内存地址引用,没有任何对象拷贝的开销。
  • 如果函数内部是直接修改对象本身的内容(比如修改列表某个索引的值、append/删除元素、给切片赋值),所有改动会直接作用在原对象上,外部访问原对象就能看到变化。
  • 如果函数内部是给参数名重新赋值(比如lst = [1,2,3]),这只是让函数内部的局部参数名指向了新对象,和外部的原对象完全无关,不会改动外部变量。

你之前写的kyub函数不生效,就是因为列表推导式会生成一个全新的列表,你直接return新列表,从头到尾没碰过传进来的原列表,原对象自然不会变。

实现原地修改的cube函数

不要创建新列表,直接遍历索引修改原列表的每个位置即可,不需要写返回值,默认返回None:

def cube(lst):
    for idx in range(len(lst)):
        lst[idx] = lst[idx] ** 3

测试效果完全符合你的预期:

>>> b = [-2,-1,0,3,4]
>>> cube(b)
>>> b
[-8, -1, 0, 27, 64]

还有个更简洁的写法是用切片赋值,效果完全一致,也是原地修改:

def cube(lst):
    lst[:] = [i**3 for i in lst]

这里lst[:] = xxx的作用是把原列表里的所有元素逐个替换成右边可迭代对象的内容,不是让lst变量重新指向新列表,属于对原对象的修改操作。

.sort()和random.shuffle()的实现逻辑

这两个的本质和上面写的cube完全一样:

  • list.sort()是列表类型的内置方法,调用时拿到当前列表实例self的引用,直接在原内存空间里做排序、交换元素位置,全程不生成新列表,所以返回None,调用后原列表直接变成排序后的结果。
  • 你翻random.py的源码就能看到,shuffle函数内部就是循环生成随机索引,交换传入列表里的元素位置,全程没有创建新列表,自然会直接改动传入的原列表。

这两个操作特意设计成返回None,就是为了明确告知使用者这是原地操作,和sorted()这类返回新列表的非原地操作做区分,避免使用者混淆。

关于你要的a.square()方法

Python内置的list类型是C层面实现的,不允许直接给它追加自定义方法,要实现这个效果有两种方案:

  • 方案1(推荐):和cube一样写独立的square(lst)函数,这是Python更推荐的写法,没必要硬套面向对象的方法调用风格。
  • 方案2:自定义一个继承自list的子类,在子类里定义square方法:
class MyList(list):
    def square(self):
        for idx in range(len(self)):
            self[idx] = self[idx] ** 2

使用时实例化自定义的列表类即可:

>>> a = MyList([1,3,5,7,9])
>>> a.square()
>>> a
[1, 9, 25, 49, 81]

注意事项

  • 只有可变对象支持原地修改:列表、字典、自定义类实例属于可变对象,可以通过函数修改内容;整数、字符串、元组是不可变对象,本身不允许修改内容,不管怎么写都没法在函数里原地改动原对象。
  • 一定要区分「修改对象内容」和「重绑定局部变量」:lst.append(1)、lst[0] = 2、lst[:] = [3,4]是修改原对象,会影响外部;lst = [1,2,3]是重绑定局部变量,和外部原对象无关。

内容的提问来源于stack exchange,提问作者Nikola Markovic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:45:41