12.4. Item assignment#

This section covers how to add some advanced functionality to your class.

So far we have learned how to define operators such as +, -, *, /, and == for your class. Now we will learn how to define the assignment operator =.

class MyClass:
    def __init__(self, **kwargs):
        self.data = {}
              
    def __setitem__(self, key, value): # MyCLass[key] = value
        self.data[key] = value
        
    def __getitem__(self, key): # MyClass[key]
        return self.data[key]      

my_class = MyClass()


my_class['Exam1'] = 90
my_class['Exam1']
90

12.4.1. Basic Columnar Functionality#

  • Add functionality to pass in multiple columns of data; with and without header

  • Add functionality to select multiple columns

  • If the data that is passed has header, use header=True; otherwise just assume that the headers will be sequentially numbered.

from collections import defaultdict
class MyClass:
    def __init__(self, **kwargs):
        self.data = defaultdict(list)
        header = kwargs.get('header') 
        lines = kwargs.get('lines')
        if header:
            header = lines.pop(0)
        else:
            header = list(range(len(lines[0])))
        
        # Store the data as a dictionary
        for line in lines:
            row = dict(zip(header, line))
            for key,value in row.items():
                self.data[key].append(value)
              
    def __setitem__(self, key, value): # MyCLass[key] = value
        self.data[key] = value
        
    def __getitem__(self, key): # MyClass[key]
        if type(key) in (str, int):
            return self.data[key]   
        elif isinstance(key, list):
            output = []
            for k in key:
                output.append(self.data[k])
            output = list(zip(*output))              
            return output

filename = 'people.tsv'
people = []
with open(filename) as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        people.append(line.strip().split('\t'))


mc = MyClass(lines=people, header=True)
print(mc[['first_name', 'last_name', 'email']])
print(mc['first_name'])

people = tuple(people)
filename = 'testdata.txt'
grades = []
with open(filename) as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        grades.append(line.strip().split(','))

grades = tuple(grades)
mc = MyClass(lines=list(people), header=True)
print(mc[['first_name', 'last_name', 'email']])
print(mc['first_name'])


