Legion
Legion

Reputation: 474

How to get class method to update dictionary?

I'm trying to make a flexible argument parser which takes strings, finds arguments within them and creates a dictionary like this:

message = "--mass=12"
physics = comparse(message, "mass", "int", 10, "this is your mass attribute")

Produces: {'mass': 12}

I'm unable to update and add more arguments/keys (like if I wanted to add a 'vel' variable) to the dictionary. Unfortunately, I'm new to Python classes and although the parser detects the first argument, I'm unable to add to the dictionary. Here's my program:

import shlex
class comparse(object):
    def __init__(self, message, attribute, var_type, default, help_txt):
        self.data = {}   #This is the "data" dictionary that this function will ultimately return.
        self.message = message
        self.attribute = attribute
        self.var_type = var_type
        self.default = default
        self.help_txt = help_txt

        #Remove unwanted symbols (e.g. "=", ":", etc.)
        self.message = self.message.replace("=", " ")
        self.message = self.message.replace(":", " ")
        self.args = shlex.split(self.message)

    def parse(self):  
        try:
            options = {k.strip('-'): True if v.startswith('-') else v
                for k,v in zip(self.args, self.args[1:]+["--"]) if k.startswith('-') or k.startswith('')}
            if (self.var_type == "int"):
                self.data[self.attribute] = int(options[self.attribute])   #Updates if "attribute" exists, else adds "attribute".
            if (self.var_type == "str"):
                self.data[self.attribute] = str(options[self.attribute])   #Updates if "attribute" exists, else adds "attribute".  
        except:
            if self.attribute not in self.message:
                if (self.var_type == "int"):
                    self.data[self.attribute] = int(self.default)   #Updates if "x" exists, else adds "x".
                if (self.var_type == "str"):
                    self.data[self.attribute] = str(self.default)   #Updates if "x" exists, else adds "x".
        return self.data

    def add_argument(self):
        self.data.update(self.data)

message = "-mass: 12 --vel= 18"

physics = comparse(message, "mass", "int", 10, "this is your mass attribute")
comparse.add_argument(message, "vel", "int", 10, "this is your velocity attribute")
print (physics.parse())

The comparse.add_argument method doesn't work. There's obviously something I'm doing wrong and classes generally confuse me! Could someone point out what's wrong with my program?

Upvotes: 0

Views: 667

Answers (2)

Harshita
Harshita

Reputation: 488

I'm a little confused about how your class is designed. I've answered the question in a more holistic way, with suggestions about how you should maybe redesign your class to achieve your goal better.

Typically, when you initialize a class (your parser) you pass it all the data that it needs to do its work. It seems, however, like your goal is to create a generic physics parser physics = comparse() then add possible arguments like mass and velocity to the physics parser's data. You then give the physics parser a message string like message = "-mass: 12 --vel= 18" for which it should parse and extract the arguments. This would suggest that the end of your code snippet, which is currently

message = "-mass: 12 --vel= 18"

physics = comparse(message, "mass", "int", 10, "this is your mass attribute")
comparse.add_argument(message, "vel", "int", 10, "this is your velocity attribute")
print (physics.parse())

should look like so:

message = "-mass: 12 --vel= 18"

# create a parser
physics = comparse()
# tell the parser what arguments it should accept
comparse.add_argument("vel", "int", 10, "this is your velocity attribute")
comparse.add_argument("mass", "int", 10, "this is your mass attribute")    
# give the parser a specific message for which it should extract arguments
print (physics.parse(message))

This code snippet would create a parser, tell the parser what sorts of arguments it should accept (like velocity and mass), and then extract those arguments from a specific string message.

This design adheres better to object oriented programming principles. The benefits here are that you're creating a physics parser that can be reused, and then asking it to parse strings which it does not save in its own properties (no this.message). This way, you can make additional calls like `physics.parse("--mass: 40 --vel=15") and reuse the physics parser.

If this design fits your intention more accurately, I would modify the code in the following ways to adhere to it:

  • modify your init function so that it takes no parameters.
  • Since you have multiple arguments that you are storing within your class, instead of having self.attribute, self.var_type, self.default, self.help_txt be just single variables, I would make them arrays that you can add the attribute names, variable types, defaults, and help texts to for EACH argument. Initialize each of these as empty arrays in init like so: self.defaults = []. I would also change the name of each to indicate that they're arraysand not individual variables, so defaults, types, texts etc.
  • Modify add_argument to be the following:

    def add_argument(self. attribute, var_type, default, help_txt):
    self.attributes.append(attribute)
    self.var_types.append(var_type)
    self.defaults.append(default)
    self.help_txts.append(default)

  • Modify parser to take message as a parameter, remove its unwanted symbols, perform the split, and then execute its logic for each of the arguments you set up in add_argument.

Please comment if you have any questions, good luck!

Upvotes: 1

rawwar
rawwar

Reputation: 4992

in the following code from what you gave

def add_argument(self):
        self.data.update(self.data)

the add_argument does not take any arguments.But, you have done the fllowing

comparse.add_argument(message, "vel", "int", 10, "this is your velocity attribute")

where you have given multiple arguments. this is the cause of the problem

To fix it, try modifying the add_argument function to accept the parameter's you want it to handle

EDIT: based on your comment, the function should have been

def add_argument(self,message, attribute, var_type, default, help_txt):
    data = comparse.parse(message, attribute, var_type, default, help_txt) 
    self.data.update(data) 

But, here again, parse method is actually taking no arguments in your code, so..modify it to accept all the arguments you need along with self

Upvotes: 0

Related Questions