Таким образом, методы классов могут использоваться в качестве альтернативного «конструктора» в 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. Я что-то пропустил?
Спасибо, теперь имеет смысл.
Нет, у них не обязательно должно быть одинаковое количество аргументов, вы можете заставить alternative_init() делать то, что говорит его код. Но что должен дать Myclass.alternative_init("alex","james")? Один экземпляр, содержащий список имен? Два экземпляра? (получено из генератора? в виде списка?) или что?






Вы можете делать то, что хотите, вот так:
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
Итак, в основном я могу создать экземпляр внутри метода класса, а затем добавить атрибут к этому экземпляру. Спасибо за объяснение.
Вот и все, вы можете. Но для этого конкретного случая было бы лучше иметь аргумент surname по умолчанию в __init__, потому что атрибут surname вашего экземпляра останется неопределенным, если вы вызовете __init__
__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
Потому что 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")
Привет! Хотя этот код может решить вопрос, включая объяснение о том, как и почему это решает проблему, действительно поможет улучшить качество вашего сообщения и, вероятно, приведет к большему количеству голосов за. Помните, что вы отвечаете на вопрос для будущих читателей, а не только для человека, который задает его сейчас. Пожалуйста, редактировать свой ответ, чтобы добавить пояснения и указать, какие ограничения и предположения применяются.
cls(name,surname)звонки__init__.