mc = MyClass(lines=list(grades))
print(mc[[1, 2]])
print(mc[0])
[('Michael', 'Weaver', 'xdunn@hotmail.com'), ('Jackson', 'Owens', 'iedwards@yahoo.com'), ('Patrick', 'Gilmore', 'arogers@smith.com'), ('Jeffrey', 'Perez', 'plewis@chavez.com'), ('James', 'Thomas', 'fred92@yahoo.com'), ('Greg', 'Nelson', 'mmiller@lynch.com'), ('Joshua', 'White', 'steven49@gmail.com'), ('Todd', 'Francis', 'amanda23@hotmail.com'), ('Stephen', 'Shaw', 'jackduke@hotmail.com'), ('Mariah', 'Armstrong', 'rhodesnicholas@hotmail.com'), ('Anthony', 'Boyle', 'smithashlee@yahoo.com'), ('Patrick', 'Cuevas', 'ubriggs@hill.info'), ('Gerald', 'Reyes', 'brownclarence@gonzalez-moore.com'), ('Christopher', 'Calderon', 'teresa30@carpenter-warner.com'), ('Shane', 'Weiss', 'leekatherine@williams.com'), ('Crystal', 'Conley', 'chasewatkins@perez-phillips.com'), ('Jeffrey', 'Nelson', 'hsherman@gmail.com'), ('Brianna', 'Johnson', 'martinezdaniel@hotmail.com'), ('Brandon', 'Werner', 'justinfischer@gmail.com'), ('Brianna', 'Bennett', 'cindy08@gmail.com'), ('Austin', 'Fletcher', 'carolharrington@fleming.org'), ('Patrick', 'Lewis', 'lopezcarl@johnson.com'), ('Joseph', 'Smith', 'michael74@yahoo.com'), ('Sharon', 'Sullivan', 'gonzalezrobert@hotmail.com'), ('Krystal', 'Wilson', 'dawnjohnson@gmail.com'), ('Diana', 'Schmidt', 'watersryan@gmail.com'), ('Sean', 'Huff', 'byoung@gmail.com'), ('Robin', 'Nguyen', 'vhanson@yahoo.com'), ('Robyn', 'Russell', 'bfletcher@yahoo.com'), ('Tiffany', 'Smith', 'colleengarrison@hotmail.com'), ('Lori', 'Smith', 'catherine23@gmail.com'), ('Sabrina', 'Keith', 'xmurphy@yahoo.com'), ('Miguel', 'Johnson', 'aaronrichard@middleton.net'), ('Dustin', 'Barron', 'jesse93@best.com'), ('Michael', 'Robinson', 'johnperez@johnson.com'), ('Robert', 'Nguyen', 'jessica62@yahoo.com'), ('Brandon', 'Abbott', 'jennifer87@gmail.com'), ('Bruce', 'Oneill', 'morenolindsay@bass.org'), ('Linda', 'Nash', 'robertdavis@hotmail.com'), ('Kathleen', 'Cameron', 'melanie81@rogers.com'), ('Wesley', 'Wilkinson', 'clineerin@hotmail.com'), ('Debbie', 'Wallace', 'terri95@hotmail.com'), ('Kayla', 'Woodward', 'danielle65@yahoo.com'), ('Stephanie', 'Bennett', 'sjackson@yahoo.com'), ('Caleb', 'Jenkins', 'douglas63@yahoo.com'), ('Valerie', 'Edwards', 'woodardlindsey@yahoo.com'), ('Mary', 'Anderson', 'suebrown@yahoo.com'), ('Angela', 'Ray', 'swhite@yahoo.com'), ('Haley', 'Edwards', 'martinkimberly@lopez.com'), ('Charles', 'Clark', 'jessica11@hotmail.com'), ('Lisa', 'Hill', 'hsmith@baker.com'), ('Jonathan', 'Carpenter', 'fklein@yahoo.com'), ('Latoya', 'Griffith', 'ryan32@skinner.com'), ('Kim', 'Blair', 'tmurphy@flores.biz'), ('Mary', 'Salazar', 'mary64@ray.org'), ('Kenneth', 'Krueger', 'jennajoseph@yahoo.com'), ('Phillip', 'Burke', 'watsonsamuel@gmail.com'), ('Erica', 'Juarez', 'xvelasquez@hughes.com'), ('Jason', 'Watkins', 'april99@gmail.com'), ('Lee', 'Carter', 'kfletcher@yahoo.com'), ('Randy', 'Huang', 'xchurch@hotmail.com'), ('Kristina', 'Owen', 'megan24@stewart.net'), ('Beth', 'Turner', 'sydneycollins@hunter.com'), ('Michael', 'Aguirre', 'robertbowen@chavez-ortega.com'), ('Elizabeth', 'Wilson', 'christiandanielle@yahoo.com'), ('Teresa', 'Hardy', 'kdavidson@gordon.com'), ('David', 'Stewart', 'bennettwanda@vega-guerra.net'), ('Heather', 'Moore', 'mark00@hotmail.com'), ('Melissa', 'Grant', 'schaefernatalie@hotmail.com'), ('Jennifer', 'Thompson', 'moralesmartin@rodgers.com'), ('Raymond', 'Anderson', 'dprince@hotmail.com'), ('Angela', 'Ramsey', 'cparks@valdez-hudson.com'), ('Betty', 'Gonzales', 'martinezrichard@yahoo.com'), ('Thomas', 'Castaneda', 'kpena@yahoo.com'), ('Jonathan', 'Todd', 'julie68@gmail.com'), ('Stacey', 'Garcia', 'lukebradford@hotmail.com'), ('Judy', 'Figueroa', 'ystewart@yahoo.com'), ('Ashley', 'Castillo', 'cory33@king-shaw.net'), ('Zachary', 'Flores', 'zcalhoun@gmail.com'), ('Erica', 'Allen', 'michaelhall@hotmail.com'), ('Savannah', 'Potts', 'kristentaylor@yahoo.com'), ('Zachary', 'Wheeler', 'stephen63@yahoo.com'), ('Timothy', 'Thomas', 'bryanmartin@gmail.com'), ('Ann', 'Mcknight', 'kristinavelasquez@gmail.com'), ('Ruth', 'Thompson', 'denise01@burns.org'), ('Daniel', 'Levy', 'beancody@jones.com'), ('Paul', 'Hubbard', 'ubradley@yahoo.com'), ('Jason', 'Jones', 'anthony75@yahoo.com'), ('Margaret', 'Garcia', 'antonio52@gmail.com'), ('Jeremy', 'Peters', 'johnlewis@hotmail.com'), ('Mark', 'Stone', 'nmoore@hotmail.com'), ('Darius', 'Edwards', 'nchurch@yahoo.com'), ('Tracy', 'Lawson', 'piercejenna@gmail.com'), ('Christina', 'Cooper', 'ddavidson@hotmail.com'), ('Megan', 'Harris', 'ndelacruz@yahoo.com'), ('Timothy', 'Jones', 'jenniferadkins@griffin.biz'), ('Tracie', 'Burch', 'evansmiguel@yahoo.com'), ('Jason', 'Chung', 'kenneththompson@baxter.com'), ('Samantha', 'Melton', 'bcurtis@hotmail.com'), ('Michael', 'Hansen', 'phillipssean@hotmail.com')]
['Michael', 'Jackson', 'Patrick', 'Jeffrey', 'James', 'Greg', 'Joshua', 'Todd', 'Stephen', 'Mariah', 'Anthony', 'Patrick', 'Gerald', 'Christopher', 'Shane', 'Crystal', 'Jeffrey', 'Brianna', 'Brandon', 'Brianna', 'Austin', 'Patrick', 'Joseph', 'Sharon', 'Krystal', 'Diana', 'Sean', 'Robin', 'Robyn', 'Tiffany', 'Lori', 'Sabrina', 'Miguel', 'Dustin', 'Michael', 'Robert', 'Brandon', 'Bruce', 'Linda', 'Kathleen', 'Wesley', 'Debbie', 'Kayla', 'Stephanie', 'Caleb', 'Valerie', 'Mary', 'Angela', 'Haley', 'Charles', 'Lisa', 'Jonathan', 'Latoya', 'Kim', 'Mary', 'Kenneth', 'Phillip', 'Erica', 'Jason', 'Lee', 'Randy', 'Kristina', 'Beth', 'Michael', 'Elizabeth', 'Teresa', 'David', 'Heather', 'Melissa', 'Jennifer', 'Raymond', 'Angela', 'Betty', 'Thomas', 'Jonathan', 'Stacey', 'Judy', 'Ashley', 'Zachary', 'Erica', 'Savannah', 'Zachary', 'Timothy', 'Ann', 'Ruth', 'Daniel', 'Paul', 'Jason', 'Margaret', 'Jeremy', 'Mark', 'Darius', 'Tracy', 'Christina', 'Megan', 'Timothy', 'Tracie', 'Jason', 'Samantha', 'Michael']
[]
[]
[('92', '77'), ('74', '93'), ('83', '96'), ('100', '72'), ('77', '96'), ('100', '86'), ('66', '91'), ('97', '86'), ('95', '98'), ('78', '76'), ('78', '100'), ('82', '92'), ('83', '78'), ('89', '81'), ('86', '94'), ('96', '75'), ('85', '72'), ('83', '68'), ('70', '99'), ('80', '89'), ('79', '100'), ('100', '65'), ('68', '67'), ('94', '71'), ('89', '99'), ('94', '65'), ('83', '91'), ('97', '96'), ('65', '78'), ('96', '85'), ('85', '69'), ('82', '82'), ('88', '76'), ('66', '85'), ('75', '98'), ('85', '89'), ('93', '85'), ('86', '90'), ('96', '82'), ('85', '98'), ('98', '95'), ('84', '82'), ('95', '91'), ('80', '83'), ('67', '89'), ('65', '72'), ('99', '89'), ('77', '91'), ('68', '97'), ('82', '66'), ('86', '66'), ('91', '98'), ('94', '77'), ('69', '80'), ('100', '91'), ('77', '68'), ('65', '100'), ('75', '75'), ('91', '84'), ('71', '79'), ('69', '71'), ('79', '91'), ('91', '87'), ('93', '97'), ('100', '75'), ('68', '66'), ('82', '74'), ('66', '96'), ('88', '85'), ('78', '76'), ('97', '73'), ('88', '94'), ('92', '99'), ('86', '98'), ('68', '87'), ('88', '92'), ('66', '72'), ('70', '95'), ('69', '94'), ('86', '86'), ('96', '87'), ('76', '95'), ('66', '72'), ('83', '85'), ('98', '79'), ('69', '94'), ('78', '88'), ('66', '67'), ('89', '78'), ('92', '66'), ('87', '69'), ('86', '88'), ('77', '77'), ('93', '99'), ('86', '83'), ('78', '84'), ('74', '95'), ('71', '87'), ('71', '69'), ('81', '80')]
['student1', 'student2', 'student3', 'student4', 'student5', 'student6', 'student7', 'student8', 'student9', 'student10', 'student11', 'student12', 'student13', 'student14', 'student15', 'student16', 'student17', 'student18', 'student19', 'student20', 'student21', 'student22', 'student23', 'student24', 'student25', 'student26', 'student27', 'student28', 'student29', 'student30', 'student31', 'student32', 'student33', 'student34', 'student35', 'student36', 'student37', 'student38', 'student39', 'student40', 'student41', 'student42', 'student43', 'student44', 'student45', 'student46', 'student47', 'student48', 'student49', 'student50', 'student51', 'student52', 'student53', 'student54', 'student55', 'student56', 'student57', 'student58', 'student59', 'student60', 'student61', 'student62', 'student63', 'student64', 'student65', 'student66', 'student67', 'student68', 'student69', 'student70', 'student71', 'student72', 'student73', 'student74', 'student75', 'student76', 'student77', 'student78', 'student79', 'student80', 'student81', 'student82', 'student83', 'student84', 'student85', 'student86', 'student87', 'student88', 'student89', 'student90', 'student91', 'student92', 'student93', 'student94', 'student95', 'student96', 'student97', 'student98', 'student99', 'student100']

