Что такое чистый, питонский способ иметь несколько конструкторов в Python? - PullRequest
621 голосов
/ 25 марта 2009

Не могу найти однозначного ответа на это. AFAIK, вы не можете иметь несколько __init__ функций в классе Python. Так как мне решить эту проблему?

Предположим, у меня есть класс с именем Cheese со свойством number_of_holes. Как у меня может быть два способа создания сырных объектов ...

  1. тот, который занимает несколько отверстий, как это: parmesan = Cheese(num_holes = 15)
  2. и тот, который не принимает аргументов и просто рандомизирует свойство number_of_holes: gouda = Cheese()

Я могу придумать только один способ сделать это, но это кажется немного неуклюжим:

class Cheese():
    def __init__(self, num_holes = 0):
        if (num_holes == 0):
            # randomize number_of_holes
        else:
            number_of_holes = num_holes

Что вы говорите? Есть ли другой способ?

Ответы [ 13 ]

0 голосов
/ 17 января 2019

Это довольно чистый способ, я думаю и хитрый

class A(object):
    def __init__(self,e,f,g):

        self.__dict__.update({k: v for k,v in locals().items() if k!='self'})
    def bc(self):
        print(self.f)


k=A(e=5,f=6,g=12)
k.bc() # >>>6
0 голосов
/ 26 февраля 2018
class Cheese:
    def __init__(self, *args, **kwargs):
        """A user-friendly initialiser for the general-purpose constructor.
        """
        ...

    def _init_parmesan(self, *args, **kwargs):
        """A special initialiser for Parmesan cheese.
        """
        ...

    def _init_gauda(self, *args, **kwargs):
        """A special initialiser for Gauda cheese.
        """
        ...

    @classmethod
    def make_parmesan(cls, *args, **kwargs):
        new = cls.__new__(cls)
        new._init_parmesan(*args, **kwargs)
        return new

    @classmethod
    def make_gauda(cls, *args, **kwargs):
        new = cls.__new__(cls)
        new._init_gauda(*args, **kwargs)
        return new
0 голосов
/ 18 января 2017

Вот как я решил это для класса YearQuarter, который мне пришлось создать. Я создал __init__ с единственным параметром под названием value. Код для __init__ просто решает, к какому типу относится параметр value, и соответственно обрабатывает данные. Если вам нужны несколько входных параметров, вы просто упаковываете их в один кортеж и проверяете, является ли value кортежем.

Вы используете это так:

>>> temp = YearQuarter(datetime.date(2017, 1, 18))
>>> print temp
2017-Q1
>>> temp = YearQuarter((2017, 1))
>>> print temp
2017-Q1

А вот так __init__ и остальные члены класса выглядят так:

import datetime


class YearQuarter:

    def __init__(self, value):
        if type(value) is datetime.date:
            self._year = value.year
            self._quarter = (value.month + 2) / 3
        elif type(value) is tuple:               
            self._year = int(value[0])
            self._quarter = int(value[1])           

    def __str__(self):
        return '{0}-Q{1}'.format(self._year, self._quarter)

Конечно, вы можете расширить __init__ несколькими сообщениями об ошибках. Я опустил их для этого примера.

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