Python:如何将这2个重载的构造函数合并到1个构造函数中

时间:2010-12-20 23:27:34

标签: python sql

我有一个名为Portfolio& amp;现在我有2个构造函数(虽然我刚刚发现你在python中无法重载函数)所以我必须合并这两个构造函数

我是一名经验丰富的python程序员,但这两个非常矛盾的合并构造函数确实是我的头脑! :P

第一个构造函数:
+目的是创建一个.db文件&初始化类变量
- 初始化类成员变量
- 检查具有路径和名称db_path的文件是否存在:如果存在,我们退出coz我们不想覆盖现有数据库,因此我们返回无 - 我们创建数据库(sql数据库)&设置必要的表格 - 导入投资组合数据(创建日期等)

第二个构造函数:
+目的是从现有的sql数据库文件导入所有库存数据&初始化变量
- 初始化类成员变量
- 检查具有路径和名称db_path的文件是否存在:如果不存在,我们退出coz,我们不想覆盖现有数据库,因此我们返回无 - 我们将该函数称为从数据库中导入所有股票 - 导入投资组合数据(创建日期等)

如何合并这两个构造函数,呃,为什么python不允许重载

class Portfolio:
""" Portfolio class implementation """

# Class Variables:

# self.db_path
# self.app_parent
# self.tracking_stocks
# self.registered_stocks
# self.total_purchase_exp
# self.ytd_roi
# self.cash_reserve


# Class Functions:

def __init__( self, _app_parent, _db_path, stock_list ):
    """ Constructor: """

    self.db_path            = _db_path
    self.app_parent         = _app_parent
    self.tracking_stocks    = []
    self.registered_stocks  = []
    self.total_purchase_exp = 0
    self.ytd_roi            = 0
    self.cash_reserve       = 500

    if database_exists( self.db_path ):
        return None

    self.create_database()
    self.import_portfolio_data()

    for stock_data in stock_list:

        self.add_stock( stock_data )


def __init__( self, _app_parent, _db_path ):
    """ Constructor: """

    self.db_path            = _db_path
    self.app_parent         = _app_parent
    self.tracking_stocks    = []
    self.registered_stocks  = []
    self.total_purchase_exp = 0
    self.ytd_roi            = 0
    self.cash_reserve       = 500

    if not self.database_exists( self.db_path ):
        return None

    self.import_portfolio_data()
    self.import_stocks()

3 个答案:

答案 0 :(得分:2)

为什么这一切都必须在构造函数中发生?

您可以构建对象,然后在其上调用单独的方法以导入库存列表或创建数据库。

Builder pattern中的内容包装起来可能适合您现有的设计。

答案 1 :(得分:1)

def __init__(self, _app_parent, _db_path, stock_list=None):
    self.db_path            = _db_path
    self.app_parent         = _app_parent
    self.tracking_stocks    = []
    self.registered_stocks  = []
    self.total_purchase_exp = 0
    self.ytd_roi            = 0
    self.cash_reserve       = 500

    if stock_list:
        if database_exists( self.db_path ):
            return None
        self.create_database()
        self.import_portfolio_data()
        for stock_data in stock_list:
            self.add_stock( stock_data )
    else:
        if not self.database_exists( self.db_path ):
            return None

        self.import_portfolio_data()
        self.import_stocks()

大多数都是复制粘贴的,所以我无法证明缩进的准确性等,但这是在Python中创建通用__init__方法的一般模式(注意{{1本身不是构造函数,它是一个初始化器)。由于Python支持关键字args和关键字args的默认值,因此没有理由使用重载(实际上,我们通过不进行重载来节省大量重复代码)。相反,我们只使用关键字arg stock_list,默认值为None。

这也没有完全修复;一些问题仍然存在(因为它是复制粘贴的)。我不知道构造函数的细节,但我认为通过更多的重构,你可以设置__init__更短更优雅的东西(考虑将初始化的部分分成几部分)方法,如__init__,并调用来自_init_db()的方法。

答案 2 :(得分:1)

我会使用class methods来处理不同的情况。这实际上是适用于Python的C++ Named Constructor习语的变体。您可以调用类方法来根据需要创建实例,而不是调用构造函数目录。以下是我对此进行编码的方法:

class Portfolio:
    def __init__(self, app_parent, db_path):
        """Create a fully initialized and empty instance."""
        self.db_path = db_path
        self.app_parent = app_parent
        self.tracking_stocks = []
        self.registered_stocks = []
        self.total_purchase_exp = 0
        self.ytd_roi = 0
        self.cash_reserve = 500

    @classmethod
    def new_database(cls, app_parent, db_path, stock_list):
        """Create a Portfolio instance wrapped around a new database and
        initialize it with ``stock_list``.  If a database already exists at
        ``db_path``, then an exception is thrown."""
        instance = cls(app_parent, db_path)
        if database_exists(instance.db_path):
            raise Exception('Database already exists at '+instance.db_path)
        instance.create_database()
        instance.import_portfolio_data()
        for stock_data in stock_list:
            instance.add_stock(stock_data)
        return instance

    @classmethod
    def from_database(cls, app_parent, db_path):
        """Create a Portfolio instance from the database located at
        ``db_path``.  If the database does not exist, then an exception
        is thrown."""
        instance = cls(app_parent, db_path)
        if not database_exists(instance.db_path):
            raise Exception('Database does not exist at '+instance.db_path)
        instance.import_portfolio_data()
        instance.import_stocks()
        return instance

用法很简单:

new_portfolio = Portfolio.new_database('/data/port.db')
existing_portfolio = Portfolio.from_database('/data/port.db')

从可用性和可维护性的角度来看,有一些非常重要的事情。首先,使用类实例参数(cls)在命名构造函数而不是类中创建新实例。我可以使用instance = cls(...)而不是instance = Portfolio(...)。如果向Portfolio添加子类并调用其中一个类方法,则会中断。

第二个(也可能更重要)一点是,您应该使用异常而不是在出现错误时返回None。它更像 pythonic ,一般来说更安全。