在Python中不能定义多个构造函数吗?
在Python中,是否不能定义多个构造函数,且它们的参数不同?如果不能,那一般有什么方法来解决这个问题呢?
举个例子,假设你想定义一个类叫做City
。
我希望能够这样使用:someCity = City()
,或者someCity = City("Berlin")
,前者是给一个默认的名字,后者则是指定一个名字。
5 个回答
15
对于你给出的例子,可以使用默认值:
class City:
def __init__(self, name="Default City Name"):
...
...
一般来说,你有两个选择:
根据类型做
if
-elif
判断:def __init__(self, name): if isinstance(name, str): # todo elif isinstance(name, City): # todo # todo
使用鸭子类型——也就是说,假设使用你这个类的人足够聪明,能够正确使用它。这通常是更受欢迎的选择。
319
如果你的函数参数只是在数量上有所不同,使用默认参数是个不错的选择。如果你想传入不同类型的参数,我建议避免使用其他答案中提到的基于isinstance
的方法,而是使用关键字参数。
如果只用关键字参数变得很麻烦,你可以把它和类方法结合起来(bzrlib的代码就喜欢这种方式)。下面是一个简单的例子,希望能让你明白这个想法:
class C(object):
def __init__(self, fd):
# Assume fd is a file-like object.
self.fd = fd
@classmethod
def from_filename(cls, name):
return cls(open(name, 'rb'))
# Now you can do:
c = C(fd)
# or:
c = C.from_filename('a filename')
注意所有这些类方法仍然通过同一个__init__
,但使用类方法比记住哪些关键字参数组合适用于__init__
要方便得多。
最好避免使用isinstance
,因为Python的鸭子类型让你很难判断实际传入的是哪种对象。例如:如果你想接受一个文件名或一个类似文件的对象,你不能用isinstance(arg, file)
,因为有很多类似文件的对象并不继承自file
(比如从urllib返回的对象,或者StringIO等等)。通常来说,让调用者明确告诉你想要的对象类型,使用不同的关键字参数会是个更好的主意。
385
跟Java不一样,你不能定义多个构造函数。不过,如果没有传入参数,你可以设置一个默认值。
def __init__(self, city="Berlin"):
self.city = city