dsl in python example needed like in ruby - python

Am a ruby guy basically, and got into a situation where I need to make a small dsl in py as follows, I know in ruby following is doable, am looking for exactly same in py
from_a_dsl_file = "
take_this 'abc'
and_process_it
and_give_me_the_output
"
class A
def take_this abc
end
def and_process_it
end
def and_give_me_the_output
'desired'
end
end
A.new.instance_eval from_a_dsl_file
# => 'desired'
Any hints, or great to have a working example please
thanks in advance

As I understand it, in Ruby there are some tricky things you can do with function calls that don't require parentheses:
x y
In Ruby, that could be a function call where function x is called with y for the argument.
Well, in Python, we don't have those tricks; if you are calling a function, you need parentheses after the function name. So, I don't think you will have much luck trying to play games with eval() for this.
Better is just to write a parser that parses the language for you and figures out what the language is trying to do. For that, Python has a particularly good library: pyparsing
http://pyparsing.wikispaces.com/
P.S. Just doing a Google search for "Python domain specific language" finds some good links, many in StackOverflow. Here is the best one I found:
Mini-languages in Python
EDIT: Okay, you asked for an example and here you go. This is my first-ever program in PyParsing and it was pretty easy. I didn't even read the documentation; I just worked from the examples in a presentation I found on the web.
Here's the URL of the presentation: http://www.ptmcg.com/geo/python/confs/TxUnconf2008Pyparsing.html
from pyparsing import *
def give_desired_output(s):
return "desired"
TAKE_THIS = Suppress("take_this") + Suppress(Word(printables))
AND_PROC = Suppress("and_process_it")
AND_GIVE = Keyword("and_give_me_the_output")
AND_GIVE.setParseAction(give_desired_output)
LANGUAGE_LINE = TAKE_THIS | AND_PROC | AND_GIVE
LANGUAGE = ZeroOrMore(LANGUAGE_LINE)
def parse_language(text):
lst = LANGUAGE.parseString(text)
assert len(lst) == 1 # trivial language returns a single value
return lst[0]
if __name__ == "__main__":
from_a_dsl_file = \
"""
take_this 'abc'
and_process_it
and_give_me_the_output
"""
print(parse_language(from_a_dsl_file)) # prints the word: desired

Sounds like you might want to look at exec() and/or execfile() (and specifically things like the ability to specify the globals and locals available).
(There's also eval(), but it only allows for a single expression, rather than a series of commands.)

Related

Is there a way to get the function parameters in the callee as the caller put it?

I want to achieve that calling foo(2*3) prints 2*3.
The reason is that I try to create a test framework for querying data files and I want to print the query statement with the assertion result.
I tried to get it work via the inspect module but I could not make it work.
In general, the answer is "no", since the value received by the function is the result of the expression 2*3, not the expression itself. However, in Python almost anything is possible if you really want it ;-)
For simple cases you could achieve this using the inspect module like this:
#!/usr/bin/env python3
import inspect
def foo(x):
context = inspect.stack()[1].code_context[0]
print(context)
def main():
foo(2 * 3)
if __name__ == '__main__':
main()
This will print:
foo(2 * 3)
It would be trivial to get the part 2 * 3 from this string using a regular expression. However, if the function call is not on a single line, or if the line contains multiple statements, this simple trick will not work properly. It might be possible with more advanced coding, but I guess your use case is to simply print the expression in a test report or something like that? If so, this solution might be just good enough.
Because the expression is evaluated before it is passed to the function, it is not possible to print out the un-evaluated expression.
However, there is a possible workaround. You can instead pass the expression as a string and evaluate it inside the function using eval(). As a simple example:
def foo(expr):
print(expr)
return(eval(expr))
Please note however that using eval is considered bad practice.
A better solution is to simply pass a string as well as the expression, such as foo(2*3, "2*3").

Best practice for using parentheses in Python function returns?

