D Emma
D Emma

Reputation: 317

How to create a many-to-many relationship variable and increase code usability?

I'm trying to create a common utility for file transfer, from source to destination. The arguments are separated into dir and filename, which is the result of os.path.dirname(some_file) and os.path.basename(some_file), respectively. The destination filename is the same as the source filename by default if not specified.

I have created a script that at least is working perfectly well with the specific requirements in my first project. But as you can notice, the get_src_des method is very repetitive that I want to improve the code re-usability out from the nasty if...elif... statement. Anyone has better idea to rewrite this method?

class FileTransfer:

    def __init__(self, ftp_dir, local_dir, ftp_filename=None, local_filename=None):
        self.ftp_dir = ftp_dir
        self.ftp_filename = ftp_filename
        self.local_dir = local_dir
        self.local_filename = local_filename

        self.ftp_dict = self.get_group(ftp_dir, ftp_filename)
        self.local_dict = self.get_group(local_dir, local_filename)

    @staticmethod
    def get_group(dir, filename):
        group = {
            "dir": dir,
            "filename": filename,
        }
        return group

    def get_src_des(self, src):
        if src == "ftp":
            dict_src = self.ftp_dict
            dict_des = self.local_dict
        elif src == "local":
            dict_src = self.local_dict
            dict_des = self.ftp_dict
        else:
            dict_src = None
            dict_des = None

        return dict_src, dict_des

    # other methods, such as download_from_src_to_des, upload_from_src_to_des, ...

Upvotes: 1

Views: 54

Answers (2)

Yakov Dan
Yakov Dan

Reputation: 3372

Yes. This is classic use case for a dictionary.

You can rewrite your code as follows:

class FileTransfer:

    def __init__(self, ftp_dir, local_dir, ftp_filename=None, local_filename=None):
        self.ftp_dir = ftp_dir
        self.ftp_filename = ftp_filename
        self.local_dir = local_dir
        self.local_filename = local_filename

        self.ftp_dict = self.get_group(ftp_dir, ftp_filename)
        self.local_dict = self.get_group(local_dir, local_filename)
        self.param_dict = {
            'ftp':(self.ftp_dict,self.local_dict),
            'local' : (self.local_dict,self.ftp_dict)
        }

    @staticmethod
    def get_group(dir, filename):
        group = {
            "dir": dir,
            "filename": filename,
        }
        return group

    def get_src_des(self, src):
        if src in param_dict:
           return param_dict[src]

        else:
          return (None,None)

Next time, instead of adding another elif statement, you just add another entry in your param_dict

Upvotes: 2

martineau
martineau

Reputation: 123541

I agree that that this could be done with a dictionary, as @Yakov Dan's answer suggests, but I would code it as shown below, which doesn't require any other changes to the class and is more dynamic.

The get_group() method could be written more concisely, as indicated.

class FileTransfer:
    ...

    @staticmethod
    def get_group(dir, filename):
        return dict(dir=dir, filename=filename)

    def get_src_des(self, src):
        return {
            'ftp': (self.ftp_dict, self.local_dict),
            'local': (self.local_dict, self.ftp_dict)
        }.get(src, (None, None))

Upvotes: 1

Related Questions