Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
passing an expression
#1
i can code the expression in a string and pass that string to my function with evaluates it with eval() in the context it needs to do (perhaps by raising different exceptions). but i don't really like coding it in a string. is there a better way to do this in Python? the objective is to pass some code (not its value) to a function which may or may not execute it. these would be expressions, not statement, if that matters.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
why not make a module and then import it
Reply
#3
Here is an attempt to do this with a function. In the following code, the function 'expression()' is executed by 'main()' and it uses the variables 'x' and 'y' defined in 'main()'.
import sys
y = 10

class Caller:
    def __init__(self, frame):
        self.frame = frame
    
    def __getattr__(self, attr):
        try:
            return self.frame.f_locals[attr]
        except KeyError:
            return self.frame.f_globals[attr]

def call(func, *args, **kwargs):
    f = sys._getframe(1)
    return func(Caller(f), *args, **kwargs)

    
def spam(u):
    return 5 * u

def expression(caller):
    return caller.x + spam(caller.y)


def main():
    x = 3
    y = 2
    print(call(expression))

if __name__ == '__main__':
    main()
The only thing to do to make it work is to add a first parameter 'caller' in the function's signature and use it to get the variables from the calling namespace. Other parameters can be added to 'expression()' and passed in the 'call()' statement.

The previous code prints 13, but if you comment the line 'y = 2' in 'main()', it prints 53.
Reply
#4
(Feb-17-2021, 02:29 AM)Larz60+ Wrote: why not make a module and then import it

you mean have my code write out the module as sources code?

i'm wanting to avoid having anything in a string. if i use a string, then dynamically evaluating it does it.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#5
It 'has been stated' that eval is bad news

I refer you to: https://nedbatchelder.com/blog/201206/ev...erous.html

There are others who disagree.
Reply
#6
(Feb-16-2021, 10:35 PM)Skaperen Wrote: tlhe objective is to pass some code (not its value) to a function which may or may not execute it

Why don't you just pass a function then? If you were doing this in C, you'd pass a pointer to a function containing the code you wanted to execute right? It's the same idea here - look up higher order functions if you're not familiar with the idea.
Skaperen likes this post
Reply
#7
(Feb-18-2021, 11:23 AM)Larz60+ Wrote: It 'has been stated' that eval is bad news

I refer you to: https://nedbatchelder.com/blog/201206/ev...erous.html

There are others who disagree.

right.

this is one of the reasons i want to avoid passing a string to eval(). fortunately, i am only needing to evaluate expressions in my code. there are no untrusted sources in this.

in a language i once created, it was possible to manipulate compiled code in a way that allowed passing the code to a function which could manipulate it further (pass it to another function) and/or evaluate/execute it perhaps more than once (using local values that can be changed). i'm just looking for a way to do something like this in Python.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#8
(Feb-21-2021, 12:15 AM)Skaperen Wrote: passing the code to a function which could manipulate it further (pass it to another function)

It would help if you gave a concrete example of what you're trying to do, but a couple of thoughts:

1. If all you want to do is pass code around to be executed later, then as I mentioned above, pass that code as a function. Even if you didn't know that passing functions around was possible, you likely know another way: passing objects, right? You could put the code to be executed in a method of a class and pass an instance of that class around and you call the method on it as appropriate. It's basically the same idea as just passing a function, if you think about it, but with more stuff around.

2. It might be worth looking at some literature on design patterns. If you wanted to, say, augment the behaviour of an object, the decorator pattern is one way to do that. If you wanted to allow customisation of the steps in a computation, the template pattern might be appropriate. Basically, what I'm getting at is that there is a whole class of approaches like this that help with designing your system. The book Design Patterns (also known as the Gang of Four book, after the authors) is the classic text, but there are undoubtedly others.
Reply
#9
This will not help you with your project, but makes for an interesting story:

Forth was an extensible interpretative compiler, of 'words'. Code was interpreted, then immediately compiled.
It written by Charles (Chuck) Moore to run his telescope, at the National Radio Astronomy Observatory, starting in 1968. Same year I started writing assembly code 'Easycoder' or Honeywell 1000 series mainframes. Took another decade before I was exposed to Forth.

One of the 'verbs' was named 'build does>', it was the extensible part of the compiler. This allowed you to create new 'words' (add to the compiler) at will, interactively.

It was extremely powerful for instrument control (we built a scanning mono-chronometer using it). The problem is that it required a tight connection between all team members otherwise you could end up with 20 different languages. This could make it difficult at best to bring a system together. However, If you could keep your team tight, you'd end up with an extremely elegant system requiring a very small footprint (ours fit in a 2708 E-prom). It was stack oriented, so required little memory.

One of Our team members had a bumper sticker made up which was a Forth statement, It read "Forth Heart if honk then" which was proper forth syntax, and would expressed 'If you love forth, honk' It was discovered by a radio talk host in Boston, and discussed over the next week on his radio show, trying to ID the meaning. None of us called in to tell what it was all about.

I'm telling you this as I expect it's probably right up your alley, and you'd enjoy.
Skaperen likes this post
Reply
#10
(Feb-21-2021, 07:36 AM)ndc85430 Wrote: It would help if you gave a concrete example of what you're trying to do, but a couple of thoughts:

i don't have concrete examples, yet, because i'm just imagining this, so far. i'm trying to overlay a function with its derivative for a form of plotting. but i am thinking up a way to do it with the maths function in a referenced python function as you suggested.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020