Несколько конструкторов в python?

Возможный дубликат:
Что такое чистый, pythonic способ иметь несколько конструкторов в Python?

Невозможно ли определить несколько конструкторов в Python с разными сигнатурами? Если нет, то какой общий способ обойти это?

Например, скажем, вы хотели бы определить класс City

Я хотел бы сказать someCity = City() или someCity = City("Berlin"), где первый просто дает значение имени по умолчанию, а второе определяет его.

Ответ 1

В отличие от Java, вы не можете определить несколько конструкторов. Однако вы можете определить значение по умолчанию, если оно не передано.

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

Ответ 2

Если ваши подписи отличаются только количеством аргументов с использованием аргументов по умолчанию, это правильный способ сделать это. Если вы хотите иметь возможность передавать различные аргументы, я бы попытался избежать подхода, основанного на isinstance, упомянутого в другом ответе, вместо этого используя аргументы ключевого слова. Если использование только аргументов ключевого слова становится громоздким, вы можете комбинировать его с classmethods (код bzrlib любит этот подход). Это просто глупый пример, но я надеюсь, что вы поняли:

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 лучше избегать, потому что утиная утиная питона затрудняет определение того, какой объект был фактически передан. Например: если вы хотите взять либо имя файла, либо файл-подобный объект, вы не можете использовать isinstance(arg, file) потому что существует много файловых объектов, которые не подклассы file (например, те, которые возвращаются из urllib или StringIO, или...). Как правило, лучше всего просто указать, что вызывающий абонент явно указал вам, какой именно объект имел в виду, используя разные аргументы ключевых слов.

Ответ 3

Самый простой способ - использовать аргументы ключевого слова:

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

someCity = City(city="Berlin")

Это довольно простой материал, возможно, посмотрите документы python?

Ответ 4

В приведенном примере используйте значения по умолчанию:

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

В общем, у вас есть два варианта:

1) Сделайте if - elif блоки на основе типа:

def __init__(self, name):
    if isinstance(name, str):
        ...
    elif isinstance(name, City):
        ...
    ...

2) Используйте duck typing --- то есть предположим, что пользователь вашего класса достаточно интеллектуальный, чтобы правильно его использовать. Обычно это предпочтительный вариант.

Ответ 5

Джек М. прав, делайте это так:

>>> 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

>>>