我已经编写了一个实例方法,它使用递归找到一个特定的解决方案。它的工作非常好,除了我退出if-elif块的时候。我在IF块中调用函数本身。另外,我只有一条返回语句。这个方法的输出对我来说很奇怪。下面是代码和输出:
def create_schedule(self):
"""
Creates the day scedule for the crew based on the crew_dict passed.
"""
sched_output = ScheduleOutput()
assigned_assignements = []
for i in self.crew_list:
assigned_assignements.extend(i.list_of_patients)
rest_of_items = []
for item in self.job.list_of_patients:
if item not in assigned_assignements:
rest_of_items.append(item)
print("Rest of the items are:", len(rest_of_items))
if len(rest_of_items) != 0:
assignment = sorted(rest_of_items, key=lambda x: x.window_open)[0]
# print("\nNext assignment to be taken ", assignment)
output = self.next_task_eligibility(assignment, self.crew_list)
if len(output) != 0:
output_sorted = sorted(output, key=itemgetter(2))
crew_to_assign = output_sorted[0][1]
assignment.eta = output_sorted[0][4]
assignment.etd = int(assignment.eta) + int(assignment.care_duration)
crew = next((x for x in self.crew_list if x.crew_number == crew_to_assign), None)
self.crew_list.remove(crew)
crew.list_of_patients.append(assignment)
crew.time_spent = assignment.etd
self.crew_list.append(crew)
self.create_schedule()
else:
print("*" * 80, "\n", "*" * 80, "\nWe were not able to assign a task so stopped.\n", "*" * 80, "\n", "*" * 80)
sched_output.crew_output = self.crew_list
sched_output.patients_left = len(rest_of_items)
elif not rest_of_items:
print("Fully solved.")
sched_output.crew_output = self.crew_list
sched_output.patients_left = 0
print("After completely solving coming here.")
return sched_output这是产出:
Rest of the items are: 10
Rest of the items are: 9
Rest of the items are: 8
Rest of the items are: 7
Rest of the items are: 6
Rest of the items are: 5
Rest of the items are: 4
Rest of the items are: 3
Rest of the items are: 2
Rest of the items are: 1
Rest of the items are: 0
Fully solved.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.我不明白的是,一旦列表rest_of_items为空,我就将数据分配给sched_output并返回它。但是,执行print语句的时间与执行递归的时间相同。我怎么才能避免这种情况?
我的输出很好。我只想了解这种行为的原因,以及如何避免这种行为。
发布于 2018-03-30 17:43:40
当您在函数完成之前在其内部调用您的create_schedule函数时,一旦它已经结束并且不需要再次调用它自己,每个函数就会结束,并在函数的末尾点击“在完全求解之后”。
这意味着每个函数在调用自身之后仍然在运行--只停留在它调用自己的行上--直到它们都完成为止,这时暂停的函数可以完成它们的任务,打印出您的语句。
发布于 2018-03-30 17:46:38
它打印11次的原因是,您总是在函数的末尾调用print,并且调用该函数11次。(这和你获得Rest of the items are: … 11次的原因是一样的,这一点应该更明显。)
通常,最好的解决方案是重新设计东西,而不是在函数中执行“副作用”(如print ),您只需返回一个值,然后调用方就可以对结果执行它想要的任何副作用。在这种情况下,您调用print 11次并不重要;print只在调用方中发生一次。
如果这是不可能的,您可以更改这一点,以便您只在堆栈顶部时进行print处理。但是,在许多递归函数中,没有明显的方法可以在不传递更多信息的情况下解决这一问题:
def create_schedule(self, depth=0):
# etc.
self.create_schedule(depth+1)
# etc.
if not depth:
print('After completely solving come here.')
returns sched_output最后的方法是只包装递归函数,如下所示:
def _create_schedule(self):
# etc.
self._create_schedule()
# etc.
# don't call print
return sched_output
def create_schedule(self):
result = self._create_schedule()
print('After completely solving come here.')
return result这通常只有在您需要为递归过程做一些一次性设置时才有必要,但是这里您想要做一些一次性的后处理,这基本上是相同的问题,所以可以用同样的方式解决。
(当然,这只是第一个伪装的解决方案,但它隐藏在create_schedule的实现中,因此您不需要更改调用方看到的接口。)
发布于 2018-03-30 17:47:47
递归函数的末尾有print("After completely solving coming here.")。该行将对每个递归执行一次。
考虑一下这个简单的例子,它重新创建了您的问题:
def foo(x):
print("x = {x}".format(x=x))
if x > 1:
foo(x-1)
print("Done.")现在调用该函数:
>>> foo(5)
x = 5
x = 4
x = 3
x = 2
x = 1
Done.
Done.
Done.
Done.
Done.如您所见,在对foo(x=0)的最后调用中,它将打印"Done."。此时,函数将返回到以前的调用,该调用还将打印"Done."等。
https://stackoverflow.com/questions/49578862
复制相似问题