我需要创建几个对象(通常是循环的)相互引用的对象。一般情况下,可能涉及多个对象,但这里有一个简单的例子,我只需要一对相互引用的汽车:
class Car:
def __init__(self, position, speed):
self.position = position
self.speed = speed
def set_reference(self, other_car):
self.other_car = other_car
# ...
def main():
# ...
car1 = Car(pos1, spd1)
car2 = Car(pos2, spd2)
car1.set_reference(car2)
car2.set_reference(car1)
没有引用另一辆车的汽车不是有效物品。理想情况下,我想从set_reference
方法中执行__init__
;这将更安全(没有使用无效对象的机会)和更清洁(所有初始化将在__init__
执行,如人们所料)。
有没有实现这一目标的简洁解决方案?我不介意一次创建一对汽车,但每辆汽车都是一个独立的实体,所以它需要一个独立的实例。
我也知道循环引用对于GC很麻烦;我会处理那个。
用例:
每辆车都作为另一辆车的备用。汽车实例是“聪明的”,即他们可以做很多工作。如果一个汽车实例不知道它的备份是很烦人的,因为它可以防止汽车完成动作,而不需要每次都从外面引用。
答案 0 :(得分:2)
我认为没有一种方法可以将set_reference()
电话转移到__init__()
,因为另一辆车可能还不存在。我可能会做这样的事情。
class Car:
def __init__(self, position, speed):
self.position = position
self.speed = speed
def set_reference(self, other_car):
self.other_car = other_car
@classmethod
def create_pair(cls, car1_args, car2_args):
car1 = cls(*car1_args)
car2 = cls(*car2_args)
car1.set_reference(car2)
car2.set_reference(car1)
return car1, car2
def main():
car1, car2 = Car.create_pair((pos1, spd1), (pos2, spd2))
以下是如何为更大的循环参考结构扩展相同的概念:
class Car:
# ...
@classmethod
def create_loop(cls, *args):
cars = [cls(*car_args) for car_args in args]
for i, car in enumerate(cars[:-1]):
car.set_reference(cars[i+1])
cars[-1].set_reference(cars[0])
return cars
然后你可以像这样(任意数量的汽车)调用它:
car1, car2, car3 = Car.create_loop((pos1, spd1), (pos2, spd2), (pos3, spd3))
您应该使用这样的参考设置:
>>> car1.other_car is car2 and car2.other_car is car3 and car3.other_car is car1
True
答案 1 :(得分:0)
如果您真的不想使用工厂方法,那么唯一真正的选择是强制用户以后配置它们。 (在评论中记录你所说的可能需要循环的依赖关系):
class Car:
def __init__(self, position, speed):
self.position = position
self.speed = speed
@staticmethod
def setup(*args):
for car, next in zip(args, args[1:]):
car.other_car = next
args[-1].other_car = args[0]
def main():
...
car1 = Car(pos1, spd1)
car2 = Car(pos2, spd2)
Car.setup(car1, car2)
另一种选择是拆分分组:
class CarGroup(list):
def other_car(self, car):
index = self.index(car)+1
index = 0 if index >= len(self) else index
return self[index]
class Car:
def __init__(self, position, speed, group):
self.position = position
self.speed = speed
self.group = group
self.group.append(self)
@property
def other_car(self):
return self.group.other_car(self)
def main():
...
group = CarGroup()
car1 = Car(pos1, spd1, group)
car2 = Car(pos2, spd2, group)
答案 2 :(得分:0)
我建议将汽车数据结构与引用一系列汽车的数据结构分开。 other_car
看起来并不像car
中严格属于的数据,而是代表一些可迭代的汽车序列。因此,最简单和最逻辑一致的解决方案是定义汽车,然后将其放入一系列汽车中。