Python __init__ и метод класса, должны ли они иметь одинаковое количество аргументов?

Таким образом, методы классов могут использоваться в качестве альтернативного «конструктора» в Python, они привязаны к классу, а не к экземпляру, что пока довольно ясно. Но у меня вопрос: обязательно ли иметь такое же количество аргументов в возвращаемом экземпляре метода класса, что и в __init__. Точнее:

    class MyClass(object):
      def __init__(self,name):
         self.name=name

      @classmethod
      def alternative_init(cls,name,surname):
          return cls(name,surname)

И если я попытаюсь создать экземпляр, Myclass("alex") будет работать нормально, но если я попытаюсь создать экземпляр Myclass.alternative_init("alex","james"), у меня будет TypeError, потому что я передаю множество аргументов, а init принимает только 2. Я что-то пропустил?

cls(name,surname)звонки__init__.
internet_user 19.03.2018 20:24

Спасибо, теперь имеет смысл.

dejdej 19.03.2018 20:26

Нет, у них не обязательно должно быть одинаковое количество аргументов, вы можете заставить alternative_init() делать то, что говорит его код. Но что должен дать Myclass.alternative_init("alex","james")? Один экземпляр, содержащий список имен? Два экземпляра? (получено из генератора? в виде списка?) или что?

smci 01.01.2019 07:43
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
10
3
12 941
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вы можете делать то, что хотите, вот так:

class MyClass(object):
    def __init__(self,name):
        self.name=name

    @classmethod
    def alternative_init(cls,name,surname):
        new_instance = cls(name)
        new_instance.surname = surname
        return new_instance

a = MyClass.alternative_init('Bob', 'Spongy')
print(a.name, a.surname)
# Bob Spongy

Итак, в основном я могу создать экземпляр внутри метода класса, а затем добавить атрибут к этому экземпляру. Спасибо за объяснение.

dejdej 19.03.2018 20:30

Вот и все, вы можете. Но для этого конкретного случая было бы лучше иметь аргумент surname по умолчанию в __init__, потому что атрибут surname вашего экземпляра останется неопределенным, если вы вызовете __init__

Thierry Lathuille 20.03.2018 07:46
Ответ принят как подходящий

__init__ принимает только один параметр, имя. Таким образом, вы можете передать name или surname в cls, но не оба сразу. Однако вы можете создать экземпляр класса в classmethod и добавить дополнительный параметр:

class MyClass(object):
  def __init__(self,name):
    self.name=name
  def __setattr__(self, name, val):
     self.__dict__[name] = val
  @classmethod
  def alternative_init(cls,name,surname):
    v = cls(name)
    v.surname = surname
    return v

Насколько я понимаю, поскольку вы возвращаете v, ваш метод alternative_init больше похож на alternative_new

Camion 29.03.2019 03:10

Потому что Myclass.alternative_init("alex","james") вызывает cls (имя, фамилия), который такой же, как MyClass(name,surname), который также такой же, как __init__(self,name,surname), но ваша функция __init__ не имеет параметра surname. Вы можете сделать surname необязательным с помощью __init__(self,name,surname=None)

class MyClass(object):
  def __init__(self,name,surname=None):
     self.name=name
     self.surname=surname

  @classmethod
  def alternative_init(cls,name,surname):
      return cls(name,surname)

В Python первым аргументом, передаваемым методу, всегда является сам объект. Если вы сейчас вызовете свой метод с именем, вы получите self в качестве первого параметра, а имя - в качестве второго.

Когда вы вызываете сейчас метод в этом изнутри вашего метода класса, python не знает, что ему делать с фамилией.

class MyClass(object):
    def __init__(self,name):
        self.name=name

    @classmethod
    def alternative_init(cls,name,surname):
        return cls(name)


a = MyClass("alex")
MyClass.alternative_init("alex","james")

Привет! Хотя этот код может решить вопрос, включая объяснение о том, как и почему это решает проблему, действительно поможет улучшить качество вашего сообщения и, вероятно, приведет к большему количеству голосов за. Помните, что вы отвечаете на вопрос для будущих читателей, а не только для человека, который задает его сейчас. Пожалуйста, редактировать свой ответ, чтобы добавить пояснения и указать, какие ограничения и предположения применяются.

Brian 23.04.2020 21:16

Другие вопросы по теме