Python中的for循环问题

1 投票
3 回答
513 浏览
提问于 2025-04-15 20:25

这段代码的目的是根据self.order中的字符顺序来对self.array里的项目进行排序。这个排序的方法在前两次运行得很好,但到了第三次的时候,似乎出现了问题,for循环好像无限重复下去。到底发生了什么呢?

补充说明:我在做自己的排序函数,因为这是我Python作业的一个加分部分。

class sorting_class:
    def __init__(self):
        self.array = ['ca', 'bd', 'ac', 'ab'] #An array of strings
        self.arrayt = []
        self.globali = 0
        self.globalii = 0
        self.order = ['a', 'b', 'c', 'd'] #Order of characters
        self.orderi = 0
        self.carry = []
        self.leave = []
        self.sortedlist = []
    def sort(self):
        for arrayi in self.arrayt:  #This should only loop for the number items in self.arrayt. However, the third time this is run it seems to loop indefinitely. 
            print ('run', arrayi)   #Shows the problem
            if self.order[self.orderi] == arrayi[self.globali]:
                self.carry.append(arrayi)
            else:
                if self.globali != 0:
                    self.leave.append(arrayi)
    def srt(self):
        self.arrayt = self.array
        my.sort() #First this runs the first time.
        while len(self.sortedlist) != len(self.array):
            if len(self.carry) == 1:
                self.sortedlist.append(self.carry)
                self.arrayt = self.leave
                self.leave = []
                self.carry = []
                self.globali = 1
                self.orderi = 0
                my.sort()
            elif len(self.carry) == 0:
                if len(self.leave) != 0: #Because nothing matches 'aa' during the second iteration, this code runs the third time"
                    self.arrayt = self.leave
                    self.globali = 1
                    self.orderi += 1
                    my.sort()
                else:
                    self.arrayt = self.array
                    self.globalii += 1
                    self.orderi = self.globalii
                    self.globali = 0
                    my.sort()
                    self.orderi = 0
            else: #This is what runs the second time.
                self.arrayt = self.carry
                self.carry = []
                self.globali += 1
                my.sort()
my = sorting_class()  
my.srt()

3 个回答

1

你有一行代码 self.arrayt = self.leave,这意味着 arraytleave 指向的是同一个数组(这不是内容的复制!),然后在循环 for arrayi in self.arrayt: 中,你执行了 self.leave.append(arrayi),这会让 self.leave 的长度增加,而 self.leave 其实就是你正在循环的 self.arrayt 的另一个名字。对正在循环的列表进行添加操作,很容易导致无限循环。

这只是代码混乱的一个表现。我建议你使用内置的 sort 方法来进行排序,把精力放在定义合适的 key= 提取函数上,这样可以让你想要的排序方式实现——这更有效率。

1

在你循环的第三次运行时,你正在往正在遍历的列表中添加新元素,所以你永远无法跳出这个循环:
self.arrayt = self.leave - 这个赋值操作导致 self.leave.append(arrayi) 会把元素添加到 self.arrayt 所指向的列表中。

一般来说,你可以考虑创建列表的副本,而不是让不同的变量或成员指向同一个列表。

1

Alex提到的这个关键提取器其实很简单,可以用一个lambda函数来实现。

>>> array = ['ca', 'bd', 'ac', 'ab']
>>> order = ['a', 'b', 'c', 'd']
>>> sorted(array, key=lambda v:map(order.index,v))
['ab', 'ac', 'bd', 'ca']

>>> order = ['b', 'a', 'c', 'd']
>>> sorted(array, key=lambda v:map(order.index,v))
['bd', 'ab', 'ac', 'ca']

>>> order = ['d', 'c', 'b', 'a']
>>> sorted(array, key=lambda v:map(order.index,v))
['ca', 'bd', 'ac', 'ab']

我们来看看这是怎么工作的:

map会对v中的每个元素调用order.index这个方法,然后把返回的结果用来创建一个列表。
v会是array中的某个元素。

>>> order = ['a', 'b', 'c', 'd']
>>> map(order.index,array[0])
[2, 0]
>>> map(order.index,array[1])
[1, 3]
>>> map(order.index,array[2])
[0, 2]
>>> map(order.index,array[3])
[0, 1]

这个函数作为key=参数提供给排序,所以实际上是对那些列表进行排序,而不是对字符串进行排序。

撰写回答