1

I have worked with Python for about 4 years and have recently started learning C++. In C++ you create a constructor method for each class I I was wondering if it is correct to think that this is equivalent to the __init__(self) function in Python? Are there any notable differences? Same question for a C++ destructor method vs. Python _exit__(self)

melpomene
  • 84,125
  • 8
  • 85
  • 148
LonaiGuy
  • 63
  • 9
  • 1
    Did you made any research? – Yaroslav Surzhikov Oct 21 '17 at 14:37
  • the init function is what is executed first when you call the class. the constructors in C++ however can be called separately. there's barely any similarity between constructors and the __init__ function in python except for belonging to a class. –  Oct 21 '17 at 14:38
  • 1
    I recommend you get [a good beginners book or two](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) to read. It should give you all information you need about constructors and destructors. – Some programmer dude Oct 21 '17 at 14:38
  • @j_h_o_m_o but `__new__` is called first, dont it? – Yaroslav Surzhikov Oct 21 '17 at 14:38
  • Vaguely similar, but fundamentally different. Python has no analogue for multiple constructors, delegating constructors, copy/move constructors, etc... – Sam Varshavchik Oct 21 '17 at 14:40
  • 4
    In Python, the object constructor is `__new__`, but you don't often see it since it's rarely necessary to override the `__new__` inherited from `object`. Strictly speaking, `__init__` initializes the new instance created by `__new__`, but it's fairly common in casual discussions to call `__init__` the constructor. – PM 2Ring Oct 21 '17 at 14:41
  • @j_h_o_m_o Not quote; `__new__` is called first; `__init__` is only called on the eventual return value of `__new__` (assuming `__new__` returns an instance of the class being instantiated). – chepner Oct 21 '17 at 14:41
  • he's not asking about that though. and of course if you create a __new__ method than __init__ will be initialized later –  Oct 21 '17 at 14:41
  • @j_h_o_m_o how about that: `class A: pass; print(dir(A))` - shows that A has `__new__` method – Yaroslav Surzhikov Oct 21 '17 at 14:43
  • 3
    He's asking if `__init__` and a constructor are the same; they are not. – chepner Oct 21 '17 at 14:44
  • @YaroslavSurzhikov Technically, `A` does not have a `__new__` method; in its absence, `A.__new__` *resolves* to the same object as `object.__new__`. – chepner Oct 21 '17 at 14:45
  • @chepner yup, but `__new__` is *always* called *before* `__init__` even if `__new__` is inherited – Yaroslav Surzhikov Oct 21 '17 at 14:46

3 Answers3

1

Yes, Python's __init__ is analogous to C++'s constructor. Both are typically where non-static data members are initialized. In both languages, these functions take the in-creation object as the first argument, explicit and by convention named self in Python and implicit and by language named this in C++. In both languages, these functions can return nothing. One notable difference between the languages is that in Python base-class __init__ must be called explicitly from an inherited class __init__ and in C++ it is implicit and automatic. C++ also has ways to declare data member initializers outside the body of the constructor, both by member initializer lists and non-static data member initializers. C++ will also generate a default constructor for you in some circumstances.

Python's __new__ is analogous to C++'s class-level operator new. Both are static class functions which must return a value for the creation to proceed. In C++, that something is a pointer to memory and in Python it is an uninitialized value of the class type being created.

Python's __del__ has no direct analogue in C++. It is an object finalizer, which exist also in other garbage collected languages like Java. It is not called at a lexically predetermined time, but the runtime calls it when it is time to deallocate the object.

__exit__ plays a role similar to C++'s destructor, in that it can provide for deterministic cleanup and a lexically predetermined point. In C++, this tends to be done through the C++ destructor of an RAII type. In Python, the same object can have __enter__ and __exit__ called multiple times. In C++, that would be accomplished with the constructor and destructor of a separate RAII resource holding type. For example, in Python given an instance lock of a mutual exclusion lock type, one can say with lock: to introduce a critical section. In C++, we create an instance of a different type taking the lock as a parameter std::lock_guard g{lock} to accomplish the same thing. The Python __enter__ and __exit__ calls map to the constructor and destructor of the C++ RAII type.