12.4.2. Add functionality to calculate means#

  • Add functionality to calculate mean of a column(s)

    • Before you can calculate the mean, you must cast/convert columns to the correct data type.

from collections import defaultdict



class ListV2:
    def __init__(self, values):
        self.values = values
        
    def __add__(self, right):
        output = [l + r for l, r in zip(self.values, right.values)]
#         return ListV2(output)
        return output
    
    def __repr__(self):
        return str(self.values)
        

class MyClass:
    def __init__(self, **kwargs):
        self.data = defaultdict(list)
        header = kwargs.get('header')
        lines = kwargs.get('lines')
        if header:
            header = lines.pop(0)
        else:
            header = list(range(len(lines[0])))
        
        for line in lines:
            row = dict(zip(header, line))
            for key,value in row.items():
                self.data[key].append(value)
              
    def __setitem__(self, key, value): # MyCLass[key] = value
        self.data[key] = value
        
    def __getitem__(self, key): # MyClass[key]
        if type(key) in [str, int]:
            return ListV2(self.data[key])  
        elif isinstance(key, list):
            output = []
            for k in key:
                output.append(self.data[k])
            output = list(zip(*output))
                
            return output
        
    def as_type(self, column, cast_type):
        self.data[column] = list(map(cast_type, self.data[column]))

