OOP中类间关联的正确实现及Python代码优化咨询
OOP类间关联问题解答
问题背景
我是OOP新手,正尝试掌握正确的编程风格。目前我在用三个类:父类Person、子类Customer,还有第三个类BillFormular,需要实现类间的数据关联。我懂关系型数据库的概念,但不确定要不要在某个类里用类似外键的方式来灵活关联其他类。如果不想集成外部数据库,是不是应该改用字典?请看看我代码里的注释:
#Inheritance Person -> Customer class Person: def __init__(self, person_id, firstname): self.person_id = person_id self.firstname = firstname # ... class Customer(Person): def __init__(self, person_id, firstname, customer_level): super().__init__(person_id, firstname) self.customer_level = customer_level # ... def get_customer_level(self): return self.customer_level class BillFormular(): def __init__(self, bill_id, customer_id, is_paid=False): self.bill_id = bill_id # currently i store the customer_id (as some kind of secondary key for # the person_id in the inhereting BillFormular(Person)-Class, as i don´t # have a relational database. Is that a good way? self.customer_id = customer_id self.is_paid = is_paid # ... def print_bill(self): # the Argument 'judith' works, if i want to connect the other classes methods # But how to make it more flexible, e. g. by using the stored 'customer_id' # in the BillFormular(Person)-Class and the 'person_id' in the Person-Class print(f'Your Status from external class: {Customer.get_customer_level(judith)}') judith = Customer(22, 'Judith', 3) bill42 = BillFormular(42, 22) bill42.print_bill()
具体疑问
- 当前在BillFormular类中存储customer_id(作为Person类person_id的类似外键),这种方式是否合理?
- print_bill方法中目前直接传入实例judith才能调用方法,如何利用存储的customer_id和Person类的person_id实现更灵活的调用?
解答
1. 存储customer_id作为关联标识是否合理?
完全合理。这是内存中模拟关系型数据库外键的常用方案,尤其在不依赖外部数据库的场景下:
- 它能清晰建立账单与客户的关联关系,逻辑和数据库外键一致,容易理解和维护。
- 相比直接持有Customer实例引用,存储id可以避免潜在的循环引用问题,也更灵活(比如实例可以暂时销毁后重建,只要id不变就能重新关联)。
- 注意要保证
customer_id的唯一性,确保每个id都对应一个有效的Customer实例。
2. 如何利用customer_id实现灵活调用?
你需要一个实例注册表(用字典实现),用来存储所有Customer实例,key是person_id/customer_id,value是实例本身。这样BillFormular就能通过存储的customer_id从字典中找到对应实例,无需手动传递。
修改后的代码示例:
# 继承关系 Person -> Customer class Person: def __init__(self, person_id, firstname): self.person_id = person_id self.firstname = firstname # ... class Customer(Person): # 用类变量作为全局注册表,存储所有Customer实例 customer_registry = {} def __init__(self, person_id, firstname, customer_level): super().__init__(person_id, firstname) self.customer_level = customer_level # 实例化时自动注册到注册表 Customer.customer_registry[person_id] = self # ... def get_customer_level(self): return self.customer_level class BillFormular(): def __init__(self, bill_id, customer_id, is_paid=False): self.bill_id = bill_id self.customer_id = customer_id self.is_paid = is_paid # ... def print_bill(self): # 通过customer_id从注册表获取对应实例 customer = Customer.customer_registry.get(self.customer_id) if customer: print(f'Your Status from external class: {customer.get_customer_level()}') else: print(f'未找到ID为{self.customer_id}的客户') judith = Customer(22, 'Judith', 3) bill42 = BillFormular(42, 22) bill42.print_bill()
额外说明:
- 这里用Customer类的类变量
customer_registry作为注册表,每个Customer实例创建时自动完成注册,无需手动维护。 - 你也可以单独定义一个全局字典(比如
all_customers = {}),在创建Customer实例时手动添加,效果相同。 - 这种方式既保留了类似外键的关联逻辑,又实现了松耦合的实例调用,符合OOP设计原则。
内容的提问来源于stack exchange,提问作者Marcel
相关产品推荐
相关产品推荐

