当方法没有 return 语句时,如何打印出它的 return 值?

When a method has no return statement, how do I print out it's return value?

已编辑。

我正在学习链表。对于方法应用的每个过程,它都会打印到控制台。因此,添加、删除、搜索(即显示搜索结果)都流式传输到 stdout,但我似乎无法为插入方法执行此操作,即使执行了 insert 方法.

一些方法有一个 return 语句,而其他方法则依赖 __repr__() 转换为字符串,然后流式传输到控制台。插入方法(不是我的,而是一个课程示例)采用 两个 参数并且没有 return 语句。我尝试打印时收到的最一致的错误消息是 TypeError: %d format: a real number is required, not NoneTypeTypeError: not enough arguments for format string,其中我已将 %d 替换为 %s

我不明白的是,为什么我无法为插入方法显示测试数据,而我可以为所有其他方法显示测试数据。 代码,

#!/usr/bin/env python3

class Node:
  data = None
  next_node = None

  def __init__(self, data):
    self.data = data

  def __repr__(self):
    return "<Node data: {}>".format(self.data)

# Linked List
class LinkedList:

  def __init__(self):
    self.head = None

  def is_empty(self):
    return self.head == None  # corrected

  def size(self):
    current = self.head
    count = 0

    while current:
      count += 1
      current = current.next_node

    return count

  # Adding a node
  def add(self, data):

    new_node = Node(data)
    new_node.next_node = self.head
    self.head = new_node
    

  # Searching the List
  def search(self, key):

    current = self.head

    while current:
      if current.data == key:
        return current
      else:
        current = current.next_node
    return None
  
  # Inserting into the List
  def insert(self, data, index):
    
    if index == 0:
      self.add(data)

    if index > 0:
      new_data = Node(data)

    position = index
    current = self.head

    while position > 1:
      current = current.next_node
      position -= 1

    past_node = current
    future_node = current.next_node

    past_node.next_node = new_data
    new_data = current.next_node

  # Removing a node from the List
  def remove(self, key):
    
    current = self.head
    previous = None
    found = False

    while current and not found:
      if current.data == key and current == self.head:
        found = True
        self.head = current.next_node
      elif current.data == key:
        found = True
        previous.next_node = current.next_node

    return current

  def __repr__(self):
    
    nodes = []
    current = self.head

    while current:
      if current is self.head:
        nodes.append("[Head: {}]".format(current.data))
      elif current.next_node is None:
        nodes.append("[Tail {}]".format(current.data))
      else:
        nodes.append("[{}]".format(current.data))

      current = current.next_node
    return '-> '.join(nodes)

测试输出;

l = LinkedList()
l.add(1)
l.add(2)
l.add(3)
l.add(5)
l.add(6)
l.add(7)

length = l.size()
print("Size of list: {}".format(length))  # Size of list: 6

print(l)  # [Head: 7]-> [6]-> [5]-> [3]-> [2]-> [Tail: 1]

seek = l.search(7)
print("Found: {}".format(seek))  # Found: <Node data: 7>

between = l.insert(4, 3)
if between is not None:
  print(f"Inserted {between} at index {between}")
else:
  print("A problem with code") # A problem with code

gone = l.remove(1)
print("Removed: {}".format(gone))  # Removed: <Node data: 1>

# Note the insertion of '4' at index 3
print(l)  # [Head: 7]-> [6]-> [5]-> [4]-> [3]-> [Tail: 2]

此代码有效!

已尝试打印格式的其他变体 f"{}", .format(),甚至尝试转换为字符串 str(),但没有成功。有人可以准确解释问题是什么(虽然,我认为这是一个 NoneType 问题)以及如何解决它?

我希望我的问题更清楚。谢谢。

我认为您混淆了两件事。 return 语句后的值是调用函数时替换为函数调用的值。例如:

def square(x):
    return x*x

square(4) 

这里的 square(4) 将被替换为 4*4。如果您没有明确使用 return 语句,那么 None 会在 function/method.

中的最后一个命令之后被 returned

repr() 是一种指定该对象的字符串表示形式的方法。例如:

class A:
    pass

a = A()
print(a) 

可能会创建 <main.A at 0x7fbc841c9490> 的神秘输出。所以如果你想让它更具描述性,你可以添加一个 repr() 方法:

