How do I explain to the user of my class the expected type of one of its attributes?
我在Python中开发了一个类,其中一个属性应该表示一个神经网络。我希望这个属性实际上是另一个类的实例,我们称它为NN,有几种方法(如train()用于培训,predict()用于预测等)。此外,我认为初始化这个属性的一个合理方法是使用我的类的构造函数,这将期望一个NN类的实例作为它的参数之一。
关于如何解决这个问题,我的第一个想法是实现一个接口,然后输入check,检查用户提供给我的类构造函数的内容,以确保它来自预期的NN类。然而,似乎在Python中,接口(1)和类型检查(2、3、4、5)都不是好的实践。
相反,我们应该使用duck类型,并尝试使用objects方法,直到不能(即将类型检查延迟到运行时)。但是,在我的例子中,NN类可能非常复杂,有几个方法和属性。如果我真的放弃了接口的想法,仅仅期望我的类的用户为一个对象提供所有必要的方法和属性,他/她怎么知道这个对象的期望值呢?我应该在类docstring、构造函数docstring或其他地方编写所有这些信息吗?还是有更好的方法来解决这种情况?
- 我会说,鸭子打字是一种方法。这样,您就不必编写任何代码来处理传递给类的实例没有预期方法的情况。因此,有必要记录您的期望,并使这些期望简单化:让您的类只对传入的实例调用方法。
- 我的实践,不是使用duck类型,而是使用一个基类,它具有训练和预测方法,并且不会引发implementederror
- @我相信我们在这一点上是一致的。然而,主要的问题是:如何记录这一点?尤其是当期望的类非常复杂时。
- @克米郭:有趣。所以你在这里逆水行舟?或者你是不是有一些Python的动机?
- @Jlagana:也许需要一个单独的文档来描述关于您的类期望调用的所有方法的所有期望。
我想说,__init__docstring是您想要放入它的地方,因为它是提供nn对象的地方。
类似:
1 2 3 4 5
| """
(...)
:param NN: an object supporting run(), train() and validate() methods
(...)
""" |
这里的优点是你可以提供任何东西作为参数-见鬼,你可以写一个甚至不是类的nn参数,而是一个函数,或者一个内置的修改实例,或者其他类似的疯狂的东西-只要用户提供了一些正确运行的东西,它就会像你的神经网络一样工作。
- 谢谢你的时间!不过,这似乎不太具有可扩展性。如果nn类有几个方法呢?我可以把每个人应该在那里做什么的描述包括进去吗?连同这些函数的预期参数,加上这个类应该具有的所有属性?如果nn类本身有一个接受另一个复杂类的对象的方法呢?
- 然后我会在我的类中有一个嵌套的docstring吗(即,在nn类的文档中,在我的基类的构造函数的文档中,为nn子类提供文档)?我希望有更好的方法…
- 明确地说,你只是在记录你关心的方法需要有什么。如果nn有500个方法,但run()和validate()是您要调用的唯一两个方法,那么您只需指定对象必须支持这两个方法。它本质上是一个接口的"软"版本——因为python是动态类型的,所以您只需调用所需的方法,如果没有,您要么抛出一个错误,让用户知道您需要定义这个名称,要么自己处理它,例如提供一个默认值。
从Python3.5开始,您可以使用类型提示。这将向用户记录预期的类型,并启用可选的脱机类型检查。
- 谢谢你的时间!您能提供一个如何使用类型提示来实现这一点的最小示例吗?更具体地说,我如何使用类型提示来指定一个完整的类,这个类应该是我的类的构造函数的参数之一的类型?