我可以__60632_在Python类中有多个 __init__
函数 . 那么我该如何解决这个问题呢?
假设我有一个名为 Cheese
的类,其中包含 number_of_holes
属性 . 我怎样才能有两种创建奶酪对象的方法......
-
需要像这样的一些洞:
parmesan = Cheese(num_holes = 15)
-
和一个不带参数,只是随机化
number_of_holes
属性:gouda = Cheese()
我只想到一种方法,但这似乎有点笨重:
class Cheese():
def __init__(self, num_holes = 0):
if (num_holes == 0):
# randomize number_of_holes
else:
number_of_holes = num_holes
你说什么?还有另一种方式吗?
11 回答
为什么你认为你的解决方案“笨重”?就个人情况而言,我个人更喜欢一个默认值超过多个重载构造函数的构造函数(Python不支持方法重载):
对于具有许多不同构造函数的非常复杂的情况,使用不同的工厂函数可能更简洁:
在您的奶酪示例中,您可能想要使用奶酪的Gouda子类...
这些是您实施的好主意,但如果您要向用户展示奶酪制作界面 . 他们并不关心奶酪有多少孔或者是什么内部制作奶酪 . 您的代码的用户只想要“gouda”或“parmesean”吗?
那么为什么不这样做:
然后你可以使用上面的任何方法来实际实现这些功能:
这是一种很好的封装技术,我认为它更像是Pythonic . 对我来说,这种做事方式更适合鸭子打字 . 你只是要求一个gouda对象而你并不关心它是什么类 .
如果您将只使用
__init__
,则使用num_holes=None
作为默认值是正常的 .如果你想要多个独立的"constructors",你可以将它们作为类方法提供 . 这些通常称为工厂方法 . 在这种情况下,您可以将
num_holes
的默认值设为0
.现在创建这样的对象:
如果你想使用可选参数,所有这些答案都非常好,但另一种Pythonic可能是使用classmethod来生成工厂式伪构造函数:
而是使用
num_holes=None
作为默认值 . 然后检查是否num_holes is None
,如果是,则随机化 . 无论如何,这就是我通常看到的 .更完全不同的构造方法可能需要一个返回
cls
实例的类方法 .实际上
None
对"magic"值更好:现在,如果您想完全自由地添加更多参数:
为了更好地解释
*args
和**kwargs
的概念(您实际上可以更改这些名称):http://docs.python.org/reference/expressions.html#calls
最好的答案是关于默认参数的上面的答案,但我很乐意写这个,它确实符合“多个构造函数”的账单 . 使用风险由您自己承担 .
怎么样new方法 .
“典型实现通过使用super(currentclass,cls). new (cls [,...])调用超类的 new ()方法并使用适当的参数创建类的新实例,然后根据需要修改新创建的实例 . 归还它 . “
因此,您可以通过附加适当的构造函数方法让 new 方法修改类定义 .
这就是我为必须创建的
YearQuarter
类解决它的方法 . 我用一个名为value
的参数创建了__init__
.__init__
的代码只决定value
参数的类型并相应地处理数据 . 如果你想要多个输入参数,你只需将它们打包成一个元组并测试value
是一个元组 .你这样使用它:
这就是
__init__
和班上其他人的样子:当然,您可以使用多个错误消息展开
__init__
. 我在这个例子中省略了它们 .人们肯定更喜欢已发布的解决方案,但由于还没有人提到这个解决方案,我认为值得一提的是完整性 .
可以修改
@classmethod
方法以提供不调用默认构造函数(__init__
)的替代构造函数 . 而是使用__new__
创建实例 .如果无法根据构造函数参数的类型选择初始化类型,并且构造函数不共享代码,则可以使用此方法 .
例:
我会使用继承 . 特别是如果存在比孔数更多的差异 . 特别是如果Gouda需要有不同的成员,那么Parmesan .