filename = 'testdata.txt'
grades = []
with open(filename) as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        grades.append(line.strip().split(','))

grades = tuple(grades)

mc = MyClass(lines=list(grades))
print(mc[[1, 2]])
mc.as_type(1, int)
print(mc[[1, 2]])
mc.as_type(1, int)
print(mc[[1, 2]])
[('92', '77'), ('74', '93'), ('83', '96'), ('100', '72'), ('77', '96'), ('100', '86'), ('66', '91'), ('97', '86'), ('95', '98'), ('78', '76'), ('78', '100'), ('82', '92'), ('83', '78'), ('89', '81'), ('86', '94'), ('96', '75'), ('85', '72'), ('83', '68'), ('70', '99'), ('80', '89'), ('79', '100'), ('100', '65'), ('68', '67'), ('94', '71'), ('89', '99'), ('94', '65'), ('83', '91'), ('97', '96'), ('65', '78'), ('96', '85'), ('85', '69'), ('82', '82'), ('88', '76'), ('66', '85'), ('75', '98'), ('85', '89'), ('93', '85'), ('86', '90'), ('96', '82'), ('85', '98'), ('98', '95'), ('84', '82'), ('95', '91'), ('80', '83'), ('67', '89'), ('65', '72'), ('99', '89'), ('77', '91'), ('68', '97'), ('82', '66'), ('86', '66'), ('91', '98'), ('94', '77'), ('69', '80'), ('100', '91'), ('77', '68'), ('65', '100'), ('75', '75'), ('91', '84'), ('71', '79'), ('69', '71'), ('79', '91'), ('91', '87'), ('93', '97'), ('100', '75'), ('68', '66'), ('82', '74'), ('66', '96'), ('88', '85'), ('78', '76'), ('97', '73'), ('88', '94'), ('92', '99'), ('86', '98'), ('68', '87'), ('88', '92'), ('66', '72'), ('70', '95'), ('69', '94'), ('86', '86'), ('96', '87'), ('76', '95'), ('66', '72'), ('83', '85'), ('98', '79'), ('69', '94'), ('78', '88'), ('66', '67'), ('89', '78'), ('92', '66'), ('87', '69'), ('86', '88'), ('77', '77'), ('93', '99'), ('86', '83'), ('78', '84'), ('74', '95'), ('71', '87'), ('71', '69'), ('81', '80')]
[(92, '77'), (74, '93'), (83, '96'), (100, '72'), (77, '96'), (100, '86'), (66, '91'), (97, '86'), (95, '98'), (78, '76'), (78, '100'), (82, '92'), (83, '78'), (89, '81'), (86, '94'), (96, '75'), (85, '72'), (83, '68'), (70, '99'), (80, '89'), (79, '100'), (100, '65'), (68, '67'), (94, '71'), (89, '99'), (94, '65'), (83, '91'), (97, '96'), (65, '78'), (96, '85'), (85, '69'), (82, '82'), (88, '76'), (66, '85'), (75, '98'), (85, '89'), (93, '85'), (86, '90'), (96, '82'), (85, '98'), (98, '95'), (84, '82'), (95, '91'), (80, '83'), (67, '89'), (65, '72'), (99, '89'), (77, '91'), (68, '97'), (82, '66'), (86, '66'), (91, '98'), (94, '77'), (69, '80'), (100, '91'), (77, '68'), (65, '100'), (75, '75'), (91, '84'), (71, '79'), (69, '71'), (79, '91'), (91, '87'), (93, '97'), (100, '75'), (68, '66'), (82, '74'), (66, '96'), (88, '85'), (78, '76'), (97, '73'), (88, '94'), (92, '99'), (86, '98'), (68, '87'), (88, '92'), (66, '72'), (70, '95'), (69, '94'), (86, '86'), (96, '87'), (76, '95'), (66, '72'), (83, '85'), (98, '79'), (69, '94'), (78, '88'), (66, '67'), (89, '78'), (92, '66'), (87, '69'), (86, '88'), (77, '77'), (93, '99'), (86, '83'), (78, '84'), (74, '95'), (71, '87'), (71, '69'), (81, '80')]
[(92, '77'), (74, '93'), (83, '96'), (100, '72'), (77, '96'), (100, '86'), (66, '91'), (97, '86'), (95, '98'), (78, '76'), (78, '100'), (82, '92'), (83, '78'), (89, '81'), (86, '94'), (96, '75'), (85, '72'), (83, '68'), (70, '99'), (80, '89'), (79, '100'), (100, '65'), (68, '67'), (94, '71'), (89, '99'), (94, '65'), (83, '91'), (97, '96'), (65, '78'), (96, '85'), (85, '69'), (82, '82'), (88, '76'), (66, '85'), (75, '98'), (85, '89'), (93, '85'), (86, '90'), (96, '82'), (85, '98'), (98, '95'), (84, '82'), (95, '91'), (80, '83'), (67, '89'), (65, '72'), (99, '89'), (77, '91'), (68, '97'), (82, '66'), (86, '66'), (91, '98'), (94, '77'), (69, '80'), (100, '91'), (77, '68'), (65, '100'), (75, '75'), (91, '84'), (71, '79'), (69, '71'), (79, '91'), (91, '87'), (93, '97'), (100, '75'), (68, '66'), (82, '74'), (66, '96'), (88, '85'), (78, '76'), (97, '73'), (88, '94'), (92, '99'), (86, '98'), (68, '87'), (88, '92'), (66, '72'), (70, '95'), (69, '94'), (86, '86'), (96, '87'), (76, '95'), (66, '72'), (83, '85'), (98, '79'), (69, '94'), (78, '88'), (66, '67'), (89, '78'), (92, '66'), (87, '69'), (86, '88'), (77, '77'), (93, '99'), (86, '83'), (78, '84'), (74, '95'), (71, '87'), (71, '69'), (81, '80')]

