0
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

bob = Person1('bob', 25)

__init__ does not return anything so how are the values of properties name and age passed from __init__ function to the variable bob after assigning the properties name and age to the empty object self?

thebjorn
  • 26,297
  • 11
  • 96
  • 138
star
  • 244
  • 1
  • 2
  • 10
  • Does this answer your question? [How to return a value from \_\_init\_\_ in Python?](https://stackoverflow.com/questions/2491819/how-to-return-a-value-from-init-in-python) – doggie_breath Feb 03 '20 at 19:42
  • `__init__` dosen't return anything, but in this case set to your instance the atributtes `name` and `age`, so you can use it – Andrex Feb 03 '20 at 19:46
  • That is why `self` is passed in addition to the arguments. By the time `__init__` is called, the new object is already created and `__init__` just assigns its attributes to it – Tomerikoo Feb 03 '20 at 19:48

1 Answers1

4

bob = Person1('bob', 25) is really equivalent to something like

rv = Person1.__new__(Person1, 'bob', 25)
if isinstance(rv, Person1):
    rv.__init__('bob', 25)
bob = rv

Calling a class doesn't immediately call the __init__ method. The class's __new__ method is called first to actually create the new instance, and if __new__ returns an instance of the class passed as the first argument, then __init__ is called before returning the value.


Going a step further, this is all encapsulated in type.__call__, so really the call to Person1('bob', 25) is something like

bob = type.__call__(Person1, 'bob', 25)  # Person1 is an instance of type

where type.__call__ is what calls Person1.__new__ and, if appropriate, Person.__init__, and returns the resulting object for it to be assigned to bob.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • In other words, an empty Person1 is being returned by __new__, at which point the class variables are set during the __init__ – Greg Feb 03 '20 at 19:48
  • 1
    Not necessary empty; `__new__` itself can be overriden to do a lot of the same things `__init__` does. `__init__` exists because usually you don't have to be bothered to call a parent class's `__new__` method yourself first. – chepner Feb 03 '20 at 19:49