I'm learning Python and, so far, I absolutely love it. Everything about it.
I just have one question about a seeming inconsistency in function returns, and I'm interested in learning the logic behind the rule.
If I'm returning a literal or variable in a function return, no parentheses are needed:
def fun_with_functions(a, b):
total = a + b
return total
However, when I'm returning the result of another function call, the function is wrapped around a set of parentheses. To wit:
def lets_have_fun():
return(fun_with_functions(42, 9000))
This is, at least, the way I've been taught, using the A Smarter Way to Learn Python book. I came across this discrepancy and it was given without an explanation. You can see the online exercise here (skip to Exercize 10).
Can someone explain to me why this is necessary? Is it even necessary in the first place? And are there other similar variations in parenthetical syntax that I should be aware of?
Edit: I've rephrased the title of my question to reflect the responses. Returning a result within parentheses is not mandatory, as I originally thought, but it is generally considered best practice, as I have now learned.
It's not necessary. The parentheses are used for several reason, one reason it's for code style:
example = some_really_long_function_name() or another_really_function_name()
so you can use:
example = (some_really_long_function_name()
or
another_really_function_name())
Another use it's like in maths, to force evaluation precede. So you want to ensure the excute between parenthese before. I imagine that the functions return the result of another one, it's just best practice to ensure the execution of the first one but it's no necessary.
I don't think it is mandatory. Tried in both python2 and python3, and a without function defined without parentheses in lets_have_fun() return clause works just fine. So as jack6e says, it's just a preference.
if you
return ("something,) # , is important, the ( ) are optional, thx #roganjosh
you are returning a tuple.
If you are returning
return someFunction(4,9)
or
return (someFunction(4,9))
makes no difference. To test, use:
def f(i,g):
return i * g
def r():
return f(4,6)
def q():
return (f(4,6))
print (type(r()))
print (type(q()))
Output:
<type 'int'>
<type 'int'>

Alternative to exec

I'm currently trying to code a Python (3.4.4) GUI with tkinter which should allow to fit an arbitrary function to some datapoints. To start easy, I'd like to create some input-function and evaluate it. Later, I would like to plot and fit it using curve_fit from scipy.
In order to do so, I would like to create a dynamic (fitting) function from a user-input-string. I found and read about exec, but people say that (1) it is not safe to use and (2) there is always a better alternative (e.g. here and in many other places). So, I was wondering what would be the alternative in this case?
Here is some example code with two nested functions which works but it's not dynamic:
def buttonfit_press():
def f(x):
return x+1
return f
print(buttonfit_press()(4))
And here is some code that gives rise to NameError: name 'f' is not defined before I can even start to use xval:
def buttonfit_press2(xval):
actfitfunc = "f(x)=x+1"
execstr = "def {}:\n return {}\n".format(actfitfunc.split("=")[0], actfitfunc.split("=")[1])
exec(execstr)
return f
print(buttonfit_press2(4))
An alternative approach with types.FunctionType discussed here (10303248) wasn't successful either...
So, my question is: Is there a good alternative I could use for this scenario? Or if not, how can I make the code with exec run?
I hope it's understandable and not too vague. Thanks in advance for your ideas and input.
#Gábor Erdős:
Either I don't understand or I disagree. If I code the same segment in the mainloop, it recognizes f and I can execute the code segment from execstr:
actfitfunc = "f(x)=x+1"
execstr = "def {}:\n return {}\n".format(actfitfunc.split("=")[0], actfitfunc.split("=")[1])
exec(execstr)
print(f(4))
>>> 5
#Łukasz Rogalski:
Printing execstr seems fine to me:
def f(x):
return x+1
Indentation error is unlikely due to my editor, but I double-checked - it's fine.
Introducing my_locals, calling it in exec and printing in afterwards shows:
{'f': <function f at 0x000000000348D8C8>}
However, I still get NameError: name 'f' is not defined.
#user3691475:
Your example is very similar to my first example. But this is not "dynamic" in my understanding, i.e. one can not change the output of the function while the code is running.
#Dunes:
I think this is going in the right direction, thanks. However, I don't understand yet how I can evaluate and use this function in the next step? What I mean is: in order to be able to fit it, I have to extract fitting variables (i.e. a in f(x)=a*x+b) or evaluate the function at various x-values (i.e. print(f(3.14))).
The problem with exec/eval, is that they can execute arbitrary code. So to use exec or eval you need to either carefully parse the code fragment to ensure it doesn't contain malicious code (an incredibly hard task), or be sure that the source of the code can be trusted. If you're making a small program for personal use then that's fine. A big program that's responsible for sensitive data or money, definitely not. It would seem your use case counts as having a trusted source.
If all you want is to create an arbitrary function at runtime, then just use a combination of the lambda expression and eval. eg.
func_str = "lambda x: x + 1" # equates to f(x)=x+1
func = eval(func_str)
assert func(4) == 5
The reason why your attempt isn't working is that locals(), in the context of a function, creates a copy of the local namespace. Mutations to the resulting dictionary do not effect the current local namespace. You would need to do something like:
def g():
src = """
def f(x):
return x + 1
"""
exec_namespace = {} # exec will place the function f in this dictionary
exec(src, exec_namespace)
return exec_namespace['f'] # retrieve f
I'm not sure what exactly are you trying to do, i.e. what functions are allowed, what operations are permitted, etc.
Here is an example of a function generator with one dynamic parameter:
>>> def generator(n):
def f(x):
return x+n
return f
>>> plus_one=generator(1)
>>> print(plus_one(4))
5

Python 3: Can we avoid repeating an instance name when calling several of its methods?

I now (or so I have read) that it is not possible in Python 2.x, and can't find it for Python 3 either, but maybe I don't know how to search for it...
It easier to explain it with a simple Python example:
for i in range(11):
one_turtle.penup()
one_turtle.forward(50)
one_turtle.down()
one_turtle.forward(8)
one_turtle.up()
one_turtle.forward(8)
one_turtle.stamp()
one_turtle.forward(-66)
one_turtle.left(360/12)
I'd like to avoid repeating "one_turtle" the same way you can do in VBA, which it would result in something similar to this:
For i = 1 To 11
With one_turtle.penup()
.forward(50)
.down()
.forward(8)
.up()
.forward(8)
.stamp()
.forward(-66)
.left(360/12)
The code resulting from the With keyword is much clearer and easy to write and read (it'll need an End With and a Next lines but I wanted to focus the discussion). One of the main reasons I have decided to learn Python is because it is said to be very neat and "zen-like" to program. Is it really not possible to do this?
In your definition of all these member-methods, simply return self.
eg. Change definition of penup() like this:
def penup(self):
# Your logic
return self
The ideal solution is I think already posted, returning self is simply the cleanest way. However if you're not able to edit the turtle object or whatever, you can create an alias:
forward = one_turtle.forward
... some code ...
forward()
Now the function forward just applies forward to one_turtle, simple example
s = "abc"
x = s.upper
print(x()) # prints "ABC"

call function with raw_input list

I am trying to directly input raw_input using the least amount of lines possible(without extra variables and whatever) and call the function with it. The problem is, I need a list. I am quite aware of the split function, however
histogram(split.raw_input("List, sire: "))
throws naming errors. I didn't think it would work, but I thought I'd try anyway. I'm sure the python gods know how, I've seen pretty ridiculous "pythonic" stuff or whatever it is you call it, but unfortunately I'm not that advanced yet.
Edit: I suppose I should add the rest of my code, but it is most likely entirely irrelevant.
#!/usr/bin/python
def histogram(x):
for i in x:
print int(i) * "*"
Referrals to advanced/long reading is appreciated, I'd like to try to soak in as much as I can.
Thanks, got it working.
Without using any modules, this is how it's done:
#!/usr/bin/python
def string_len(x):
for i in x:
print int(i) * "*"
string_len(raw_input("String here").split())
Or, completely replace any occurrence of string_len with histogram.

Categories