12.4.2.1. Calculate Means#

from collections import defaultdict


class ListV2:
    def __init__(self, values):
        self.values = values
        
    def __add__(self, right):
        output = [l + r for l, r in zip(self.values, right.values)]
#         return ListV2(output)
        return output
    
    def __repr__(self):
        return str(self.values)
        


class MyClass:
    def __init__(self, **kwargs):
        self.data = defaultdict(list)
        header = kwargs.get('header')
        lines = kwargs.get('lines')
        if header:
            header = lines.pop(0)
        else:
            header = list(range(len(lines[0])))
        
        for line in lines:
            row = dict(zip(header, line))
            for key,value in row.items():
                self.data[key].append(value)
              
    def __setitem__(self, key, value): # MyCLass[key] = value
        self.data[key] = value
        
    def __getitem__(self, key): # MyClass[key]
        if type(key) in [str, int]:
            return ListV2(self.data[key])  
        elif isinstance(key, list):
            output = []
            for k in key:
                output.append(self.data[k])
            output = list(zip(*output))
                
            return output
        
    def as_type(self, column, cast_type):
        self.data[column] = list(map(cast_type, self.data[column]))
        
    def mean(self, columns):
        if type(columns) in [str, int]:
            data = self.data[columns]
            return sum(data)/len(data)
        elif isinstance(columns, list):
            data = []
            for column in columns:
                data.append(sum(self.data[column])/len(self.data[column]))
            
            data =  [columns, data]
            return MyClass(lines=data, header=True)

