Python __init__ and classmethod, do they have to have the same number of args?
Asked Answered
S

5

15

So classmethods can be used as an alternative "constructor" in python, they are bound to the class and not to an instance, pretty clear so far. But my question is, if it is mandatory to have the same number of arguments in the returned instance of the class method as in the __init__. More exactly :

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

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

And if I try to create an instance Myclass("alex") works fine, but if I try to create an instance Myclass.alternative_init("alex","james") I have a TypeError , because I pass to many arguments, and init take only 2 . Am I missing something?

Seko answered 19/3, 2018 at 19:19 Comment(3)
cls(name,surname) calls __init__.Tersanctus
Thanks , makes sense now .Seko
No they don't have to have the same number of args, you can make alternative_init() do whatever its code says to do. But what is Myclass.alternative_init("alex","james") supposed to give? One instance containing a list of names? Two instances ? (yield'ed from a generator? as a list?) or what?Alvar
I
13

__init__ only takes one parameter, the name. Thus, you can pass either name or surname to cls, but not both. However, you can create a class instance in classmethod, and add an additional paramter:

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
Idiocrasy answered 19/3, 2018 at 19:28 Comment(1)
As far as I understand, since you returns v, your alternative_init method is more of an alternative_newSixpence
C
2

You could do what you want like this:

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
Counteroffensive answered 19/3, 2018 at 19:27 Comment(2)
Ok, so basically I can create an instance inside the classmethod and then add attribute to that instance. Thanks for the explanation.Seko
That's it, you can. But for this particular case, it would be better to have a default argument surname in __init__, because the surname attribute of your instance would be left undefined if you called __init__Counteroffensive
G
2

Because Myclass.alternative_init("alex","james") calls the cls(name, surname) which same as MyClass(name,surname) which also same as __init__(self,name,surname) but your __init__ function don't have surname parameter. You can make surname optional by __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)
Gonna answered 19/3, 2018 at 19:28 Comment(0)
W
2

In Python, the first argument Passed to a method is always the object itself. If you call now your method with a name, you will get self as first parameter and the name as second.

When you call now the init method from inside of your classmethod, python has no idea what it should do with the surname.

Wellman answered 19/3, 2018 at 19:33 Comment(0)
T
1
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")

Trestle answered 23/4, 2020 at 16:20 Comment(1)
Hello! While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.Precipitancy

© 2022 - 2024 — McMap. All rights reserved.