Reputation: 474
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
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:
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
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