使用 Python 类方法进行递归

69 阅读3分钟

在 Python 类方法中使用递归时遇到了问题,具体表现为:

  • 试图在 Python 类方法中使用递归,但结果有限。
  • 正在尝试构建一个车类,具有非常基本的属性:id、单车道位置(用整数表示)和速度。
  • 其中一个函数用于返回该车紧跟在后面的车的 id -- 即如果我们有类:
class Car:
    def __init__(self, position, id, velocity):
        self.position = position
        self.id = id
        self.velocity = velocity
  • 现在,想出了以下类方法(更多详细信息在代码下方):
def findSuccessorCar(self, cars):

    successorCar = ""
    smallestGapFound = 20000000 

    for car in cars:
        if car.id == self.id: continue

        currentGap = self.calculateGap(car)

        if (currentGap > -1) and (currentGap < smallestGapFound):
            smallestGapFound = currentGap
            successorCar = car

    if successorCar == "":
        return 1 # calling code checks for 1 as an error code
    else:        
        return successorCar
  • 计划创建汽车对象,然后将它们存储在一个列表中。
  • 每次调用 findSuccessorMethod 时,都会将这个汽车的全局列表传递给它,例如:
    c1 = testCar.Car(4, 5, 1) # position, pos_y, Vel, ID
        c2 = testCar.Car(7, 9, 2)
        c3 = testCar.Car(9, 1, 2)
        cars = [c1, c2, c3]

        c1_succ = c1.findSuccessorCar(cars)
  • 这工作得很好:find successor car 函数会说汽车 c2 位于汽车 c1 的前面(位置 7 位于位置 4 的前面)。

  • 但是,希望汽车 c1 找出紧跟在它直接的后继的汽车 -- 也就是哪个汽车位于前面的汽车的前面,在这种情况下是汽车 c3。

  • 我的想法是,如果我执行 c1_succ.findSuccessorCars(cars) 那么这应该可以正常工作:执行 type(c1_succ) 显示它是一个实例,而 hasattr 显示它具有预期的对象属性。

  • 然而,当我确实尝试执行 c1_succ.findSuccessorCars(cars) 时,返回了一个整数。因此,我感到困惑 -- 为什么这不起作用?为什么不能以这种方式递归执行类方法?这个整数是从哪里来的?

  • 直觉告诉我这与 self 声明有关,并且我需要修改代码,以便除汽车的全局列表外,还需要一个它们当前位置的全局列表,或另一个类方法,例如 findSuccessorsSuccessor(是的,我完全意识到命名不当!)然而,有兴趣了解为什么这种递归方法不起作用。

  • 下面是计算两辆汽车之间间隙的请求代码 -- 我很感激它非常基本,所以请不要在后面大笑。

    def calculateGap(self, car):
        ''' Calculate the gap between two cars
        '''
        thisCar = self
        otherCar = car

        gap = otherCar.position_x - thisCar.position_x 

        return gap
  1. 解决方案
  • 正在尝试使用实例方法而不是类方法。类方法作用于类,实例方法作用于实例。
  • 在这里,正在处理 Car 实例,而不是 Car 类本身。
  • 正确的方法是使用实例方法,而不是类方法。
  • 实例方法可以使用 self 作为第一个参数,self 是实例的引用。
  • 类方法可以使用 cls 作为第一个参数,cls 是类的引用。
  • 可以使用以下代码来实现:
class Car:
    def __init__(self, position, id, velocity):
        self.position = position
        self.id = id
        self.velocity = velocity

    def findSuccessor(self, cars):
        ret = smallestGap = None
        for car in cars:
            if car == self:
                continue
            gap = self.calculateGap(car)
            if gap < 0:
                continue
            if smallestGap is None or gap < smallestGap:
                ret, smallestGap = car, gap
        return ret

    def findNthSuccessor(self, n, cars):
        cur = self
        for x in xrange(n):
            cur = cur.findSuccessor(cars)
            if cur is None:
                return None
        return cur

c1 = Car(4, 5, 1)
c2 = Car(7, 9, 2)
c3 = Car(9, 1, 2)
cars = [c1, c2, c3]

print c1.findSuccessor(cars)
print c1.findSuccessor(cars).findSuccessor(cars)
print c1.findNthSuccessor(2, cars)

Output:
Car(7, 9, 2)
Car(9, 1, 2)
Car(9, 1, 2)