1
\$\begingroup\$

I made a program that can modify a list using commands that the user enters.

The commands that are supported are (used from actual program):

  • /add [value1] [value2] [valueN]... - Add a value to the list
  • /rvalue [value] - Removes a value from the list
  • /rindex [index] - Removes the value at the specified index from the list
  • /print - Prints the list
  • /help - Lists every available command

Here is the code:

#Program to modify lists

value_list = []

def cmd_help():
    print("/add [value1] [value2] [valueN]... - Add a value to the list")
    print("/rvalue [value] - Removes a value from the list")
    print("/rindex [index] - Removes the value at the specified index from the list")
    print("/print - Prints the list")
    print("/help - Lists every available command")

def get_command_params():
    commands = {
        "/add": lambda *value : value_list.extend(list(value)),
        "/rvalue": lambda value : value_list.remove(value),
        "/rindex": lambda value : value_list.pop(int(value)),
        "/print": lambda : print(value_list),
        "/help": cmd_help
    }

    while True:
        input_cmd = input("Enter a command: ")

        #Separate arguments
        command = ""
        current_args_index = -1
        args = []
        last_char = ""

        for char in input_cmd:
            #Update separator
            if char == "/" or char == " ":
                last_char = char

            if last_char == "/":
                command += char
            elif last_char == "append":
                args[current_args_index] += char
            elif last_char == " ":
                args.append("")
                #To append individual characters to same index
                last_char = "append"
                ++current_args_index

        cmd = commands.get(command)
        if cmd == None:
            print("Invalid command!")
            continue

        return cmd, args

def main():
    cmd_help()

    #Wait for command
    while True:
        command, args = get_command_params()

        #Execute command with arguments
        try:
            command(*args)

            #Don't print success if command is print/help
            if args != []:
                print("Success!")
        except IndexError:
            print("Index out of range!")
        except ValueError:
            print("Element not found!")
        except TypeError:
            print("Invalid arguments! Type /help for help")

if __name__ == "__main__":
    main()
\$\endgroup\$
2
\$\begingroup\$
value_list = []

Global variables are almost never necessary. If you are tempted to use a global, you have two choices:

  1. Give the variable as an argument and reassign it to what the function returns (or just give it if the function mutates it).
  2. Define a class and use instance attributes.

In this case, value_list is used by far too many things and with lambda functions and everything. Therefore, I would suggest that you define a Commands class.

"/add": lambda *value : value_list.extend(list(value))

You don't need to convert value to a list. That is just unnecessary processing time. A list can be extended by a list, a tuple, a string, a generator, ... whatever iterable you want.

"/rindex": lambda value : value_list.pop(int(value)),

I wouldn't convert it to an integer within a lambda function. I would create a whole function that uses a try block in case the user doesn't type a valid number. That is also helpful if the user does type a number, but types a number that is too big or too small.

elif last_char == "append"
...
    last_char = "append"

Don't use magic numbers (or magic values). You should define a constant called APPEND that can really be assigned to any object except a single-character string.

++current_args_index

Python doesn't use ++. If x is 4, then +x is 4 and ++x is still 4. If x is -4, then +x is -4 and ++x is still -4. In other words, it does absolutely nothing. Python isn't like C where that increments current_args_index. If you want to increment it, do current_args_index += 1

cmd = ...
if cmd == None:
    ...

I have two problems. First, if you treat None as a special case, you can simply use a try block. Second, you should say is None, not == None because a class could define its __eq__ method to say that any instance is equal to None, but only None really is None.

Your main() function and how you use it looks terrific! You take care of each error separately, and you don't call main() unless your file is being run as a program. Keep it up!

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.