我目前正在 LinkedList 上工作,我有以下代码,但我不明白
__iter__
和 __repr__
到底在做什么?
class Node:
def __init__(self, value):
self.value = value
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def append(self, value):
if self.head is None:
self.head = Node(value)
return
node = self.head
while node.next:
node = node.next
node.next = Node(value)
def __iter__(self):
node = self.head
while node:
yield node.value
node = node.next
def __repr__(self):
return str([v for v in self])
我在这里创建 LinkedList 并将值附加到列表末尾。
llist = LinkedList()
for value in [4,2,5,1,-3,0]:
llist.append(value)
如果我打印列表
print(llist)
那么我会得到[4, 2, 5, 1, -3, 0]
我猜这是来自
__iter__
和__repr__
。我不明白的是我的 __iter__
和 __repr__
何时启动,哪个先运行?如何打印班级外的对象?
根据我对 Python 内部结构的有限理解,当您
print()
一个对象时,会在其上调用 str()
函数。这个函数可能知道如何格式化某些类型的对象,例如字符串和数字,对于其他对象,它调用它们的 __repr__()
方法,该方法应该返回一个字符串。所以首先调用 __repr__()
。
__repr__()
方法由开发人员编写,用于返回由列表理解[v for v in self]
创建的普通列表表示形式。迭代最终调用 __iter__()
方法,它是一个生成器函数(如使用 yield
所示)。此函数迭代列表的元素,每个 yield
都会使一个元素可供 for ... in ...
构造使用。
阅读文档。
iter:定义什么属性/如何迭代类的对象应该工作 - 例如什么是“下一步”。如果您想说对动物进行迭代,并且希望迭代由每个动物的体重定义,那么您可以在动物类中使用 self.weight,就像您现在使用 self.value 一样...... .
_ repr _:当你执行 print(my_Object) 时,Python 默认会定义一个表示 (repr)。您可以使用此功能重新定义。
当您实现 iter 方法时,您正在更改循环列表的行为。
我的意思是当你调用时在正常的 for 循环中:
for l in list:
print(l)
这就是幕后会发生的事情:
# create an iterator object from that iterable
iter_obj = iter(list)
# infinite loop
while True:
try:
# get the next item
element = next(iter_obj)
# do something with element
except StopIteration:
# if StopIteration is raised, break from loop
break
因此,如果您在链表类中重新定义 iter 函数,您将重新定义迭代函数以及应该迭代迭代器返回的内容。
与 repr 基本相同,您重新定义对象的表示。例如,当您调用 print(obj) 时,您会打印出 obj,但如果您按照自己的意愿正确实现了 repr,则可以将其更改为您想要的格式。
请查看此处以获取更多说明: https://www.programiz.com/python-programming/iterator https://www.pythonforbeginners.com/basics/str-vs-__repr
__iter__
表示类的迭代器方法。我们通过代码来理解一下:
llist = LinkedList()
for value in [4,2,5,1,-3,0]:
llist.append(value)
for value in llist:
print(value)
输出
4
2
5
1
-3
0
这里,当我们将对象作为迭代器时,
__iter__()
方法将起作用,迭代并遍历链表并产生节点值。
print(llist)
输出
[4, 2, 5, 1, -3, 0]
在这里,
__repr__()
方法将起作用并打印代码中指定的节点值。
例如
`class Node:
def __init__(self, value):
self.value = value
self.next = None
def __str__(self):
if self.next is not None:
return "Node\n value: %d \t next.value: %s " % (self.value, self.next.value)
else:
return "Node\n value: %d " % (self.value)
head = Node(34)
head.next = Node(38)
print(head)`
结果:
Node value: 34 next.value: 38
在这个例子中,我们添加了一个str()函数,当打印出Company类的实例时,输出是employee_st。但是,我们没有显式调用 str() 函数,因为在实例上使用 print() 函数时,Python 的内部机制会自动调用 str() 函数。
类内部有很多像str()这样的函数,我们统称为魔术函数。现在,我们来明确一下魔法函数的类别: 魔术函数是指类中以双下划线开头并以双下划线结尾的函数。在特定的时间,Python会自动调用这些函数。魔法函数不是通过继承或其他机制获得的,但是一旦定义了一个类,Python的内部机制会自动将这些特殊函数分配给该类,并且用户无法创建魔法函数,即使函数名称以双下划线开头和结尾。通过神奇的功能,可以实现很多个性化、便捷的操作。