6

I have a program that I am writing in Python that does the following:

The user enters the name of a folder. Inside that folder a 8-15 .dat files with different extensions.

The program opens those dat files, enters them into a SQL database and then allows the user to select different changes made to the database. Then the database is exported back to the .dat files. There are about 5-10 different operations that could be performed.

The way that I had planned on designing this was to create a standard class for each group of files. The user would enter the name of the folder and an object with certain attributes (file names, dictionary of files, version of files (there are different versions), etc) would get created. Determining these attributes requires opening a few of these files, reading file names, etc.

Should this action be carried out in the __init__ method? Or should this action be carried our in different instance methods that get called in the __init__ method? Or should these methods be somewhere else, and only be called when the attribute is required elsewhere in the program?

I have already written this program in Java. And I had a constructor that called other methods in the class to set the object's attributes. But I was wondering what standard practice in Python would be.

Constantinius
  • 34,183
  • 8
  • 77
  • 85
Tim Brooks
  • 162
  • 11

4 Answers4

3

Well, there is nothing special about good OOP practices in Python. Decomposition of one big method into a bunch of small ones is great idea both in Java and in Python. Among other things small methods gives you an opportunity to write different constructors:

class GroupDescriptor(object):
    def __init__(self, file_dictionary):
        self.file_dict = file_dictionary
        self.load_something(self.file_dict['file_with_some_info'])

    @classmethod
    def from_filelist(cls, list_of_files):
        file_dict = cls.get_file_dict(list_of_files)
        return cls(file_dict)

    @classmethod
    def from_dirpath(cls, directory_path):
        files = self.list_dir(directory_path)
        return cls.from_filelist(files)

Besides, I don't know how it is in Java but in Python you don't have to worry about exceptions in constructor because they are finely handled. Therefore, it is totally normal to work with such exception-prone things like files.

Kirill
  • 3,364
  • 2
  • 21
  • 36
  • +1 Best answer so far! ;-) I love the decomposition innuendo with the "polymorphic" constructor/initialisator finishing-move even if it's slightly sloppy, because you didn't elaborate it! – Don Question Mar 12 '12 at 15:59
1

It looks the action you are describing are initialization, so it'd be perfectly ok to put them into __init__. On the other hand, these actions seem to be pretty expensive, and probably useful in the other part of a program, so you might want to encapsulate them in some separate function.

Roman Bodnarchuk
  • 29,461
  • 12
  • 59
  • 75
1

The __init__ method is called when the object is instantiated.

Coming from a C++ background I believe its not good to do actual work other than initialization in the constructor.

DSM
  • 342,061
  • 65
  • 592
  • 494
nate_weldon
  • 2,289
  • 1
  • 26
  • 32
1

There's no problem with having a long __init__ method, but I would avoid it simply because its more difficult to test. My approach would be to create smaller methods which are called from __init__. This way you can test them and the initialization separately.

Whether they should be called when needed or run up front really depends on what you need them to do. If they are expensive operations, and are usually not all needed, then maybe its better to only call them when needed. On the other hand, you might want to run them up front so that there is no lag when the attributes are required.

Its not clear from your question whether you actually need a class though. I have no experience with Java, but I understand that everything in it is a class. In python it is perfectly acceptable to just have a function if that's all that's required, and to only create classes when you need instances and other classy things.

aquavitae
  • 17,414
  • 11
  • 63
  • 106
  • Essentially I have a group of files that could be categorized as a "job." Different functions perform different actions on this job to produce the desired result of the program. That is why I thought it best keep it as a class. – Tim Brooks Mar 12 '12 at 15:16
  • And it seems like this is what you're suggesting: __init__(self, foldername): self.filelist = getfilelist(...); self.fileversion = getfileversion(...); etc? Except in the instance that one of the methods is expensive and only necessary in certain instances? – Tim Brooks Mar 12 '12 at 15:16
  • If that's what your code's doing, then perhaps you should use [lazy properties](http://stackoverflow.com/q/3012421/1235039) instead. There are many ways to do this, it just depends on your requirements and preference. – aquavitae Mar 12 '12 at 15:28