filename = 'testdata.txt'
grades = []
with open(filename) as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        grades.append(line.strip().split(','))

grades = tuple(grades)

mc = MyClass(lines=list(grades))
mc.as_type(1, int)
mc.as_type(2, int)
a = mc.mean([1, 2])
print(a.data)       
defaultdict(<class 'list'>, {1: [82.75], 2: [84.13]})

12.4.3. Add functionality to Slice#

Basic example

class AClass:
    
    def __getitem__(self, a):
        print(a, type(a))
a = AClass()   
a[1:10:2, :]
(slice(1, 10, 2), slice(None, None, None)) <class 'tuple'>
b = slice(1, 10, 2)
print(b.start)
print(b.stop)
print(b.step)

print(a[:, 5:20:2])
1
10
2
(slice(None, None, None), slice(5, 20, 2)) <class 'tuple'>
None

12.4.3.1. How to Transpose#

x = [[1,2,3], [4, 5, 6], [7, 8,9]]
for c1, c2, c3 in zip(*x):
    print(c1, c2, c3)


x = {1: [5, 6], 2: [7, 8]}
list(zip(*x.values()))
1 4 7
2 5 8
3 6 9
[(5, 7), (6, 8)]
from collections import defaultdict



class ListV2:
    def __init__(self, values):
        self.values = values
        
    def __add__(self, right):
        output = [l + r for l, r in zip(self.values, right.values)]
