为什么类主要通过函数实例化?

Vin*_*ent 5 python oop instance

多年来,我一直将 python 用于科学目的。我最近对类编写更加熟悉,但我觉得我缺少一些关于实例化类的标准方法的东西。

假设我定义了一个类MyClass

class MyClass:
    def __init__(self):
        pass
Run Code Online (Sandbox Code Playgroud)

然后我知道我可以简单地映射x到一个实例MyClass

x = MyClass()
Run Code Online (Sandbox Code Playgroud)

这工作得很好,完全符合我的预期。

然而,在我看来,当我使用代码从标准库或numpy或者scipy,我不创建以同样的方式对象:据我所知,我一般不使用类的名称来实例化。根据我的理解,我会说这意味着我既不使用类方法也不使用类的默认构造函数,而是使用在类之外定义的其他函数。

例如,numpyrandom模块使用一个类Generator来生成随机数。但是,numpy明确建议不要使用类构造函数来获取Generator实例,而是使用模块中的default_rng函数random。所以如果我想生成随机数,我使用

rng = numpy.random.default_rng()
Run Code Online (Sandbox Code Playgroud)

创建一个Generator实例。这是在不明确使用类名的情况下完成的。

在我看来,我使用的大部分代码都是用后一种方式编写的。为什么呢?直接调用默认类构造函数在某种程度上被认为是不好的做法吗?在模块中使用单独的函数来创建类实例是否被认为是更好的做法?仅仅是因为在创建类的实例之前通常必须进行一些预处理吗?(我想不是,因为那样的话,为什么不在类的初始化中这样做呢?)

Wup*_*ups 2

不,使用普通构造函数并不是坏习惯,但有时使用替代构造函数可能会很有用。

使用函数作为替代构造函数来创建对象的原因:

(不是完整列表,也没有任何顺序)

  • 将对象的创建与其实现分离。
    解耦通常是 OOP 的目标。
  • 隐藏复杂性
    构造函数可以有许多参数,但通常需要一个默认对象。

  • numpy.random.default_rng()与 更容易读/写和理解numpy.random.Generator(numpy.random.PCG64())
  • 一个工厂,根据有时复杂的条件创建并返回(不同的)对象。
    例如,pythonopen()对于文本文件和二进制文件返回不同的对象。

这些要在哪里实施呢?

在其他一些语言中,这些将被实现为它们实例化的类的类方法,甚至是新类的类方法。
这也可以在 python 中完成,但如果它们作为模块级别的函数实现,它通常会更短且更方便使用。