在python中有多个构造函数?

Multiple constructors in python?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
What is a clean, pythonic way to have multiple constructors in Python?

是否不可能用不同的签名在python中定义多个构造函数?如果没有,一般的解决方法是什么?

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

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


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

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


如果您的签名只在参数数量上有所不同,那么使用默认参数是正确的方法。如果您希望能够传递不同类型的参数,我将尽量避免使用其他答案中提到的基于isinstance的方法,而不是使用关键字参数。如果只使用关键字参数变得不方便,可以将其与类方法结合起来(BZrlib代码喜欢这种方法)。这只是一个愚蠢的例子,但我希望你能理解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class C(object):

    def __init__(self, fd):
        # Assume fd is a file-like object.
        self.fd = fd

    @classmethod
    def fromfilename(cls, name):
        return cls(open(name, 'rb'))

# Now you can do:
c = C(fd)
# or:
c = C.fromfilename('a filename')

注意,所有这些类方法仍然使用相同的__init__,但是使用类方法比记住__init__的关键字参数组合要方便得多。

最好避免使用isinstance,因为python的duck类型使得很难确定实际上传入了什么类型的对象。例如:如果您要使用文件名或类似文件的对象,则不能使用isinstance(arg, file),因为有许多类似文件的对象不属于file的子类(如从urlib、stringio或…)中返回的对象)。通过使用不同的关键字参数,让调用者明确地告诉您对象的含义通常是一个更好的主意。


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

1
2
3
4
class City:
    def __init__(self, name="Default City Name"):
        ...
    ...

一般来说,您有两种选择:

1)根据类型执行ifelif块:

1
2
3
4
5
6
def __init__(self, name):
    if isinstance(name, str):
        ...
    elif isinstance(name, City):
        ...
    ...

2)使用duck类型——也就是说,假设你的类的用户足够聪明,能够正确地使用它。这通常是首选选项。


杰克M.是对的,这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> 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

>>>

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

1
2
3
4
5
class City():
  def __init__(self, city=None):
    pass

someCity = City(city="Berlin")

这是非常基本的东西,也许看看python文档?