在Python中引用自定义类

时间:2018-07-29 03:21:01

标签: python reference immutability mutable

我了解Python中的自定义类通常是可变的。因此,在下面的示例中,对函数s中的参数inc_age所做的任何更改都会在调用部分反映出来。

class Student:
    def __init__(self, name, age):
            self.name = name
            self.age = age

def inc_age(s):
    s.age += 1


s1 = Student("Test",5)
inc_age(s1)
print(s1.age) # 6

我尝试使用自定义类在Python中实现链接列表,如下所示:

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

def next_node(L):
    L = L.next

end = ListNode(3)
mid = ListNode(2,end)
beg = ListNode(1,mid)

next_node(beg)
print(beg.data) # 1

我的问题是为什么在调用部分没有观察到函数L中对象next_node的变化。

2 个答案:

答案 0 :(得分:2)

简短的版本是这样的:

  • 如果您更改L中值的属性,这些将在对该值的任何其他引用中表示。
  • 如果您只是将局部变量L更改为一个完全不同的值的名称,那么除了局部变量L不会改变任何其他内容。

如果这让您感到困惑,则您没有正确考虑Python中的变量。在某些语言中,例如C ++,变量是值所在的位置。在其他语言中,例如Python,变量只是一个名称,您可以在名称空间中查找该变量以找到一个值。价值观可以随心所欲。

因此,L =不会对L的值做任何事情,它只是将L变成本地命名空间中一个不同值的名称。

但是L.next =会使next成为L所引用值的命名空间中另一个值的名称。因此,具有与L相同值的任何其他名称都可以看到更改。

答案 1 :(得分:0)

您必须使用self来寻址属性,并避免使用内置方法的名称(下一个)来命名变量和属性:

  • 从头开始建立链接列表也是一种更好的做法
  • 此外,我更正了一些错字

输出测试从头开始枚举所有节点。

class ListNode:
    def __init__(self, data=0, next_node=None):
        self.data = data
        self.next_node = next_node

    def add_next_node(self, node):
        self.next_node = node


if __name__ == '__main__':
    beg = ListNode(1)
    mid = ListNode(2)
    end = ListNode(3)

    beg.add_next_node(mid)
    mid.add_next_node(end)

    current = beg
    while True:
        print(current.data)
        current = current.next_node
        if current is None:
            break

输出:

1
2
3