1

I have 2 classes:

class ClassOne:
    def __init__(self, file_name):
        self.file_name = file_name
        self.dict = {}

    def load(self):
        #reads from file and parse into dictionary self.dict
       


    def regions(self):
        return list(self.dict.keys()) #returns a list of keys of the dictionary dict

and

class ClassTwo:
    def __init__(self, file_name):
        self.file_name = file_name
        self.dict = {}

    def load(self):
        regions = ClassOne.regions(self)#The issue is here

The load() method does similar things in both classes: open file csv, read from file and parse data into dictionary dict. The only difference that method load() of ClassTwo must call method regions() of the class ClassOne Also, I have main function where I create objects :

def main():

    class_one_object = ClassOne("file1.csv")
    class_one_object.load ():

    class_two_object = ClassTwo("file2.csv")
    class_two_object.load ():
   

if __name__ == "__main__":
    main()

The problem is that I get empty list here: regions = ClassOne.regions(self) because I call ClassOne.regions() with self of ClassTwo, but I need to pass self of ClassOne there somehow.

Also, if I create class_one_object, class_two_object without main, everything works, but I need to use main. Could you help me with the issue, please? I would appreciate any help. Thanks.

andsemenov
  • 51
  • 8
  • Why can't `ClassTwo` just have a copy of the code from `ClassOne.regions`? You've already done that in the `__init__()` methods. – quamrana Oct 15 '22 at 15:21
  • Thank you for response. I don't think it solves the issue that I described. – andsemenov Oct 15 '22 at 16:15
  • I don't see why not. Why do you have two classes and you want one to call the other? Surely they have their own code and operate on their own data? – quamrana Oct 15 '22 at 16:21
  • 1
    You are right, they operate on different data. ClassOne has method load() - it reads data from file1 and store in dictionary. Also, it has method regions() - it returns a list of dictionary's keys. But in ClassTwo, I need to invoke the load() method of ClassOne and reed from file 2 and story only data which corresponds with the list of keys from regions() method of another class. – andsemenov Oct 15 '22 at 17:26
  • I think the real question is, if the `regions` method is needed by both classes, why is it a method of one of them? Shouldn't it be a top-level function? Or maybe a method of a shared base class? – Blckknght Oct 15 '22 at 20:32
  • What does `regions` have to do with `ClassOne`? – chepner Oct 15 '22 at 20:35
  • @Blckknght, thank you for your response. Following the task, it requires creating methods regions() for both classes. I think the real question how to get access to method regions() of ClassOne from method load() of ClassTwo because if I pass self from class2, it returns empty array. – andsemenov Oct 15 '22 at 20:42
  • @chepner Thank you for the answer. The method regions() returns list of keys of dictionary self.dict. Both classes are similar and has the same structure. I think that inheritance can help make the code cleaner. in method loads() of ClassTwo I would like get a list of keys of self.dict of ClassTwo (it stores data from file1) calling method regions() of ClassOne. – andsemenov Oct 15 '22 at 20:52
  • But `region` *only* uses an instance of `ClassTwo`; why isn't it an instance method of `ClassTwo`? – chepner Oct 15 '22 at 21:44
  • Ok I got it. Are your Classes both Singletons ? – pippo1980 Oct 15 '22 at 21:49
  • @chepner I think instance method regions() of ClassTwo can return only list 0f regions from file2, not file1. I don't know how to call instance method of ClassOne regions in method loads() of ClassTwo. If I could pass instance of ClassOne there, it would help. – andsemenov Oct 15 '22 at 22:05
  • @pippo1980 I am not sure about singletons. Hypothetically, it allows to create multiple instances of both classes, but one instance for each class is enough for the task. – andsemenov Oct 15 '22 at 22:10

2 Answers2

2

Inheritance allows you to do what you want without any copy-pasting or static methods. You create a very detailed ClassOne then inherit it in ClassTwo so that you can access load and regions from there.

Notice the use of super() that gives you a handle to ClassOne while being inside ClassTwo, which allows you to use ClassOne.load.

class ClassOne:
    def __init__(self, file_name):
        self.file_name = file_name
        self.dict = {}

    def load(self):
        print(f"Loading {self.file_name}")
        pass # Do something here.

    def regions(self):
        return list(self.dict.keys()) 


class ClassTwo(ClassOne):
    def load(self):
        super().load() # <---
        self.regions()
        

c1 = ClassOne("file1.csv")
c1.load()
# >>> Loading file1.csv

c2 = ClassTwo("file2.csv")
c2.load()
# >>> Loading file2.csv
Guimoute
  • 4,407
  • 3
  • 12
  • 28
  • 1
    need to explain load overriding too: What is overriding? Overriding is the ability of a class to change the implementation of a method provided by one of its ancestors. – pippo1980 Oct 15 '22 at 20:36
  • @Guimoute, thank you for the code. My load() method for class2 is a bit different, should I just override that? If I understand properly, I need to call super().regions() in method load() of class? – andsemenov Oct 15 '22 at 21:07
