There are at least two not obvious class initialization mechanisms in Python, especially if your background is in different programming languages 😉
Class field initialization
If you assign a class value outside __init__ method like here (see class_field):
import random, string
class ClassToBeUsed:
def __init__(self):
self.field = ''.join(random.choices(string.ascii_letters + string.digits, k=10))
class ClassInitialization:
class_field = ClassToBeUsed()
def __init__(self, field: str):
self.field = field
if __name__ == '__main__':
instance1 = ClassInitialization('Instance1')
instance2 = ClassInitialization('Instance2')
print("Are both class_field objects the same?",
instance1.class_field is instance2.class_field)
You should get:
Are both class_field objects the same? True
So be careful – class fields initialized outside __init__ are initialized only once (when the file is imported).
Class __init__ default arguments initialization
If you define a default vaule for arguments in the __init__ method like here:
import random, string
class ClassToBeUsed:
def __init__(self):
self.field = ''.join(random.choices(string.ascii_letters + string.digits, k=10))
class DefaultArgumentsInitialization:
def __init__(self, field: str, class_to_be_used: ClassToBeUsed = ClassToBeUsed()):
self.field = field
self.class_to_be_used = class_to_be_used
if __name__ == '__main__':
instance1 = DefaultArgumentsInitialization('Instance1')
instance2 = DefaultArgumentsInitialization('Instance2')
print("Are both class_to_be_used objects the same?",
instance1.class_to_be_used is instance2.class_to_be_used)
You should get:
Are both class_to_be_used objects the same? True
So be careful – the default arguments of __init__ methods are initialized only once (when the file is imported).
So how do I support default arguments then?
You need to assign None to the argument by default and then reassign it inside __init__ if it has not been changed, see:
import random, string
class ClassToBeUsed:
def __init__(self):
self.field = ''.join(random.choices(string.ascii_letters + string.digits, k=10))
class DefaultArgumentsInitialization:
def __init__(self, field: str, class_to_be_used: ClassToBeUsed = None):
if class_to_be_used is None:
class_to_be_used = ClassToBeUsed()
self.field = field
self.class_to_be_used = class_to_be_used
if __name__ == '__main__':
instance1 = DefaultArgumentsInitialization('Instance1')
instance2 = DefaultArgumentsInitialization('Instance2')
print("Are both class_to_be_used objects the same?",
instance1.class_to_be_used is instance2.class_to_be_used)
You should get:
Are both class_to_be_used objects the same? False