-1

So, I want a simple little application where a user can input a command and its arguments, and then Python will translate that into a defined function and its arguments. For example:

define foo(x,y)
    bar = x ** y
    print bar

Then, in a command-line interface, if the user inputs foo 2 3, I want the program to recognise that and print the result, 8.

Also of note is that it should be able to detect integer arguments, string arguments, and float arguments, without the user hav9ng to specify. As in, if they input foo red 1 2.2, it can recognise all of red, 1, and 2.2 as a string arg, an integer arg, and a float arg of foo, repsectively.

Research returns the sys.argv command, but I can't wrap my head around it.

Basically, I'm trying to develop a language within a language. Help?

JessLovely
  • 142
  • 1
  • 12
  • 1
    Your path leads through dangerous roads and `eval`. Turn back while you still can:P – Andras Deak -- Слава Україні Oct 14 '16 at 23:01
  • 1
    @AndrasDeak Not exactly, see [here](http://stackoverflow.com/q/7936572/5647260) – Andrew Li Oct 14 '16 at 23:03
  • Hmm, you might spare an eval using a dispatch dict: `fundict = {'foo': foo}`, then you just have to parse the input and call `fundict[funname](*args)` – Andras Deak -- Слава Україні Oct 14 '16 at 23:03
  • @AndrewL. thanks, although I'd consider `globals`/`locals` to be dangerous themselves;) But great point, haven't seen that yet, thanks. – Andras Deak -- Слава Україні Oct 14 '16 at 23:04
  • 1
    @AndrasDeak Indeed: *I believe using dictionary is a bit more clean that relying on `globals().copy()` in accepted answer.* – Andrew Li Oct 14 '16 at 23:05
  • Oh no... I'm... rather inexperienced with python. I'm familiar with simple things like `raw_input` and libraries, but then people start bringing up `fundict`s and `eval` and I'm getting utterly lost. – JessLovely Oct 14 '16 at 23:06
  • 1
    Rule of thumb: if you see `eval`, run. But `fundict` is just the name of a variable I just defined: it's a `dict` that has a string as a key and a function as a value. It allows you to translate a string of `'foo'` to an actual method `foo`. My complete idea was this: `'foo 2 3'` -> parse to `['foo', [2,3]]` --> `funname = 'foo'; args = [2,3];` --> call `fundict[funname](*args)` will be equivalent to `foo(2,3)`. – Andras Deak -- Слава Україні Oct 14 '16 at 23:07
  • 1
    Ahh, I see. Now, to find out how to set up the command line interface and make it work without python support (like a shell or something). And, on that note, when I hear `eval` from now on, I'm using pocket sand. – JessLovely Oct 14 '16 at 23:09
  • 1
    Have a look at PyParsing. You can develop a safe language with it. – dawg Oct 14 '16 at 23:10
  • I'd say the comments here have helped me put together my own answer; to quickly close this duplicate question, I'll say the suggested duplicate was, indeed, a duplicate. Thanks for the help! – JessLovely Oct 14 '16 at 23:25

2 Answers2

0

The usual way to do the function part is to use a lookup table:

def double(a):
    return a * 2

def halve(b):
    return b / 2

functions = {
    'double': double,
    'halve': halve,
    ...
}

Then assuming you have the user input function name in f:

if f in functions:
    func_to_call = functions[f]
else:
    print 'unknown function %s' % f

To determine if the arg is a float, int, or string, use a series of try/excepts:

try:
    float_value = float(user_input)
except ValueError:
    # nope, it wasn't a float...
    float_value = None

try:
    int_value = int(user_input)
except ValueError:
    # nope, it wasn't an int...
    int_value = None

if float_value is None and int_value is None:
    # must be a string... 
John Gordon
  • 29,573
  • 7
  • 33
  • 58
0

There is few ways to access functions by string name.

I recomend this way. File commands.py - module for commands:

def foo(x,y)
    bar = x ** y
    print bar

def fuu(x,y)
    bar = x << y
    print bar

File main.py - start here:

import commands
def nocmd(*a):
    print('where is no such command')

cmd,a,b = input('>>').split()
a,b = float(a),float(b) #in this moment need to check user input
getattr(commands,cmd,nocmd)(a,b)

Run python3 main.py

Also objects can be retrived by name with locals()[name] or globals()[name]

eri
  • 3,133
  • 1
  • 23
  • 35