0

The purpose of constructors is to initialize the state of the object. init in python much behaves like a constructor in python as it initialize the state of the objects. But I read that classmethods are also used as alternative constructors. How? I am not getting this point. How classmethods acts as constructors? See the code below:

class ABC:
   def __init___(self,name)
       self.name=name
   @classmethod
   def from_string(cls,name):
       return cls(name)     # Here classmethod "from_string"  just returns me an object.So 
                            # How can we say that this class method act as constructor? as it
                            # just gives me an object. And the purpose of constructor is not
                            # create an object but to initialize the state of object. Please
                            # clarify this confusion. Thanks
                              
  • 1
    Constructor both creates and initialises the object. Calling the `ABC()` is not just calling the `__init__` method. – matszwecja Sep 01 '22 at 12:47
  • @matszwecja read this stackoverflow answer, constructor doesn't create an object. https://stackoverflow.com/questions/14453270/does-invoking-a-constructor-mean-creating-object#:~:text=Simply%20speaking%2C%20a%20constructor%20does,operator%20which%20creates%20the%20object. – user19626400 Sep 01 '22 at 12:50
  • 1
    It's an answer for Java... – matszwecja Sep 01 '22 at 12:50
  • __init__ doesn't create an object,, it's __new__ that create an object... – user19626400 Sep 01 '22 at 12:51
  • @matszwecja same applies to C++ and python. new creates an object in python not init method itself. – user19626400 Sep 01 '22 at 12:52
  • 2
    Technically, `__init__` is not a constructor. `cls()` is, which combines both `__new__` + `__init__` – matszwecja Sep 01 '22 at 12:52
  • @matszwecja Techinally, __init__ is not a constructor. cls() is. Please expalin it a bit. I am not getting you. – user19626400 Sep 01 '22 at 12:55
  • 1
    The class itself, as a callable, is more like a factory function that wraps both the constructor and the initializer (when appropriate). The class uses `__new__` to create an object, and if `__new__` returns an instance of the class, also uses `__init__` to initialize it. – chepner Sep 01 '22 at 12:55
  • @chepner please explain what is the difference between constructor and initializer? – user19626400 Sep 01 '22 at 12:59
  • 1
    calling `__init__` on it's own does not create a new object, so it is not a constructor. It just initialises state of the object. `__new__` is a constructor, because it creates a new instance of the object. `cls()` is also a constructor, because it calls `__new__` along the way. And if you have a class method using `cls()` that would also be a constructor (alternate), because you create a new instance. – matszwecja Sep 01 '22 at 12:59
  • 2
    Really, there is only *one* constructor in Python: `object.__new__`. All other `__new__` methods either cause `object.__new__` to be called indirectly, or return pre-existing objects; they do not *construct* new objects themselves. – chepner Sep 01 '22 at 13:08
  • 2
    But the term "constructor" is used to distinguish methods that *produce* instances of a class from "initializers", which *receive* instances of a class in order to modify them in some way before they are returned to the user. – chepner Sep 01 '22 at 13:10

2 Answers2

1

What is meant by "alternative constructor" is best illustrated:

>>> from datetime import datetime
>>> datetime(2020, 1, 1)
datetime.datetime(2020, 1, 1, 0, 0)
>>> datetime.now()
datetime.datetime(2022, 9, 1, 14, 50, 43, 536862)

You can either instantiate the class with datetime(...) and pass it the required arguments, or you use datetime.now() which also simply gives you an instance of the datetime class, but fills in the values with the current time. It's an alternative way to construct/instantiate the class with different functionality than the main constructor has.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • ""deceze"" can you please explain what is the purpose of constructors in python. Is __init__ method a constructor ? – user19626400 Sep 01 '22 at 12:56
  • 2
    You're reading too much into this. Internally `__new__` is actually creating the instance and `__init__` initialises it. This is fairly irrelevant most of the time though. You call a class object, you get an instance of it; that's all that matters to you most of the time. Thus the class object as such is "the constructor", it's the thing that gives you an instance of the class when you call it. Thus a classmethod is an *alternative* you can call instead which will also "constructs" an instance for you. – deceze Sep 01 '22 at 13:01
1

Not all languages make a distinction between construction and initialization. Python does. __new__ creates an object (usually, by delegating to an inherited __new__; object.__new__ is the only way to really create a new object) or returns an existing object. __init__ receives that object as an argument to further initialize it. (Whether __init__ gets called depends on whether cls.__new__ returns an instance of cls; it isn't required to, but usually does.)

A class method is used to implement an alternate constructor because it can behave much like __new__. It receives the class and some other arguments, and in this scenario returns an object, usually by calling the __new__ method (indirectly, by calling the class) with arguments derived from its own.

Here's a simple example:

class A:
    # trivial constructor: it just defers to super().__new__
    # You could leave this undefined.
    def __new__(cls, a):
        return super().__new__(cls)

    def __init__(self, a):
        self.a = a

    @classmethod
    def from_pair(cls, x, y):
        return cls(x + y)

a1 = A(6)
a2 = A.from_pair(2, 4)

Both a1 and a2 produce instances of A whose a attribute is 6. The from_pair class method acts as an alternate constructor in that it creates an instance of A, but hides the details of how the two arguments are used to do so.

chepner
  • 497,756
  • 71
  • 530
  • 681