在Python中实现双向关联关系

在Python中实现双向关联关系,python,oop,uml,class-diagram,bidirectional,Python,Oop,Uml,Class Diagram,Bidirectional,在Martin Fowler的“双向关联”一节中,他说: 在编程语言中实现双向关联通常有点棘手,因为 您必须确保两个属性保持同步。使用C#,我使用代码处理这些 实现双向关联的行: 书中的代码 class汽车。。。 法人所有者{ 获取{return\u owner;} 设置{ 如果(_owner!=null)_owner.friendCars()。删除(此项); _所有者=价值; 如果(_owner!=null)_owner.friendCars().Add(此); } } 私人业主; ... 班

在Martin Fowler的“双向关联”一节中,他说:

在编程语言中实现双向关联通常有点棘手,因为 您必须确保两个属性保持同步。使用C#,我使用代码处理这些 实现双向关联的行:

书中的代码

class汽车。。。
法人所有者{
获取{return\u owner;}
设置{
如果(_owner!=null)_owner.friendCars()。删除(此项);
_所有者=价值;
如果(_owner!=null)_owner.friendCars().Add(此);
}
}
私人业主;
...
班上人。。。
公车{
获取{return ArrayList.ReadOnly(_cars);}
}
公共无效添加车辆(车辆arg){
arg.Owner=这个;
}
私有IList_cars=新ArrayList();
内部IList friendCars(){
//只能由汽车使用。车主
归还车辆;
}
....
问题1:

我尝试在python中实现这一点(
get_cars()
in
Person
&
get_owner\u v2()
in Car),我想知道我的代码是否可以用来描述“双向关联”,如果不能,应该如何修改它来实现

注意:第一个版本(检查调用方的类/对象)运行良好,直到我开始独立创建car对象,并通过两个步骤将它们分配给所有者(最后4个print语句证明了这一点)。第二个版本使用许可证编号
lno
来确定所有者。我不确定我做的是否正确,但根据我的理解,它确实起作用了

我的实施:

#尝试反向双向关联
班长:
汽车和轿车=[]
定义初始化(self,name):
self.\uu cars=[]
self.\uu cars.append(“虚拟”)
self.\uu name=名称
def添加车(自身,*args,obj=None):
#进口检验
如果不是obj:
car_对象=car(*args)
其他:
car_对象=obj
Person.cars\u和lnos.append((car\u对象,self.\uu名称))
self.\u cars.append(car\u对象)
定义报告(自我):
返回f“{self.\u name}”
def get_车辆(自我):
返回自我
等级车:
汽车计数=0
定义初始(自身、lno、价格、年份、品牌、型号):
进口检验
自。u_lno=lno
自身价格=价格
自年=年
自制
self.\uuu model=模型
Car.Car\u计数+=1
self.\uuuu car\u id=car.car\u计数
如果inspect.getargvalues(inspect.stack()[1][0]).args中的“self”:
self.u owned_by=f“Car(ID:{self.u Car_ID})的所有者:{inspect.stack()[1][0].f_locals['self']},它是类的实例:{inspect.stack()[1][0].f_locals['self'.\uu Class.\uuu name}”
其他:
self.\uuu owned\u by=“这辆车不属于任何人。”
定义报告(自我):
返回f“Car ID:{self.\u Car\u ID}”
def get_规格(自身):
打印(f“+{'-'*30}+”)
打印(f)
Liscense编号:{self.\uu lno}
价格:{self.\u价格}
年份:{self.\u Year}
Make:{self.\u Make}
模型:{self.\u Model}
""")
@财产
def get_lno(自身):
返回自我
def get_owner_v1(自我):
#进口检验
返回自我。归自己所有
def get_owner_v2(自身):
如果Person.cars\u和\u lnos:
对于tup-in-Person.cars\u和\u-lnos:
如果self.\u lno==tup[0]。则获取\u lno:
return f“Car(ID:{self.\u Car\u ID})归:{tup[1]}所有,他是:{Person.\u name\u}类。”
return“[0]这辆车不是任何人的。”
其他:
return“[1]这辆车不是任何人的。”
所有者1=个人(“威廉”)
车主1.添加汽车(“4567781”,100002012,“丰田”,“科罗拉”)
车主1.添加车辆(“2137813”,80002010,“保时捷”,“GT3”)
owner1.get_cars()[1]。get_owner_v1()
打印(f“{owner1}拥有{len(owner1.get_cars())-1}Car)。”
打印(所有者1.get_cars()[1]。get_owner_v1())
打印(“===============================================================================”)
所有者2=个人(“笛福”)
车主2.添加车(“8729120”,100002012,“道奇”,“挑战者”)
打印(f“{owner2}拥有{len(owner2.get_cars())-1}Car)。”
打印(所有者2.get\u cars()[1]。get\u owner\u v1())
打印(“===============================================================================”)
car1=汽车(“7839291”、100002012、“雪佛兰”、“卡马罗”)
car2=汽车(“6271531”,100002012,“福特”,“野马”)
打印(car2.get_owner_v1())
打印(“===============================================================================”)
所有者3=个人(“Lyan”)
车主3.添加汽车(“656721”、9000013、“丰田”、“凯美瑞”)
车主3.添加汽车(“652901”,9000013,“日产”,“阳光”)
车主3.添加车(“870251”,9000013,“宝马”,“6系”)
打印(所有者3.get\u cars()[1]。get\u owner\u v2())
打印(所有者2.get\u cars()[1]。get\u owner\u v2())
打印(所有者1.get\u cars()[1]。get\u owner\u v2())
打印(“===============================================================================”)
car3=汽车(“5424201”,100002012,“大众”,“Eos”)
打印(car3.get_owner_v1())
打印(car3.get\u owner\u v2())
所有者4=个人(“达芙妮”)
所有者4.添加车辆(obj=car3)
打印(car3.get_owner_v1())
打印(car3.get\u owner\u v2())
问题2:

在本节中,他说这两种符号可能相同:

以下符号(未指定任何箭头)是否也可以视为双向关系

编辑:


我知道对类图的逻辑细化应该是*to*(多对多),但我只关心我的实现对描述/设计的正确性,以及如何改进它,以及无箭头关联线在图中的位置。

Q2:是的。无箭头表示未指定。这意味着可以航行。UML 2.5第18页:

  • 箭头符号用于表示关联结束可导航性。根据定义,所有类拥有的关联端点都是可导航的。按照惯例,元模型中所有关联拥有的端都不是