Python 不可变的函数参数

0 投票
2 回答
3453 浏览
提问于 2025-04-18 17:54

我正在尝试理解Python的核心概念,看到了一篇不错的文章,讲的是如何将参数的引用传递给一个对象。比如说:

def add_to_list(list_to_add, value):
  list_to_add.append(value)

这样做可以改变原来的list_to_add参数,而;

def change_list(list_to_add):
  list_to_add = [1, 2, 3, 5]

这样做就不会有任何变化。

我现在正在写一个基本的链表打印函数,简单来说就是:

class Node:
  def __init__(self, val, next=None):
    self.val = val
    self.next = next

root = Node(2, Node(3, Node(4, Node(5, Node(6)))))

def print_list(root):
  while root:
    print root.val,
    root = root.next
  print ''

你们猜得没错,它并没有改变根节点的值。现在我想问的是这是为什么呢。是因为Python的类是不可变的吗?

2 个回答

1

这很简单:

obj.do_something()

这个操作会对传入的对象进行处理,可能会修改它(比如用 list_to_add.append() 来添加元素),而

obj = something_other

则会丢掉对旧对象的引用,使用一个新的对象。

对一个对象的修改(当然)会被“其他”使用这个对象的人看到,而重新赋值只会影响到被重新定义的地方。

4

Python的类并不是不可改变的。你可以随意修改它们(当然有一些特殊情况,比如扩展类型或者slots)。

不过在这里,你定义了一个模块级别的(全局)变量叫做root,然后在print_list函数里又定义了一个同名的参数root。

当你调用print_list(root)并给root赋值时,这并不会改变模块级别的全局变量!

如果你想要改变全局变量(虽然其实不应该这样做,这又是另一个关于避免使用全局变量的讨论),你需要在print_list里声明root为全局变量。

def print_list():
    global root
    ...

这样的话你就不需要这个参数了。

再说一遍:千万不要这样做!!!

如果你使用像pylint这样的工具来检查你的代码,它应该会警告你参数名“root”会覆盖模块级别的全局变量“root”。

撰写回答