#!/usr/bin/env python3

# 'self' could be replaced, e.g. by 'this'
class testInit:
 def __init__(self, name, age=None):     # defines 'self'
   self.name = name
   if age==None:
     self.age = 0
   else:
     self.age = age

 def __del__(self):                      # destructor
   print("deleting an instance of ", self.__class__.__name__)

 def hello(self):
   print("Hello for the first time\n")

 def hello(self):                        # overides first definition
   print("Hello for the second time\n")

def nothing():                           # just a function
   print("| entering nothing")          
   cc = testInit("Julia") 
   print("| leaving  nothing")           # destructor called by default

print("*******************************")
print("instance creation in a function")
print("*******************************")
print()
nothing()
print()

print("*************************")
print("basic constructor testing")
print("*************************")
c1 = testInit("Julia")                   # both constructors possible
c2 = testInit("Alice", 10)
c3 = testInit(age=33, name="Kenys")      # calling with keys
c1.hello()                               # which one is called?
print("c1  :  ",c1.name, c1.age)
print("c2  :  ",c2.name, c2.age)
print("c3  :  ",c3.name, c3.age)
del c1, c2, c3                           # deletes them

print()
print("***************")
print("__new__ testing")
print("***************")
c4 = object.__new__(testInit)            # object without attributes created
print(c4.__dict__)                       # dictionary of attributes

c4.__init__('John')                      # create attributes, don't call twice
print(c4.__dict__)

print()
print("c4  :  ",c4.name, c4.age)
# print(dir(c4))                         # for comparison
