【问题标题】:Modify a class in a function to reflect change in calling function (Python)修改函数中的类以反映调用函数的变化(Python)
【发布时间】:2022-07-08 02:35:38
【问题描述】:

我有一堂课如下:

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

我创建一个链表为:

ll = ListNode(1)
ll.next = ListNode(2)

我想通过在函数中创建新节点来将列表复制到新列表:

def create_new_node(res, l):
            print(l.val)
            res.next = ListNode(l.val)
            l=l.next
            print("Next", l.val)
            res=res.next

res = ListNode()
while ll:
        # Based on some condition
        create_new_node(res, ll)

>>> 1
Next 2
1
Next 2
....

但是,这进入了一个无限循环,因为 ll 永远不会前进到 create_node_function 之外的 while 循环中的下一个节点,即使正在生成 l(这是 ll 的引用)以l=l.next 指向next 节点。

在Python中类不是通过引用传递的,难道不能在另一个函数中修改它们以反映调用函数的变化吗?

【问题讨论】:

  • 虽然类实例是一个引用,但引用本身并不是通过引用传递的。另外,我注意到您使用“next”作为变量,但这也是 python 内置函数的名称。我得先走了,但如果没有人比我做得好,我会在大约一个小时后通过一个例子把它说得更清楚。

标签: python function class reference


【解决方案1】:

在 python 中,对象是通过赋值传递的。您可以通过以下代码看到这一点。

test_list = [1,2,3]
test_dict = {1:'a', 2:'b'}
test_tup = (1,2,3)
test_int = 5
test_str = 'hello world'

def change_test(mylist, mydict,myint, mystr):
    print('list: ', id(mylist), 'dict: ', id(mydict),'int: ', id(myint),'str: ', id(mystr))


change_test(test_list, test_dict, test_int, test_str)

print('list: ', id(test_list),'dict: ', id(test_dict),'int: ', id(test_int),'str: ', id(test_str))

输出是:

list:  4346425984 dict:  4347616128 int:  4345676144 str:  4347344688
list:  4346425984 dict:  4347616128 int:  4345676144 str:  4347344688

你看到函数内部和外部的id是一样的,所以它们的值是一样的。但是,当您更改可变对象时,id 保持不变,而对于不可变对象,id 会更改。

类实例是可变的,因此它们的行为类似于通过引用传递。我们可以通过检查以下代码中每个对象的 id 来看到这一点。

def create_new_node(res, l):
    print('in func: ', id(l))
    l.val = 99

ll = ListNode(1)
ll.next = ListNode(2)

res = ListNode()
print('out of func: ', id(ll), ll.val)
create_new_node(res, ll)
print('out of func: ', id(ll), ll.val) 

输出是

out of func:  4334042752 1
in func:  4334042752
out of func:  4334042752 99

你的代码有问题

l=l.next

当我们将 ll 传递给 create_new_node 时,l 是 ll,但是当我们将 l 设置为 l.next 时,l 现在是 l.next 而不是 ll,l.next 在内存中具有不同的地址。要使您的代码正常工作并复制列表,请像这样返回 l。

def create_new_node(res, l):
    res.next = ListNode(l.val)
    l=l.next
    res=res.next
    return l

ll = ListNode(1)
ll.next = ListNode(2)

res = ListNode(ll.val)

current = ll
while current:
    current = create_new_node(res, current)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-06
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 2014-03-04
    • 2018-10-06
    • 1970-01-01
    相关资源
    最近更新 更多