Python:声明构造函数的灵活方式

时间:2011-11-14 22:20:00

标签: python constructor

为一个类声明多个构造函数的干净方法是什么?

例如,假设我有一个Item类。创建项目的一种方法(例如是)

item = Item(product_id, name, description,price)

另一种做同样事情的方法可能是

item = Item(otherItem)

然后另一种方法来做到这一点..也许在某些情况下我没有价格所以我想通过

item = Item(product_id, name,description)

而另一个案例可能是

item = Item(product_id,price)

我的另一个问题是: 有一些私有变量可能在运行时初始化。 假设我有一些随机变量itemCount,我想在内部跟踪它。

如何声明我不必将其置于初始化模式,而是在运行时的某个地方... 我可以做点像

self._count +=1

由于

3 个答案:

答案 0 :(得分:4)

提供多个构造函数的两种最常用方法是:

  1. class methods
  2. factory functions
  3. 以下是example taken from the standard library,其中显示collections.OrderedDict如何使用类方法将 fromkeys()作为备用类构造函数实现:

    @classmethod
    def fromkeys(cls, iterable, value=None):
        '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
        If not specified, the value defaults to None.
    
        '''
        self = cls()
        for key in iterable:
            self[key] = value
        return self
    

    作为另一种常见方法的示例,标准库中有factory function used in symtable.py

    class SymbolTableFactory:
        def __init__(self):
            self.__memo = weakref.WeakValueDictionary()
    
        def new(self, table, filename):
            if table.type == _symtable.TYPE_FUNCTION:
                return Function(table, filename)
            if table.type == _symtable.TYPE_CLASS:
                return Class(table, filename)
            return SymbolTable(table, filename)
    

答案 1 :(得分:1)

您可以使用默认参数:

class Item(object):

  def __init__(self, product_id = None, name = None, description = None, price = None)
      ... implementation ...

如果默认值不同,您可以使用None所需的任何值替换。

使用示例:

item1 = Item(product_id = 4, price = 13) # use the field name!
item2 = Item(name = "hammer", description = "used to belong to Thor")

对于复制构造函数item = Item(otherItem),@ Raymond对类方法和工厂函数的建议可能是最恐怖的方式。


更新:here's关于Python中多个构造函数的问题。它还提到使用*args**kwargs

答案 2 :(得分:1)

复制通常是通过实例上的copy()方法完成的,而不是通过提供“复制构造函数”,所以它是

item = other_item.copy()

而不是

item = Item(other_item)

您提到的所有其他构造函数签名都可以通过默认参数和关键字参数轻松处理:

def __init__(self, product_id, name=None, description=None, price=None):
    ...

如果你想要另一个具有完全不同代码的构造函数,而不是classmethod是正确的方法 - 请参阅Raymond Hettinger的答案。