0

OK, tried to understand your question.

my inputs, file1.csv:

a,1,2,3
b,4,5,6

and file2.csv

c,7,8,9
d,10,11,12

my code :

import csv


class ClassOne:
    def __init__(self, file_name):
        self.file_name = file_name
        self.dict = {}

    def load(self):
        #reads from file and parse into dictionary self.dict
        with open(self.file_name, newline='') as csvfile:
            spamreader = csv.reader(csvfile, delimiter=',')
            for row in spamreader:
                    print(' '.join(row))
                    self.dict[row[0]] = row[1:]

    @staticmethod ## works with this line commented out or not
    def regions(self):
        return list(self.dict.keys()) #returns a list of keys of the dictionary dict


class ClassTwo:
    def __init__(self, file_name):
        self.file_name = file_name
        self.dict = {}

    def load(self):
        print('****')
        #reads from file and parse into dictionary self.dict
        with open(self.file_name, newline='') as csvfile:
            spamreader = csv.reader(csvfile, delimiter=',')
            for row in spamreader:
                    print(' '.join(row))
                    self.dict[row[0]] = row[1:]
        regions = ClassOne.regions(self)#The issue is here
        print('\nregions', regions)


def main():

    class_one_object = ClassOne("file1.csv")
    class_one_object.load()

    class_two_object = ClassTwo("file2.csv")
    class_two_object.load()
   

if __name__ == "__main__":
    main()

output:

a 1 2 3
b 4 5 6
****
c 7 8 9
d 10 11 12

regions ['c', 'd']

but I dont get any error, please let me know what I am doing wrong

pippo1980
  • 2,181
  • 3
  • 14
  • 30
  • Hi, thank you for your response. I can call both methods load() without any error. I omitted the code of them because it works. The problem is that in the method load() of ClassTwo need to call method regions() of ClassOne. I should read data from file1 and load into dictionary dict - ClassOne part. Then, call method regions() of Class one - it returns a list of keys of dict from ClassOne and I need to read data from file2 and load in self.dict dictionary only data which corresponds to the list of keys. It worked when I created class_one_object and class_two_object inside main. – andsemenov Oct 15 '22 at 17:22
  • in my code ClassTwo load contains regions = ClassOne.regions(self) and the method works – pippo1980 Oct 15 '22 at 17:31
  • I see: The @staticmethod is a built-in decorator that defines a static method in the class in Python. A static method doesn't receive any reference argument whether it is called by an instance of a class or by the class itself. – pippo1980 Oct 15 '22 at 17:58
  • I am creating self.dict inside the @static method .... – pippo1980 Oct 15 '22 at 18:08
  • I tried without @staticmethod. This regions = ClassOne.regions(self) returns empty list. – andsemenov Oct 15 '22 at 18:19
  • I launched your code and it is working. I will find issues on my side. Thank you so much! – andsemenov Oct 15 '22 at 18:28
  • @pippo1980 You can't just copy paste the content of a method from ClassOne to ClassTwo and call it a day... – Guimoute Oct 15 '22 at 19:26
  • @guimote, yep I know trying to figure out how '@staticmethod' works and how the interpreter sees it, I got python2 is different from 3, getting help from https://stackoverflow.com/questions/43587044/do-we-really-need-staticmethod-decorator-in-python-to-declare-static-method, https://stackoverflow.com/questions/55080991/does-the-staticmethod-decorator-do-anything – pippo1980 Oct 15 '22 at 19:30
  • @pippo1980 Your code works, but I expected another output. When you call the method regions() of the ClassOne here: regions = ClassOne.regions(self), self there is from ClassTwo and it reads data from file2 and store it in self.dict for class2. In your output the code returns ['c', 'd'], but expected output should be ['a','b'] because I am looking for way to call method of ClassOne in ClassTwo with context of ClassOne (get data from file1 and ClassOne.dict, not from file2 and ClassTwo.dict). In my case, it calls ClassOne.load for ClassTwo.dict which is still empty. – andsemenov Oct 15 '22 at 19:42
  • now you're mixing up classes and instances.... got staticmethod and inheritance first.... – pippo1980 Oct 15 '22 at 20:06
  • @pippo1980 Sorry about mixing classes and instances, it is my first code in Python and knowledge in oop around 0. – andsemenov Oct 15 '22 at 20:13
  • yep ..... sure ... lost in inheritance right now – pippo1980 Oct 15 '22 at 20:31
  • @andsemenov want my -2 points back please upvote my What is overriding? Overriding is the ability of a class to change the implementation of a method provided by one of its ancestors. comment above – pippo1980 Oct 15 '22 at 20:37
  • cheers, plenty of topics to review about classes for me – pippo1980 Oct 15 '22 at 21:04