在Python类方法中使用递归

时间:2010-08-12 09:07:02

标签: python

NB Noob警告......!

我试图在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)

这很好用:找到后继汽车功能会说汽车c2在汽车c1前面(位置4前面的位置7)。

然而,我希望汽车c1能够确定汽车在其直接继承者面前是什么 - 也就是说,哪辆车在前面的汽车前面,在这种情况下是汽车c3。我的想法是,如果我做c1_succ.findSuccessorCars(汽车),那么这应该工作正常:做类型(c1_succ)显示它是一个实例和hasattr显示它具有预期的对象属性。

但是,当我尝试执行c1_succ.findSuccessorCars(cars)时,会返回一个整数。因此,我很困惑 - 为什么这不起作用?为什么不能以这种方式递归执行类方法?这个整数来自哪里?

NB Gut觉得这与自我声明有关,而且我需要修改我的代码,以及全球汽车列表,需要有一个全球列表当前位置,或其他类方法,例如 findSuccessorsSuccessor(是的,完全了解crummy的命名!)。但是,我有兴趣理解为什么这种递归方法不起作用。

更新

以下是计算2辆车之间差距所需的代码 - 我很欣赏它是非常基本的,所以请不要在后面大笑。

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

        gap = otherCar.position_x - thisCar.position_x 

        return gap

2 个答案:

答案 0 :(得分:5)

你所谓的类方法实际上是一个实例方法。类方法在上运行,而实例方法在实例上运行。在这里,我们处理的是Car实例,而不是Car类本身。

class Car(object):
    def __init__(self, position, id, velocity):
        self.position = position
        self.id = id
        self.velocity = velocity

    def __eq__(self, other):
        return self.id == other.id

    def __str__(self):
        return 'Car(%d, %d, %d)' % (self.position, self.id, self.velocity)

    def calculateGap(self, other):
        return other.position - self.position

    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)

输出:

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

答案 1 :(得分:2)

你的方法确实在理论上有效;这是一个实现错误。也就是说,这不是正确的做事方式;具体而言,findSuccessorCar不应该是Car的类方法。这是因为Car实例列表是一个单独的构造;班级Car不会也不应该对此有任何了解。如果您想为其创建课程,则应制作一个Road的{​​{1}}列表,并将Cars放在其中。

那就是说,我不明白为什么你不能做到

findSuccessorCar

按位置顺序对汽车列表进行排序。我认为你正在实施自己的排序算法来寻找后继汽车?

其他注意事项:您应该使用例外(import operator cars.sort( key = operator.attrgetter( "position" ) ) )来表示失败,而不是魔术返回码; classmethods传统上使用raise BadCarMojoError而不是cls作为第一个参数;并且self应该继承自Car


object