Python: гибкий способ объявления конструкторов - PullRequest
2 голосов
/ 15 ноября 2011

Что такое чистый способ объявления нескольких конструкторов для одного класса?

Например, допустим, у меня есть класс Item.Один из способов создания предмета (например, это)

item = Item(product_id, name, description,price)

, другой способ сделать то же самое может

item = Item(otherItem)

А потом еще один способ сделать это .. может быть, в некоторых случаяхУ меня нет цены, поэтому я хочу передать только

item = Item(product_id, name,description)

, и еще один случай может быть

item = Item(product_id,price)

Другой вопрос, который у меня есть: есть некоторыечастные переменные, которые могут быть инициализированы во время выполнения.Допустим, у меня есть какая-то случайная переменная itemCount, и я хочу отслеживать ее внутренне.

Как мне объявить, что мне не нужно переводить ее в режим инициализации, а скорее где-то в бегевремя .. Я могу сделать что-то вроде

self._count +=1

Спасибо

Ответы [ 3 ]

4 голосов
/ 15 ноября 2011

Два наиболее распространенных подхода для предоставления нескольких конструкторов:

  1. методы класса и
  2. заводские функции

Вот пример , взятый из стандартной библиотеки , показывающий, как collection.OrderedDict использует метод класса для реализации fromkeys () в качестве конструктора альтернативного класса:

@classmethod
def fromkeys(cls, iterable, value=None):
    '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
    If not specified, the value defaults to None.

    '''
    self = cls()
    for key in iterable:
        self[key] = value
    return self

В качестве примера другого распространенного подхода приведена фабричная функция , используемая в symtable.py в стандартной библиотеке:

class SymbolTableFactory:
    def __init__(self):
        self.__memo = weakref.WeakValueDictionary()

    def new(self, table, filename):
        if table.type == _symtable.TYPE_FUNCTION:
            return Function(table, filename)
        if table.type == _symtable.TYPE_CLASS:
            return Class(table, filename)
        return SymbolTable(table, filename)
1 голос
/ 15 ноября 2011

Копирование обычно выполняется методом copy() на экземплярах вместо предоставления «конструктора копирования», поэтому

item = other_item.copy()

вместо

item = Item(other_item)

Все остальныеУпомянутые вами подписи конструктора легко обрабатываются аргументами по умолчанию и аргументами ключевых слов:

def __init__(self, product_id, name=None, description=None, price=None):
    ...

Если вам нужен другой конструктор с совершенно другим кодом, тогда classmethod - правильный подход - см. ответ Раймонда Хеттингера.

1 голос
/ 15 ноября 2011

Вы можете использовать аргументы по умолчанию:

class Item(object):

  def __init__(self, product_id = None, name = None, description = None, price = None)
      ... implementation ...

Вы можете заменить любое значение на None, если значение по умолчанию должно быть другим.

Пример использования:

item1 = Item(product_id = 4, price = 13) # use the field name!
item2 = Item(name = "hammer", description = "used to belong to Thor")

Для конструктора копирования item = Item(otherItem) предложения Рэймонда о методах класса и фабричных функциях могут быть наиболее подходящим для Pythonic способом.


Обновление: вот вопрос о нескольких конструкторах в Python. Также упоминается использование *args и **kwargs.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...