看起来 这个 或 这个 是有些相关的线程,但仍然没有弄清楚:)
我正在尝试创建 namedtuple
的子类并提供不同的初始值设定项,以便我可以用不同的方式构造对象。例如:
>>> from collections import namedtuple
>>> class C(namedtuple("C", "x, y")) :
... __slots__ = ()
... def __init__(self, obj) : # Initialize a C instance by copying values from obj
... self.x = obj.a
... self.y = obj.b
... def __init__(self, x, y) : # Initialize a C instance from the parameters
... self.x = x
... self.y = y
但是,这不起作用:
>>> c = C(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __init__
AttributeError: can't set attribute
经过一些探索(例如,参见 这个 线程),我尝试使用构造函数而不是初始化器:
>>> from collections import namedtuple
>>> class C(namedtuple("C", "x, y")) :
... __slots__ = ()
... def __new__(cls, obj) :
... self = super(C, cls).__new__(cls, obj.a, obj.b)
... def __new__(cls, x, y) :
... self = super(C, cls).__new__(cls, x, y)
这似乎构造了一个对象,但后来我无法读取它的属性:
>>> c = C(1,2)
>>> c.x, c.y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'x'
我哪里错了?如何创建具有多个构造函数或初始化器的子类?
原文由 Jens 发布,翻译遵循 CC BY-SA 4.0 许可协议
命名元组是不可变的,因此您不能在
__init__
初始值设定项中操作它们。您唯一的选择是覆盖__new__
方法:请注意,因为
__new__
是新实例的工厂方法,所以您需要 返回 新创建的实例。如果您不在__new__
方法中使用return
--- ,则默认返回值为None
,这会给您带来错误。带有
x
和y
属性的对象的演示:Python 不支持方法重载;通常,您要么使用可选的关键字参数,要么使用额外的类方法作为工厂方法。
datetime
模块,例如,有几个这样的工厂方法让你创建不适合标准构造函数的对象。datetime.datetime.fromtimestamp()
从单个数值创建一个datetime.datetime
实例,datetime.datetime.fromordinal()
也是如此;除了他们以不同的方式解释数字。如果您想支持可变参数,请执行以下操作:
此处,
y
是一个可选参数,默认为None
如果调用者未提供:使用类方法的替代方法是:
现在有两种工厂方法;一个默认值和一个命名: