【问题标题】:Parent/children class structure in pythonpython中的父/子类结构
【发布时间】:2019-10-24 07:07:38
【问题描述】:

我目前正在开发一种具有多个计算级别的定价工具。

例如,我有一个对象 Quote,它本身附有一个或多个 QuoteItem。

我认为应该有类继承,但我不想在每次创建 QuoteItem 时都初始化我的 Quote,因为所有 QuoteItem 共享具有相同特征的完全相同的 Quote。

该类继承与超类吗?还是应该是2个独立的班级? 我找不到任何关于我认为很常见的场景的文档或资源。

我有一个附加到一个报价单的报价单列表,我想先创建报价单,然后再创建报价单。如果我从引用项开始,我觉得它每次都会创建一个完全不是预期行为的引用,因为我的所有引用项应该只有一个引用。

这是正确的做法吗?

class Quote():
    def __init__():
        # this will set parameter global to the quote
        print('Quote created')


class QuoteItem(Quote):
    def __init__():
        # this will set specific details for all quote items attached to one specific quote
        print ('QuoteItem created')

或者这两个类应该完全独立吗?

欢迎提供有关此类场景的任何用例或文档。 我发现的父/子类文档只处理非常相似的对象。在我的示例中,它们是不同的,它们是子项,即没有引号就不能存在引号。

谢谢

【问题讨论】:

    标签: python class inheritance superclass


    【解决方案1】:

    在考虑继承时,您使用的是“is-a”关系。

    class Vehicle(object):  # a Vehicle IS AN object
        pass
    class Car(Vehicle):     # a Car     IS A  Vehicle
        pass
    class Sedan(Car):       # A Sedan   IS A  Car
        pass
    

    您可能在报价及其项目中寻找的是“具有”关系。

    class Tire(object):     # a Tire IS AN object, but...
        pass
    
    class Vehicle(object):
        def __init__(self, num_tires=4):
            self.tires = [Tire() for _ in num_tires]
                            # a Vehicle HAS A Tire  (or in this case 4 tires)
    

    为您的特定用例扩展隐喻:

    class QuoteItem(object):
        def __init__(self, modelnumber, quantity, totalprice):
            self.modelnumber = modelnumber
            self.quantity = quantity
            self.totalprice = totalprice
            # I'm guessing at what you'd want here
    
    
    class Quote(object):
        _last_quote_number = 0
    
        @property
        @classmethod
        def next_quote_number(cls) -> int:
            cls._last_quote_number += 1
            return cls._last_quote_number
    
        def __init__(self, customerid):
            self.number = self.next_quote_number
            self.customerid = customerid
            self.items = []
    
        def add_item(self, modelnumber, quantity, totalprice) -> None:
            item = QuoteItem(modelnumber, quantity, totalprice)
            self.items.append(item)
    
    

    【讨论】:

    • 非常清楚,谢谢!这回答了我关于如何创建子项的观点。我从 Quote 类中调用一个方法,该方法将调用 QuoteItem 类。我不确定这是最佳做法,但现在很好。如果一次要创建多个引用项,我该怎么办?我应该发送一个列表并让 Quote 中的方法将列表转换为 for 循环吗?还是应该在 QuoteItem 列表中进行分解?还是应该在调用 add_item 方法时进行 for 循环?
    • 我过去使用的是创建另一个classmethod,它本质上是一个替代构造函数,它足够聪明,可以执行解析列表(或从 csv 等读取)之类的操作。然后该方法将执行quoteitem = cls(customerid); for modelnumber, quantity, totalprice in parsed_item_details: quoteitem.add_item(modelnumber, quantity, totalprice); return quoteitem。然后你可以使用quote = Quote.yournewclassmethod(customerid, list_of_items)从你的项目列表中创建一个Quote
    【解决方案2】:

    在这里使用继承并不是最好的方法。只需让Quote 拥有一个包含所有 QuoteItem 的容器(例如一个列表)。

    当使用这样的继承时,你说QuoteItemQuote 的一种特殊类型,但它不是。 QuoteItemQuote 的一部分。

    【讨论】:

    • 好的,很清楚,谢谢!就概念而言,如何在我的 QuoteItem 类中调用构造函数?我应该有另一个主类,它首先初始化 Quote,然后是 QuoteItem ?我正在考虑在 Quote 类中放置一个方法,该方法将初始化所有引用项并循环遍历它们,这看起来正确吗?菜鸟问题,什么是容器?
    • @yeye 这取决于您想要实现的目标。您可能希望Quote 创建QuoteItem
    • @yeye 容器是包含任意数量其他对象的任何对象。见stackoverflow.com/questions/11575925/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-14
    • 1970-01-01
    • 2015-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多