【问题标题】:Initialise two variables to point to same reference in Python在 Python 中初始化两个变量以指向相同的引用
【发布时间】:2021-09-09 18:13:19
【问题描述】:

我在这里看到了很多类似的问题,但没有一个涉及我想知道的问题。举个例子吧。

我想从一个数组中创建一个链表。忽略所有的样板,让我们进入这个问题的实质。

arr = [1, 2, 3, 4, 5]
tail = head = None  # this is the problematic line
for item in arr:
  tail = Node(val=item, next=None)
  tail = tail.next
return head

不用说,这是行不通的。 Head 总是指向 None,不管 tail 指向什么。

我尝试过的其他一些事情:

head = tail = [] # head will point to the empty list after finishing
head = tail = any_other_singleton # does not work

我知道为什么会这样。这是因为我正在重新分配 tail 以指向一个节点。但我想在“head”中保留对喜欢列表头部的引用。我怎样才能使这项工作?在其他编程语言中这是微不足道的,但在 python 中,您必须在声明时为变量赋值,这给我带来了问题。

【问题讨论】:

  • Python 没有指针。阅读以下内容:nedbatchelder.com/text/names.html
  • @juanpa.arrivillaga 是正确的,但仍然可以模拟指针行为onlinegdb.com/bTMmQX56W
  • 如您所说,您将如何用其他语言轻松做到这一点?
  • 这是我的错误。我应该澄清不是所有的编程语言,而不是隐含的。但我相信 C++,我们可以有两个指向同一个引用的指针并从那里开始工作,不是吗?

标签: python pointers variables


【解决方案1】:

只需单独处理第一项即可。

arr = [1, 2, 3, 4, 5]
head = tail = Node(val=arr[0], next=None)
for item in arr[1:]:
    tail.next = Node(val=item, next=none)
    tail = tail.next
return head

【讨论】:

  • 如果 Node 是一个命名元组 tail.next = ... 将不起作用。
  • @Nolan 链表从根本上需要能够修改.next 字段——这就是它们的全部意义,能够在中间插入一个元素而无需将其余部分移回列表。如果您使用命名元组(或其他不可变变量)作为节点,那么您做错了。
  • @GreenCloakGuy 好吧,在 Python 中,通常情况就是这样。但是链表是各种函数式编程语言中不可变数据结构的典型示例,在这种情况下通常称为“cons 列表”,在 LISP 中的“cons”操作之后
【解决方案2】:

可以在真实列表之前使用一个虚拟的。如果arr 为空,则不会崩溃。

arr = [1, 2, 3, 4, 5]
tail = dummy = Node(val=None, next=None)
for val in arr:
    tail.next = tail = Node(val=val, next=None)
return dummy.next

未测试,因为缺少 Node 类。

【讨论】:

    【解决方案3】:

    你想要达到的,大概可以这样完成。

    from collections import namedtuple
    
    
    Node = namedtuple('Node', ['val', 'next'])
    
    
    def array_to_list(arr):
        lst = None
        for a in reversed(arr):
            lst = Node(val=a, next=lst)
        return lst
        
    
    x = array_to_list([1, 2, 3]) 
    print(x)
    

    如果您从未使用过持久(不可变)数据结构,接下来的代码可能有助于理解:

    def insert_recursive(lst, pos, value):
        if not pos or not lst:
            return Node(val=value, next=lst)
        return Node(val=lst.val, next=insert_recursive(lst.next, pos - 1, value))
        
    
    def insert_nonrecursive(lst, pos, value):
        values = []
        while lst and pos:
            values.append(lst.val)
            lst = lst.next
            pos -= 1
        result = Node(val=value, next=lst)
        while len(values):
            result = Node(val=values.pop(), next=result)
        return result
        
    
    y = insert_recursive(x, 1, 42)
    print(y)
    
    z = insert_nonrecursive(x, 1, 42)
    print(z)
    

    【讨论】:

      【解决方案4】:

      我知道functools.reduce 在 Python 世界中有点害群之马,但如果您反向处理列表,它可以很好地解决这个问题。例如:

      from functools import reduce
      from collections import namedtuple
      
      Node = namedtuple('Node', ['next', 'val']) # or alternatively a class with next, val members
              
      arr = [1, 2, 3, 4, 5]
      
      # Make Linked List
      lst = reduce(Node, reversed(arr), None)
      
      # Try printing them
      head = lst
      while head:
          print(head.val)
          head = head.next
      

      将打印:

      1
      2
      3
      4
      5
      

      【讨论】:

        猜你喜欢
        • 2016-01-24
        • 2015-01-17
        • 1970-01-01
        • 2017-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-01
        • 1970-01-01
        相关资源
        最近更新 更多