Question: I have a list defined at the class level in Python and below is my code: class TestStudentReg(unittest.TestCase): student_id_list = []  I'm trying to initialise the list by reading values from a csv file and below is the method that i use within the same class i.e., TestStudentReg @classmethod def initialise_student_id_list(cls): filename = 'input/student_testdata.csv' with open(filename, 'r') as csvfile: datareader = (csv.reader(csvfile, delimiter="|")) next(datareader, None) # skip the headers for col in datareader: cls.student_id_list.append(col[2])  Now that this method is being common across several classes, i'm planning to make it as a reusable function and define it in a separate python file (utilities.py) which will be like this: import csv import logging import time import timeit def get_date(dateformat="%Y-%m-%d", subtract_num_of_days=0): getdate = date.today() - timedelta(subtract_num_of_days) return getdate.strftime(dateformat) def initialise_student_id_list(**kwargs): filename = 'input/student_testdata.csv' with open(filename, 'r') as csvfile: datareader = (csv.reader(csvfile, delimiter="|")) next(datareader, None) # skip the headers for col in datareader: cls.student_id_list.append(col[2])  I would like to understand how to initialise student_id_list from the utilities file. One way i thought to implement this was to have the method return a list and initialise the value by calling this method. def initialise_student_id_list(**kwargs): id_list=[] filename = 'input/student_testdata.csv' with open(filename, 'r') as csvfile: datareader = (csv.reader(csvfile, delimiter="|")) next(datareader, None) # skip the headers for col in datareader: cls.student_id_list.append(col[2]) return id_list  Not sure if this is a correct approach. Great if someone could help me on this please.

Answer: There are multiple ways to solve your problem. Here I will list three with increasing readability and overall quality: def student_id_list_initialiser(class_obj, **kwargs): cls = class_obj filename = 'input/student_testdata.csv' with open(filename, 'r') as csvfile: datareader = (csv.reader(csvfile, delimiter="|")) next(datareader, None) # skip the headers for col in datareader: cls.student_id_list.append(col[2]) class MyTest(): student_id_list = [] @classmethod def initialise_student_id_list(cls): student_id_list_initialiser(cls)  This approach works fine, but it isn't the best because we have to manually pass-in the class object and the code breaks encapsulation. However, if coupled with a simple and short classmethod that sets the class variable student_id_list, it will be better: def student_id_list_creator(**kwargs): ret_l = [] filename = 'input/student_testdata.csv' with open(filename, 'r') as csvfile: datareader = (csv.reader(csvfile, delimiter="|")) next(datareader, None) # skip the headers for col in datareader: ret_l.append(col[2]) return ret_l class MyTest(): student_id_list = [] @classmethod def initialise_student_id_list(cls): cls.student_id_list = student_id_list_creator()  This is similar to what you said you thought of, and yes, it is indeed a good approach. Finally, inheritance is perhaps the best option here, although not a direct inheritance from the TestStudentReg class. Here's the code: class StudentInfoHelper(): @classmethod def initialise_student_id_list(cls): filename = 'input/student_testdata.csv' with open(filename, 'r') as csvfile: datareader = (csv.reader(csvfile, delimiter="|")) next(datareader, None) # skip the headers for col in datareader: cls.student_id_list.append(col[2]) class TestStudentReg(StudentInfoHelper): student_id_list = [] # outside: TestStudentReg.initialise_student_id_list()  This code is not only more readable but also is much more flexible and can be applied to any class as long as the class inherit from StudentInfoHelper. The only downside to this approach is that  You must name your class variable student_id_list. But since you already decided the variable name, it wouldn't be a problem. It wouldn't work if you define a method named student_id_initialiser. The reason is pretty obvious here: because if you do, then the original method will be "shadowed" by the new one. But sometimes, this is also a good thing if you want to custom the method or if you don't want it.