I'm working on a project where I am making a command line to learn how to use curses in Python. I am starting to work on the interpreter for the commands, but have a situation I want to see if there is a better solution.
I want to split the string input into a command and arguments. Here's an example of how I could do it:
def processor(inputText):
command, arguments=inputText.split(' ')[0], inputText.split(' ')[1:]
I could do it this way, but because I'm picky/weird I don't like having inputText.split(' ') twice. Here's another option I could choose to shorten it:
def processor(inputText):
inputTextSplit=inputText.split(' ')
command, arguments=inputTextSplit[0], inputTextSplit[1:]
Since we're shortening code, inputTextSplit is longer so replacing it with i could be 'better':
def processor(inputText):
i=inputText.split(' ')
command, arguments=i[0], i[1:]
My issue with this though, is using shorter variables like i could cause overwriting other variables later (like using i in a for loop like for i in array:). This would make code look cleaner, but at the same time could cause issues if not careful.
Is there a way to take sections of splits of an array to variables? For example, in TI-Basic you can pass a list as an argument for an operation. To get multiple outputs of a graph function in TI-Basic would look like:
"If Y₁ is 2x, then the results would be as follows:"
Y₁({1, 3})
"{2, 6}"
{Y₁(1), Y₁(3)}
"{2, 6}"
Is there a similar way to do something hypothetical like this:
def processor(inputText):
command, arguments=inputText.split(' ')[[0,1:]]
Is there some advanced Python technique that can accomplish this, or is just an lazy idea? The expected result for an input like 'command arg1 arg2' would be ['command', ['arg1', 'arg2']].
This concept isn't something I want to limit to my project example, either. Another example could be array[[0,1:6,7:8,9:]] which would give another array with 4 values, parts of the original.
Also, I am on Python 2.7. Thanks in advance for your advice.
You can simply do:
def processor(inputText):
command, *arguments = inputText.split(' ')
return command, arguments
print(processor('command arg1 arg2 arg3'))
# ('command', ['arg1', 'arg2', 'arg3'])
Using *arguments will assign all remaining parts of the list generated by split, after the first one has been assigned to command, to the arguments list.
You can have a look at PEP 3132 -- Extended Iterable Unpacking for details on this syntax.
Related
I am just a beginner in coding, trying to self teach python, then I got a lot of questions in my mind. so consider I have a main.py with a function def catch_urls(**kwargs): I will pass key:value arguments while running the file. My requirement here is there will be a bunch of arguments I pass to the function of which I need to find out the count of pattern matching keys- that means
main.py type=internal url1=google.com url2=yahoo.com timeout=10s url3=stackoverflow.com
Q1. How to get the count of how many url1, url2, url3, .... is given in arguments ? these url* count will vary on each runs then how to get the count of this pattern keys ? can we do something like psuedo code like count(url*)
Q2. Using **kwargs can I actually get these arguments passed into execution ? or do I need to use some library called "click" or so to get these arguments passed into my function ?
The arguments arrive as strings in sys.argv. So, given your example, sys.argv would be a list containing:
[
"main.py",
"type=internal",
"url1=google.com",
"url2=yahoo.com",
"timeout=10s",
"url3=stackoverflow,.com"
]
You can parse those yourself, or you can use the argparse module to parse them.
It's not usually productive to spent a lot of time optimizing code that only gets used once. You could certainly say:
cnt = sum(i.startswith("url") for i in sys.argv)
**kwargs is used for functions within a program. It's not involved in command line arguments.
I'm working on a program for my school's programming outreach club, What I'm trying to do is have the user type in a string and the program searches the string. For example, they would type something like
moveInstant(4, 8)
and it would execute function
def moveInstant(targetX, targetY)
pyautogui.moveTo(targetX, targetY)
Make sense? basically taking a long string and converting each instance of pseudo code into a predefined function with arguments. The idea is that a user could input a full txt file and it could be executed by the program.
I am curious to know what the pseudo code will look like or how you are going to implement the 'string matching'. But:
Once you got the right function names and parameters, you can just use the exec statement to execute it. If not only the side effect but the return value of a function is what you want, use eval (Differences). Or,
Do some clean-up job for the text file and execute it using the execfile function.
Noted that statements like eval or exec are potentially harmful, and that's why your 'string matching' for untrusted inputs is important.
What you're looking for is the eval() method.
Python Docs
Example:
>>> def test(x):
... print(x)
>>> test(3)
>>> 3
>>> y = "test(124)"
>>> eval(y)
>>> 124
In a current project, I found myself often writing code like so:
statement_x()
do_something()
do_other_thing()
statement_y()
# ...
statement_x()
do_third_thing()
do_fourth_thing()
statement_y()
As you can see, statement_x and statement_y often get repeated, and they are always paired, but I am unable to condense them into a single statement. What I would really like is a language construct like this:
def env wrapping:
statement_x()
run_code
statement_y()
In this case, I'm pretending env is a Python keyword indicating a special "sandwich function" that runs certain statements before and after a given block, the point of entry of the block being indicated by the second keyword run_code.
My above program can now be made more readable using this construct:
env wrapping:
do_something()
do_other_thing()
env wrapping:
do_third_thing()
do_fourth_thing()
Which I mean to have the exact same behavior.
As far as I know such a construct does not exist, and the point of my question is not to speculate on future Python features. However, surely this situation of "run some common code before and after a variable block" must occur often enough that Python has a convenient way of dealing with it! What is this way? Or is the Pythonic solution to simple give up and accept the repetition?
PS: I realize that I could write a function that takes the variable statements as an argument, but that would not be very user-friendly - I would end up writing huge lists of statements inside the parens of my function.
You can use a with statement.
Example using contextlib.contextmanager:
import contextlib
#contextlib.contextmanager
def doing_xy():
print('statement_x')
yield
print('statement_y')
Example usage:
>>> with doing_xy():
... print('do_something')
... print('do_other_thing')
...
statement_x
do_something
do_other_thing
statement_y
>>> with doing_xy():
... print('do_third_thing')
... print('do_fourth_thing')
...
statement_x
do_third_thing
do_fourth_thing
statement_y
I'm currently working on an experiment where I'm implementing an interpreter for an old in-game scripting language. It's a forth based language, so I figure it would be fairly easy to just have the instructions (once verified and santized) put into a big list.
Once I've got the code in a list, I am trying to iterate through the entire program in a for loop that processes the instructions one at a time. Certain items, like strings, could be placed onto a variable that holds the current stack, which is easy enough. But where I'm stuck is making commands happen.
I have a big list of functions that are valid and I'd like it to where if any instruction matches them, it calls the associated function.
So, for example, if I had:
"Hello, world!" notify
...the code would check for notify in a list and then execute the notify function. The bottom line is: How do I translate a string into a function name?
You could keep a dictionary of functions the code can call, and then do a look up when you need to:
def notify(s):
print(s)
d = {"notify": notify}
d["notify"]("Hello, world!")
You can do it through locals which is a dictionary with th current local symbol table:
locals()["notify"]()
or though globals which returns a dictionary with the symbol table of globals:
globals()["notify"]()
You can give arguments too e.g.:
locals()["notify"]("Hello, world!")
or
globals()["notify"]("Hello, world!")
If you have a dict called commands that maps names to functions, you can do it like this:
def my_notify_function():
print(stack.pop)
commands = {'notify': my_notify_function, ...}
for item in program:
if item in commands:
commands[item]()
else:
stack.push(item)
Something like:
import re
class LangLib(object):
pattern = re.compile(r'"(.*?)" (.*)')
def run_line(self, line):
arg, command = re.match(LangLib.pattern, line).groups()
return getattr(self, command)(arg)
def notify(self, arg):
print arg
Then your engine code would be:
parser = LangLib()
for line in program_lines:
parser.run_line(line)
Create a dictionary of function names and some tags.
I have tried it several times before, it works really well.
I am attempting to store a list of commands to send down a serial cable using deque in Python.
My function "send_command" accepts 3 values; The command, an int. pause and a boolean wait. its definition is as follows.
def send_command(self, command, pause=0, wait=False):
What I would like to do is, rather than calling this function like so:
send_command("A234", 5, True)
... or...
send_command("B4242")
I'd like to be able to store up commands inside a deque list and use the popleft function to then call my function. This would allow me to do things such as:
CommandList = deque((['A234', 5, True], ['B4242']))
...and use the deque.append() as a way to keep adding things to the list, which would then in turn be sent to my send_command function. I could then drop in and out of the list new commands when they are needed (or as quickly as the serial part of my code can do).
The part I'm struggling with is actually using the CommandList.popleft, or any part of the deque list as the args for my send_command function. It doesn't seem as straight forward as:
send_command(CommandList.popleft)
I'm sure it's something simple, but I cannot figure it out.
Can anyone help?
Thank-you kindly.
Andy
probably you need something like:
obj.send_command(*CommandList.popleft())
That is, call popleft and use the result as an argument list for send_command. self argument suggests this is a member function, so you need to call it on an object
Another way, as I wrote in the comment, is to store prepared functions with something like this:
def make_command(obj, *args, **kwargs):
def f():
obj.send_command(*args, **kwargs)
return f
Then you can do
queue.append(make_command(obj, 'ABC', whatever='else'))
and then execute:
command = queue.popleft()
command()
unbeli is right - you need the () to call the function, and you need * to unpack the arguments. However, there's no need for using deque when you can just do this:
commandlist = [['A234', 5, True], ['B4242'], ['A234', 0]]
for command in commandlist:
send_command(*command)
and that will work perfectly fine. For more info, see unpacking argument lists.
Queues are really only necessary if you're doing something in which you want to consume the values - say you want your commandlist to be empty when you're done. Of course you could also do the same thing with a list:
q = [1,2,3,4]
while q:
print q.pop(0)
print q
HTH
Have you tried:
send_command(CommandList.popleft()) # note the ()