0

I have a class with different methods inside it. In this project, I have to read in the input and call the methods according to what I receive in input. Here is my code

import sys

MIN_SIZE = 5
MAX_SIZE = 20
INFO = 'name="FabienLeGenie", version="1.0", author="TheBoss", country="Reu"'
AI = "X"
MANAGER = "O"

class Protocol:
    def __init__(self):
        self.size = 0
        self.board = []

    def startGame(self, size):
        self.size = size
        if self.size > MAX_SIZE or self.size < MIN_SIZE:
            print("ERROR message - {} is not a valid size".format(self.size), flush=True)
            sys.exit(84)
        self.board = [[0 for x in range(self.size)] for y in range(self.size)]
        print("OK - everything is good", flush=True)

    def getBoard(self) -> list:
        return self.board

    def aboutGame(self):
        print(INFO, flush=True)

    def endGame(self):
        sys.exit(0)

    def turnGame(self, pos):
        self.board[pos[0]][pos[1]] = MANAGER
        print(self.board)

def begin():
    jb = Protocol()

    jb.startGame(20)
    jb.aboutGame()
    jb.turnGame((3, 3))
    a = jb.getBoard()
    jb.endGame()
    print(a)

    # while True:
    #     data = sys.stdin.readline()
    #     protocol = data.strip().split(" ")
    #     print(protocol[1])
    #     print(protocol[2])

if __name__ == "__main__":
    begin()

So for example, if I receive BEGIN in input, I have to execute startGame.

I'm trying to find a solution to make my method calls dynamic avoiding the if statement abuse. I thought of using an array or a dictionnary for it but I don't know how to manage to send arguments in it because as you may have seen, some of my methods take arguments and other not. Is it possible to create a dictionnary with methods from a class like that ?

It could look something like that:

dict = {
 "BEGIN": jb.startGame,
 "END": jb.endGame,
 "TURN": jb.turnGame,  # <- how to send arguments here ?
}

dict["TURN"](myArgs)  # <- is it like that ?

in the case the dictionnary I made up their is good, does that mean that I have to pass unused arguments to all my methods to be able to use it ?

  • 4
    A tip not directly related to your answer: Most of this code is not necessary to support your question, it only makes the question harder to read. It's also beneficial to you as someone asking a question, to narrow the question into the smallest block of code possible, to make it as sharp as you can – Neo Feb 07 '21 at 08:52
  • 1
    As for your question, the way you call the function in the example is indeed correct (though you could check that by yourself and see it works, why wait for us to answer?). However, if any method accepts different sets of arguments, it might be best to revert to a traditional if-elif-else construct – Neo Feb 07 '21 at 08:55
  • One more tip: try to name your variables distinct from python keywords like `dict`, `list`, etc. – tafaust Feb 07 '21 at 08:59
  • 1
    Sorry, the code as shown is *not* sufficient to figure out what you are asking. What are ``myArgs``? How do you select them, i.e. can you avoid ``if``/``else`` for them or are you just shifting the issue? Most importantly, the code already looks fine – have you actually tried running it? – MisterMiyagi Feb 07 '21 at 09:01
  • 1
    In short, it *seems* like you intended to ask the abundant "how do I unpack arguments from a tuple/dict to a function", but obscure that with some inconsequential class usecase – calling a method is no different from calling anything else. – MisterMiyagi Feb 07 '21 at 09:02
  • Does this answer your question? [Pass a list to a function to act as multiple arguments](https://stackoverflow.com/questions/3480184/pass-a-list-to-a-function-to-act-as-multiple-arguments) – MisterMiyagi Feb 07 '21 at 09:04
  • Does this answer your question? [What does the star operator mean, in a function call?](https://stackoverflow.com/questions/2921847/what-does-the-star-operator-mean-in-a-function-call) – MisterMiyagi Feb 07 '21 at 09:06

1 Answers1

2

I think you are on the right track, should be that easy. If I understand your usecase well, you wouldn't pass any unused args this way.

class Protocol:

    def run(action: str, params: dict):
        dict = {
            "TURN": self.turn_func,
            ...
        }
        dict[action](**params)

And call it like:

protocol = Protocol()
turn_args = {...}
protocol.run("TURN", turn_args)
Agnes Kis
  • 491
  • 3
  • 6