在Python中不能定义多个构造函数吗?

< p > 可能的重复: < br / > 在Python中使用多个构造函数的干净的Python方式是什么? < / p >

在Python中不能定义多个具有不同签名的构造函数吗?如果不是,一般的解决方法是什么?

例如,假设你想定义一个类City

我希望能够说someCity = City()someCity = City("Berlin"),其中第一个只是给出一个默认的名称值,而第二个定义它。

321890 次浏览

最简单的方法是通过关键字参数:

class City():
def __init__(self, city=None):
pass


someCity = City(city="Berlin")

这是非常基本的东西。也许可以看看Python文档?

对于你给出的例子,使用默认值:

class City:
def __init__(self, name="Default City Name"):
...
...

一般来说,你有两个选择:

  1. 根据类型执行if-elif块:

    def __init__(self, name):
    if isinstance(name, str):
    # todo
    elif isinstance(name, City):
    # todo
    # todo
    
  2. 使用鸭子类型——也就是说,假设你的类的用户足够聪明,可以正确使用它。这通常是首选的选项。

与Java不同,您不能定义多个构造函数。但是,如果没有传递一个默认值,则可以定义一个默认值。

def __init__(self, city="Berlin"):
self.city = city

如果你的签名只在参数的数量中不同,使用默认参数是正确的方法。如果你希望能够传入不同的类型参数,我会尽量避免在另一个答案中提到的基于__abc0的方法,而是使用关键字参数。

如果只使用关键字参数变得笨拙,您可以将其与类方法结合使用(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的duck类型使得很难弄清楚实际传入的是哪种对象。例如:如果你想获取文件名或类文件对象,你不能使用isinstance(arg, file),因为有许多类文件对象不继承file(比如从urllib或StringIO或…返回的对象)。通过使用不同的关键字参数,让调用者显式地告诉你对象的类型通常是一个更好的主意。

回答:Jack M。是正确的。这样做:

>>> class City:
...     def __init__(self, city=None):
...         self.city = city
...     def __repr__(self):
...         if self.city:  return self.city
...         return ''
...
>>> c = City('Berlin')
>>> print c
Berlin
>>> c = City()
>>> print c


>>>