Home > OS >  How to modify a key value from a user inputs request
How to modify a key value from a user inputs request

Time:01-04

I am making a basic app where I let the user add, delete and edit the stock they have. I am trying to make it so I can let the user either 'add' or 'remove' which they decide and type it and the input captures their response. I don't to use a load of if user_input = 'add' do this and then elif user_input == 'remove' do that. What would be the best way to go around this.

Here is my code for the edit inventory part;

    def edit_inventory(self):
        item_name = input('Enter item name: ')

        try:
            user_input = input('Type \'ADD\' or \'REMOVE\' to change quantity: ').lower()
            if user_input not in ['add', 'remove']:
                raise ValueError
            quantity = int(input(f'Enter how many you wish to {user_input}: '))
            if user_input == 'add':
                for item_name in self.stock.keys():
                    self.stock[item_name]  = quantity
            elif user_input == 'remove':
                for item_name in self.stock.keys():
                    self.stock[item_name] -= quantity

        except KeyError:
            print('Item not in stock. Check current stock for current inventory.')
        except ValueError:
            print('Invalid response.')

I want to work around the if and elif to make it more efficient.

CodePudding user response:

One approach is to use a dispatch table, like this:

    def add_item(self, item: str, qty: int) -> None:
        self.stock[item]  = qty

    def remove_item(self, item: str, qty: int) -> None:
        self.stock[item] -= qty

    def edit_inventory(self) -> None:
        cmd_table = {
            'add': self.add_item,
            'remove': self.remove_item,
        }
        item = input('Enter item name: ')
        cmd = input("Type 'ADD' or 'REMOVE' to change quantity: ").lower()
        qty = int(input(f'Enter how many you wish to {cmd}: '))

        def invalid_cmd(_item: str, _qty: int) -> None:
            print("Invalid response.")
        try:
            cmd_table.get(cmd, default=invalid_cmd)(item, qty)
        except KeyError:
            print(
                'Item not in stock.',
                'Check current stock for current inventory.'
            )

This way if you have a large number of commands, you just need one entry in the dictionary per command, rather than a bunch of if/elif. You also get reasonable behavior around invalid entries for free; you can use [] and get a KeyError, or you can use .get() and supply a default function, or you can test if cmd in cmd_table.

If you're very specifically only modifying the quantity of an item, you could also put int operations in your table and use those rather than defining methods:

    def edit_inventory(self) -> None:
        cmd_table = {
            'add': int.__add__,
            'remove': int.__sub__,
        }
        item = input('Enter item name: ')
        cmd = input("Type 'ADD' or 'REMOVE' to change quantity: ").lower()
        qty = int(input(f'Enter how many you wish to {cmd}: '))

        def invalid_cmd(_curr: int, _qty: int) -> None:
            print("Invalid response.")
        try:
            cmd_func = cmd_table.get(cmd, default=invalid_cmd)
            self.stock[item] = cmd_func(self.stock[item], qty)
        except KeyError:
            print(
                'Item not in stock.',
                'Check current stock for current inventory.'
            )

CodePudding user response:

If was making the same idea as samwise, but in a class aproach. so, i will post it anyway

def do_this():
    print("this")


def do_that():
    print("that")

class Command1(dict):
    def __call__(self, command: str):
        self[command]()

command = input("your command: ")
executor = Command1()
executor["add"] = do_this
executor(command)

class Command2:
    my_commands = {"add": do_this, "remove": do_that}
    def __call__(self, command: str):
        self.my_commands[command]()

command = input("your command: ")
executor = Command2()
executor(command)

The benefit of this is, when your data is in a class you can just add the __call__ method and just extend the interface.

  •  Tags:  
  • Related