#         return ListV2(output)
        return output
    
    def __repr__(self):
        return str(self.values)
        

class MyClass:
    def __init__(self, **kwargs):
        self.data = defaultdict(list)
        header = kwargs.get('header')
        lines = kwargs.get('lines')
        if header:
            self.header = lines.pop(0)
        else:
            self.header = list(range(len(lines[0])))
        
        for line in lines:
            row = dict(zip(self.header, line))
            for key,value in row.items():
                self.data[key].append(value)
              
    def __setitem__(self, key, value): # MyCLass[key] = value
        self.data[key] = value
        
    def __getitem__(self, key): # MyClass[key]
        if type(key) in [str, int]:
            return ListV2(self.data[key])  
        elif isinstance(key, list):
            output = []
            for k in key:
                output.append(self.data[k])
            output = list(zip(*output))       
            return output
        elif isinstance(key, slice):
            all_rows = list(zip(*self.data.values()))
            output = all_rows[key.start:key.stop:key.step]
            return MyClass(lines=output)
            
        elif isinstance(key, tuple):
            row = key[0]
            col = key[1]
            columns = list(self.data.keys())
            columns = columns[col]
            data = []
            for col in columns:
                data.append(self.data[col])
            
            
            all_rows = list(zip(*data))
            output = all_rows[row.start:row.stop:row.step]
            output = [columns] + output
            return MyClass(lines=output, header=True)
            
            
        
    def as_type(self, column, cast_type):
        self.data[column] = list(map(cast_type, self.data[column]))
        
    def mean(self, columns):
        if type(columns) in [str, int]:
            data = self.data[columns]
            return sum(data)/len(data)
        elif isinstance(columns, list):
            data = []
            for column in columns:
                data.append(sum(self.data[column])/len(self.data[column]))
            
            data =  [columns, data]
            return MyClass(lines=data, header=True)
        
    def __repr__(self):
        print(self.header)
        for ele in list(zip(*self.data.values())):
            print(ele)


filename = 'testdata.txt'
grades = []
with open(filename) as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        grades.append(line.strip().split(','))

grades = tuple(grades)

mc = MyClass(lines=list(grades))
mc.as_type(1, int)
mc.as_type(2, int)  
a = mc[5:21:2, 1:6] 
print(a)        
[1, 2, 3, 4, 5]
(100, 86, '84', '70', '71')
(97, 86, '75', '69', '88')
(78, 76, '73', '88', '86')
(82, 92, '85', '95', '86')
(89, 81, '92', '75', '66')
(96, 75, '78', '91', '83')
(83, 68, '91', '74', '66')
(80, 89, '73', '76', '72')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[8], line 103
    101 mc.as_type(2, int)  
    102 a = mc[5:21:2, 1:6] 
--> 103 print(a)        

TypeError: __str__ returned non-string (type NoneType)