在Python中不能定义多个具有不同签名的构造函数吗?如果不是,一般的解决方法是什么?
例如,假设您想定义一个类City。
我希望能够说someCity = City()或someCity = City(“Berlin”),其中第一个只是给出一个默认名称值,第二个定义它。
在Python中不能定义多个具有不同签名的构造函数吗?如果不是,一般的解决方法是什么?
例如,假设您想定义一个类City。
我希望能够说someCity = City()或someCity = City(“Berlin”),其中第一个只是给出一个默认名称值,第二个定义它。
当前回答
杰克的回答是正确的。这样做:
>>> 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
>>>
其他回答
杰克的回答是正确的。这样做:
>>> 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
>>>
与Java不同,您不能定义多个构造函数。但是,如果没有传递一个默认值,则可以定义一个默认值。
def __init__(self, city="Berlin"):
self.city = city
对于你给出的例子,使用默认值:
class City:
def __init__(self, name="Default City Name"):
...
...
一般来说,你有两个选择:
根据类型执行if-elif块: 定义__init__(self, name): 如果isinstance(name, str): #待办事项 elif isinstance(name, City) #待办事项 #待办事项 使用鸭子类型——也就是说,假设类的用户足够聪明,能够正确地使用它。这通常是首选的选项。
最简单的方法是通过关键字参数:
class City():
def __init__(self, city=None):
pass
someCity = City(city="Berlin")
这是非常基本的东西。也许可以看看Python文档?
如果签名只在参数数量上有所不同,那么使用默认参数是正确的方法。如果您希望能够传入不同类型的参数,我会尽量避免在另一个回答中提到的基于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 is best avoided because Python's duck typing makes it hard to figure out what kind of object was actually passed in. For example: if you want to take either a filename or a file-like object you cannot use isinstance(arg, file), because there are many file-like objects that do not subclass file (like the ones returned from urllib, or StringIO, or...). It's usually a better idea to just have the caller tell you explicitly what kind of object was meant, by using different keyword arguments.