class Point:
    def __init__(self, x,y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Coordinates of the point are x: {self.x}, y: {self.y}"

p = Point(2,4)

您会收到以下神秘的默认消息:

Coordinates of the point are x: 2, y: 4

所以表示是如何将 obj 转换为字符串,而 return 值是函数调用被替换的内容。

print is TypeError: %d format: a real number is required, not NoneType, or TypeError: not enough arguments for format string, where I have replaced %d with %s.

所以这会产生错误,因为当没有 return 的方法的 return 类型是 None 时,%d 和 %s 需要数字和字符串。

insert 在输出数据时没有“问题”——就像标准的 Python 列表一样,它是一个 in-place 操作。您正在修改应用它的列表。

insert() 不需要 return 任何东西,因为你需要的所有信息都在调用它时由你提供 - 你需要传递一个列表,你需要传递数据来插入和您需要传递放置元素的索引 - returning 任何内容都不会获得新信息。

相关问题: Why don't list operations return the resulting list?

您提供的代码存在几个问题,包括:

  • Node class 不应将 datanext_node 定义为 class 属性。它们应该是实例属性。幸运的是,构造函数创建了一个实例属性 data(隐藏了 class 属性),但是对于 next_node 这并没有完成,这使得您的链表无法使用。

  • 根据前面的评论,你的构造函数中应该有self.next_node = None

  • [您在对问题的编辑中更正了这一点:方法名称is_empty表明它将return一个布尔值指示列表是否为空。但相反,它使列表为空。这似乎是错误的。]

  • [您在对问题的编辑中更正了此问题insert 可以调用未定义的方法 add。]

  • insert中,当index为0时,代码仍会在第一个if之后继续并引用一个变量new_data未定义(因为第二个 if 条件不成立)。您应该避免在 index 为 0 时执行任何其他代码。您可以使用 return.

    来执行此操作
  • insert中,在while循环中没有验证current是否为None。如果发生这种情况,current = current.next_node 将引发错误。

  • new_data = current.next_node 没有用,并且未初始化 next_nodenext_node 属性。

  • 不是问题,但在 remove 中,found 名称不是很有用。找到并删除节点后,就跳出循环。此外,避免对同一节点执行两次 current.data == key 条件。

  • remove 循环中,您永远不会更改 currentprevious,因此循环挂起。

  • [您在对问题的编辑中更正了这一点:在主代码中,列表在 l.insert 时是空的调用,因此将 3 作为 index 参数的值传递很奇怪,因为该索引超出范围。如上一条项目符号中所述,这将触发错误。如果要在索引 3 处添加节点,则必须首先在索引 0、1 和 2 处添加节点。]

  • insert 方法没有 return 任何东西,因此捕获它的 return 值除了 None 之外不会给你任何其他东西。如果你真的想从中得到一些反馈,那么就像你对 remove 方法所做的那样:让它 return 相关节点。在那种情况下,您还应该让 add 具有 return 值。

这是一些工作代码,解决了上述问题以及更多问题:

class Node:
    def __init__(self, data):
        self.data = data
        self.next_node = None   # next_node neads to be an instance attribute, not a class attribute

    def __repr__(self):
        return "<Node data: {}>".format(self.data)


class LinkedList:
    def __init__(self):
        self.head = None

    def is_empty(self):
        return self.head == None  # Don't MAKE it empty!

    def size(self):
        current = self.head
        count = 0
        while current:
            count += 1
            current = current.next_node
        return count
    
    def add(self, data):
        new_node = Node(data)
        new_node.next_node = self.head
        self.head = new_node
        return new_node  # Return the new node

    def search(self, key):
        current = self.head
        while current:
            if current.data == key:
                return current
            else:
                current = current.next_node
        return None

    def insert(self, data, index):
        if index == 0:
            # Don't continue after this call to self.add
            return self.add(data)  # Return the new node
        current = self.head
        while index > 1 and current:  # Protect against out of range index
            current = current.next_node
            index -= 1
        if current:  # Protect against out of range index
            new_data = Node(data)
            # Make sure the new node gets a next_node assignment
            new_data.next_node = current.next_node
            current.next_node = new_data
            return new_data  # Return the new node

    def remove(self, key):
        current = self.head
        previous = None
        while current:
            if current.data == key:  # Check this only once per node
                if current == self.head:
                    self.head = current.next_node
                else:
                    previous.next_node = current.next_node
                break  # No need for variable - just exit
            previous = current           # Update previous
            current = current.next_node  # Move to next node
        return current

    def __repr__(self):
        nodes = []
        current = self.head
        while current:
            if current is self.head:
                nodes.append("[Head: {}]".format(current.data))
            elif current.next_node is None:
                nodes.append("[Tail {}]".format(current.data))
            else:
                nodes.append("[{}]".format(current.data))
            current = current.next_node
        return '-> '.join(nodes)

l = LinkedList()
l.add(1)
l.add(2)
l.add(3)
l.add(5)
l.add(6)
l.add(7)

length = l.size()
print("Size of list: {}".format(length))  # Size of list: 6

print(l)  # [Head: 7]-> [6]-> [5]-> [3]-> [2]-> [Tail: 1]

seek = l.search(7)
print("Found: {}".format(seek))  # Found: <Node data: 7>

node = l.insert(4, 3)
print("Inserted {}".format(node))  # Inserted: <Node data: 4>

gone = l.remove(1)
print("Removed: {}".format(gone))  # Removed: <Node data: 1>

# Note the insertion of '4' at index 3
print(l)  # [Head: 7]-> [6]-> [5]-> [4]-> [3]-> [Tail: 2]