Jeff Garrett
  • 5,863
  • 1
  • 13
  • 12
  • Isn't \__del_\_ like delete in c++? – Robert Page May 18 '21 at 16:29
  • Arguably the most important feature of C++ destructors is that they run at a predetermined time, when the scope is exited. The analogue of that behavior is `__exit__`, because `__del__` isn't guaranteed to be called at any particular time. `__del__` is a finalizer, called right before when storage is reclaimed. In C++, destructors are separate from deallocation, although both operations often happen together. In particular, right before deallocation happens, no object will exist anymore, and there is nothing that could be called automatically even if we wanted to. – Jeff Garrett May 18 '21 at 17:23
  • Im not talking about destructors, im saying that after both \__del_\_ and delete the memory is reclaimed, so I think that we can think of \__del_\_ as analogous to delete. – Robert Page May 18 '21 at 17:34
  • OK, that's fair. I could agree with that. One distinction I would make is that most of these things are called typically implicitly by the language (__del__ at end of lifetime, __enter__, __exit__) and delete is explicitly called by the user. – Jeff Garrett May 18 '21 at 17:46
  • I remember this post almost 5 years later. I have come a long ways since the beginning of my programming journey and this was one of my first posts on stack and was definitely discouraged to see the comments such as "do your own research" or "go read a book" and "these are nothing alike!". I always appreciated this response! Thanks @JeffGarrett for your answer - it prompted me to keep learning! And while I understand that these things are not identical, it's funny to see that today when you google "python class constructor" you are directed to __init__ (pythonbasics.org and geeksforgeeks.org) – LonaiGuy Jun 09 '22 at 21:53
1

The best you can say is that __init__ and a C++ constructor are called at roughly the same point in the lifetime of a new object, and that __del__ and a C++ destructor are also called near the end of the lifetime of an object. The semantics, however, are markedly different, and the execution model of each language makes further comparison more difficult.

Suffice it to say that __init__ is used to initialize an object after it has been created. __del__ is like a destructor that may be called at some unspecified point in time after the last reference to an object goes away, and __exit__ is more like a callback invoked at the end of a with statement, whether or not the object's reference count reaches zero.

chepner
  • 497,756
  • 71
  • 530
  • 681
0

I was wondering if it is correct to think that this is equivalent to the init(self) function in Python?

No. Just by looking at the structure of the statement you can understand. Indeed, self is a reference to the instance. Therefore, the instance must be constructed before __init__ is called.

See this for more information (__new__ is actually what you're looking for)

Same question for a C++ destructor method vs. Python _exit__(self)

No. __exit__ only exit the Runtime context related to the object. In this case, what you are really looking for is __del__.

See this, which clearly state:

Called when the instance is about to be destroyed. This is also called a destructor.

scharette
  • 9,437
  • 8
  • 33
  • 67
  • `__del__` is also not *guaranteed* to be called; it is only called if the running interpreter needs to garbage-collect the instance. If the reference count goes to zero as a result of the interpreter exiting, it will not bother calling `__del__`. – chepner Oct 21 '17 at 14:53
  • Yes you are totally right, but this is still the equivalent in Python. Am I wrong ? – scharette Oct 21 '17 at 14:54
  • It's the closest thing Python provides, but it is not equivalent. Code that would often be put in a constructor is instead put in the `__exit__` method of a context manager. The fact that `__exit__` is called, though, does not imply the object is going away. You could easily define an object that can be used with multiple sequential `with` statements, its `__enter__` and `__exit__` methods being called when appropriate. – chepner Oct 21 '17 at 15:10
  • As I said in my answer `__exit__` is not a deconstructor. But, `__del__` on the other hand, can be called one. Anyway, follow my link the doc says it. – scharette Oct 21 '17 at 15:16
  • `__init__` is more like the constructor in C++. And like self, the constructor in c++ also implicitly passed with "this" pointer as the first parameter. Some basic initialization may happen in the passed memory pointed to by "this" also. – Nipun Talukdar Oct 21 '17 at 15:32
  • I really don't agree. this is from the documentation : Use __new__ when you need to control the creation of a new instance. Use __init__ when you need to control initialization of a new instance. – scharette Oct 21 '17 at 15:39