1

Let me explain a little better with some code.

class Opcode (Enum):
    WEEK=    1
    EMAIL=   2
    NAME=    3
    DOB=     4

I then have a parameters class which processes data received by the server, and stores it in the appropriate variable :

class parameters:
    week = None
    email = None
    name = None
    dob = None
    
    def __init__(self, conn):
        #some initialization stuff, irrelevant
        
    def process_input(self, opcode, data):
        if opcode == Opcode.WEEK.value:
            self.week = data
            
        elif opcode == Opcode.EMAIL.value:
            self.email= data
         
        elif opcode == Opcode.NAME.value:
            self.name= data

        elif opcode == Opcode.DOB.value:
            self.dob= data
         .
         .
         .
 
        else :
            print("unknown opcode provided. disconnecting ... ")
            #disconnect from client ...

This doesn't seem too bad with only 4 opcodes, but in reality my program has 12 opcodes and so this long if...elif...elif...else branch seems like a bad way of processing inputs. I'm use to working with C++, in which case I'd have used a switch-case, but they don't appear to be a thing in python, so perhaps there is a better solution I just don't know about. Any advice?

jf192210
  • 127
  • 7

1 Answers1

1

As I suggested in a comment, using a dictionary would provide a way of avoiding the series of if/elif statements. It would also be faster than executing them (for large numbers of opcodes) and can be implemented in a way that makes it largely data-driven and therefore very easy to extend — just add more values to the enum.

import enum

class Opcode(enum.IntEnum):
    WEEK = 1
    EMAIL = 2
    NAME = 3
    DOB = 4

# Create a dictionary mapping Opcode values to lowercase attribute names.
opcode_dict = {opcode.value: opcode.name.lower() for opcode in Opcode}
print(opcode_dict)


class Parameters:
    def __init__(self, conn):
        #some initialization stuff, irrelevant
        ...

    def process_input(self, opcode, data):
        try:
            setattr(self, opcode_dict[opcode], data)
        except KeyError:
            print("unknown opcode provided. disconnecting...")
            # Disconnect from client...

    def __repr__(self):
        pairs = ', '.join('{}={!r}'.format(attrname, getattr(self, attrname, None))
                                            for attrname in opcode_dict.values())
        return '{}({})'.format(type(self).__name__, pairs)


if __name__ == '__main__':

    import random

    params = Parameters(None)
    for opcode in Opcode:
        params.process_input(opcode, random.randint(1, 10))
        print(params)

    # Try a bogus opcode.
    params.process_input(42, random.randint(1, 10))
martineau
  • 119,623
  • 25
  • 170
  • 301
  • martineau! You dont know how much help you've been. Thank you so much for this follow up answer, i'll definitely implement it. – jf192210 Sep 03 '20 at 22:25
  • jf192210: You're welcome. Note that the `_repr__()` method is strictly optional, and is only there to make printing instances of the class more informative. – martineau Sep 03 '20 at 22:34
  • Ah, well I quite like it in any case, so i'll keep it for neater debugging aha – jf192210 Sep 03 '20 at 22:45