我正在尝试创建一个父类 -
Car
,它将能够自动分配一个唯一的 id(使用 uuid.uuid4()
),一个 created_at
属性和一个 updated_at
属性(都使用 datetime
和 dateutil
模块)到将通过我的父类的子类创建的任何对象。
例如:当我的子类
honda_civic()
的对象(Honda
)被创建时,它继承了我的Car
父类,honda_civic
会自动分配一个唯一的id,那么它也会有创建时间和更新时间,以及Honda
子类中定义的其他属性和方法。
根据我目前的研究,我知道我需要在父类
__new__
的__init__
或Car
方法中定义这些属性(我有待更正)。但是,我正在努力弄清楚他们中的哪些人应该有定义。
我知道
__new__
方法控制对象创建,而__init__
方法控制对象实例化。我现在的困惑是,如果我在 __init__
方法下定义属性,那是否意味着每次创建对象时都必须将属性作为参数传递? (这绝对不理想)。我现在需要帮助的是弄清楚在 __new__
方法下定义属性的语法,因为我对 def __new__(cls, *args, **kwargs)
方法的 __new__
原型定义以及它如何适应这些定义感到有点困惑;我可以将属性传递给__new__
原型吗?像这样:def __new__(cls, id, created_at, updated_at)
我认为你把这个复杂化了。
Car.__init__
应该执行 any Car
通用的初始化,而不管用于实例化对象的特定子类。
class Car:
def __init__(self):
self.id = uuid.uuid4()
now = datetime.datetime.now()
self.created_at = now
self.modified_at = now
每个子类都将定义一个
__init__
方法,该方法首先调用其继承的__init__
方法,然后进行任何子类特定的初始化。
class Honda:
def __init__(self):
super().__init__()
self.something_else = ...
...
civic = Honda()
civic.id
、civic.created_at
和civic.modified_at
由Car.__init__
定义; civic.something_else
由 Honda.__init__
定义。
在 Python 中,您很少需要触摸
__new__
- 通常只有当您真正知道自己在做什么时才需要。这意味着:如有疑问,请使用__init__
。 :-)
但是说真的,你提到的任务是典型的,并且应该在
__init__
完成。
它有一些语义和历史原因——但实际上,也很少有人知道非常实际的原因:
在 Python 可以做的其他事情中,有开箱即用的支持序列化和反序列化几乎任何由用户定义的类创建的对象 - 开箱即用,类作者从不担心它。
以如此出色的方式工作的原因之一是
__new__
和 __init__
方法中对象构造的分离:__new__
应该将对象构建为“空壳”,并且__init__
“填写对象初始化所需的任何属性”(不是引号,我现在正在措辞这些)。反序列化机制使用它来创建一个新对象,它们只是将原来序列化对象的属性填充到新实例中,而不调用__init__
。在您的示例中,如果 __new__
将创建一个 ID(可能在创建时在某些注册表或数据库中备份,或者是一个不可变的属性),则此机制将不起作用。