I'd like to build a class that is able to take a few user defined expressions at runtime and to calculations based on them and a few predefined variables that the class owns, e.g. the user will know that the variables a,b,c & d exist:
pseudo code:
>>> foo = myclass()
>>> foo.a = 2
>>> foo.b = 3
>>> foo.expression = 'a + b'
>>> foo.run_expression()
5
>>> foo.expression = 'a * b'
>>> foo.run_expression()
10
I've explored lambda functions but they seems to need me to explicitly define what the inputs are for the lambda function every time I create a new one which would mean a lot of boiler plate input from the user ever time they wanted to update the lambda as I know that the inputs would always be a predefined set of variables.
does anybody have experience doing anything similar, or have any thoughts on how to structure a program like this?
To evaluate expressions as Python, use the eval() function, passing in vars(self) as the namespace:
def run_expression(self):
return eval(self.expression, vars(self))
Do know this opens you up to attack vectors, where malicious users can execute arbitrary code and change your program to do completely different things.
Demo:
>>> class Foo(object):
... def run_expression(self):
... return eval(self.expression, vars(self))
...
>>> f = Foo()
>>> f.a = 2
>>> f.b = 3
>>> f.expression = 'a + b'
>>> f.run_expression()
5
Related
How can I assign the results of a function call to multiple variables when the results are stored by name (not index-able), in python.
For example (tested in Python 3),
import random
# foo, as defined somewhere else where we can't or don't want to change it
def foo():
t = random.randint(1,100)
# put in a dummy class instead of just "return t,t+1"
# because otherwise we could subscript or just A,B = foo()
class Cat(object):
x = t
y = t + 1
return Cat()
# METHOD 1
# clearly wrong; A should be 1 more than B; they point to fields of different objects
A,B = foo().x, foo().y
print(A,B)
# METHOD 2
# correct, but requires two lines and an implicit variable
t = foo()
A,B = t.x, t.y
del t # don't really want t lying around
print(A,B)
# METHOD 3
# correct and one line, but an obfuscated mess
A,B = [ (t.x,t.y) for t in (foo(),) ][0]
print(A,B)
print(t) # this will raise an exception, but unless you know your python cold it might not be obvious before running
# METHOD 4
# Conforms to the suggestions in the links below without modifying the initial function foo or class Cat.
# But while all subsequent calls are pretty, but we have to use an otherwise meaningless shell function
def get_foo():
t = foo()
return t.x, t.y
A,B = get_foo()
What we don't want to do
If the results were indexable ( Cat extended tuple/list, we had used a namedtuple, etc.), we could simply write A,B = foo() as indicated in the comment above the Cat class. That's what's recommended here , for example.
Let's assume we have a good reason not to allow that. Maybe we like the clarity of assigning from the variable names (if they're more meaningful than x and y) or maybe the object is not primarily a container. Maybe the fields are properties, so access actually involves a method call. We don't have to assume any of those to answer this question though; the Cat class can be taken at face value.
This question already deals with how to design functions/classes the best way possible; if the function's expected return value are already well defined and does not involve tuple-like access, what is the best way to accept multiple values when returning?
I would strongly recommend either using multiple statements, or just keeping the result object without unpacking its attributes. That said, you can use operator.attrgetter for this:
from operator import attrgetter
a, b, c = attrgetter('a', 'b', 'c')(foo())
I have been studying Python for three months and now I have a question that I could not solve by using google, but luckily I am able to simplify it here:
I have a var_class module:
#var_class.py
class A(object):
def __init__(self, x):
self.x = x+2
zz = A(10)
class B():
b = 0
def __init__(self):
pass
def update(self):
B.b = zz.x
and in main program I have:
#main.py
from var_class import *
b_class = B()
b_class.b # I get 0 as expected
zz = A(100)
b_class.update()
b_class.b # Instead of 102, I get 12 unexpectedly
You see my goal is to change "zz" frequently for every data input and then update a class variable 'b', and the reason I wrote zz = A(10) in var_class.py is that otherwise when I import it, module 'var_class' is missing 'zz' in 'class B', it would give error "global name zz is not defined".
However, as I write it like this now, looks like the value '10' is stuck to the class, and I am not able to change it in the main program. Don't know how to overcome this.
Thanks in advance for any help.
Answer:
alKid wrote the whole answer first, have to thanks to alexvassel and Mr. C too, would like to know if there is way to thanks them, others helped me with the knowledge, also appreciate a lot.
Easy understanding:
You can't do that, you're inside var_class module, so zz is A(10).
How about passing zz as a parameter? Like this!
class A(object):
def __init__(self, x):
self.x = x+2
zz = A(10)
class B():
b = 0
def __init__(self):
pass
def update(self, zz):
B.b = zz.x
Hope this helps!
When you do B.b = zz.x (update method) you are inside the module var_class, so zz is A(10)
python runtime finds variables by namespace. Namespace is something like scope. When B.b = zz.x executes, the runtime first searches the local namespace(the function namespace -- update), it sees no zz. Then, it goes to the module space(var_class), well we get the variable and stop searching.
The python namespace search order:
1. local namespace, the function scope
2. global namespace, the module scope
3. built-in namespace
Better not use global variables around.
your code may like this:
class B():
b = 0
def __init__(self):
pass
def update(self, zz):
B.b = zz.x
That is a matter of scope! you are using zz = A(100) in your main.py. But when you call b_class.update(), b_class has to get "some2 variable called "zz" - and the one which is available is the one you defined in your class.py - and this one still has the value A(10)!!!
To work around this, you have different options.
The dirty hack (but closest to your solution) would be to define a global variable and use ist (google "python globals" for more info on this approach).
I would suggest passing A (or A.x) to your "update" method b_class.update(A.x). This avoids globals and is more readable. Of course, you'll have to adjust B.update for the new parameter.
when you import a variable from a module, you get a copy of the variable, not the original. you need to write to the original directly.
from a.b import c
from a.b.c import var
a.b.c.var = 1
var = 2
a.b.c.var
1
var
2
Edit: So, more correctly, in python, there are objects in memory, and then there are names for the objects. When you import a module, you create two separate names, but they both point to the same object - i.e. they have a reference to the same object. It's very similar to the below code, which doesn't require any imports at all:
>>> a = 4
>>> b = a
>>> b
4
>>> a
4
>>> b = 'something different'
>>> b
'something different'
>>> a
4
Why did changing b not also change a? The sequence is like this: First, we create an object (the 4) and point the name 'a' at it. Then, we create a name 'b', and we point it at the same object. So, now looking up those names returns the same object. Now, we then go back and point the name 'b' at a different object, a string. The object 'a' is pointing to still exists, and has not changed.
New users more often trip up on this the other way, with objects like lists:
>>> a = [1,2,3,4,5]
>>> b = a
>>> b
[1,2,3,4,5]
>>> a
[1,2,3,4,5]
>>> b.append(6)
>>> b
[1,2,3,4,5,6]
>>> a
[1,2,3,4,5,6]
>>> b = b[1:3]
>>> b
[2,3]
>>> a
[1,2,3,4,5,6]
What's going on here? Well, first we create a list object, and then point the name 'a' at it. Then we create the name 'b' and point it to the same object. So, 'a' and 'b' both point to the same list. Then, we use the reference b to get the object and modify it. Note that we haven't changed what 'b' points to in this case - we grabbed the reference, and then modified the object it points to directly. So, in this case, both 'a' and 'b' will see the change - they both point to the modified object. Then, we extract a slice, and assign it to 'b'. Now, this actually creates a new object, and points 'b' at it - 'b' is no longer pointing to the original object. So now 'a' and 'b' point to different objects, and now updates to one are no longer reflected in the other.
The import case is just a special case of this.
maybe you can do this
class B():
b = 0
def __init__(self):
pass
def update(self,value):
self.b =self.b+value
I have code which contains the following two lines in it:-
instanceMethod = new.instancemethod(testFunc, None, TestCase)
setattr(TestCase, testName, instanceMethod)
How could it be re-written without using the "new" module? Im sure new style classes provide some kind of workaround for this, but I am not sure how.
There is a discussion that suggests that in python 3, this is not required. The same works in Python 2.6
http://mail.python.org/pipermail/python-list/2009-April/531898.html
See:
>>> class C: pass
...
>>> c=C()
>>> def f(self): pass
...
>>> c.f = f.__get__(c, C)
>>> c.f
<bound method C.f of <__main__.C instance at 0x10042efc8>>
>>> c.f
<unbound method C.f>
>>>
Reiterating the question for every one's benefit, including mine.
Is there a replacement in Python3 for new.instancemethod? That is, given an arbitrary instance (not its class) how can I add a new appropriately defined function as a method to it?
So following should suffice:
TestCase.testFunc = testFunc.__get__(None, TestCase)
You can replace "new.instancemethod" by "types.MethodType":
from types import MethodType as instancemethod
class Foo:
def __init__(self):
print 'I am ', id(self)
def bar(self):
print 'hi', id(self)
foo = Foo() # prints 'I am <instance id>'
mm = instancemethod(bar, foo) # automatically uses foo.__class__
mm() # prints 'I have been bound to <same instance id>'
foo.mm # traceback because no 'field' created in foo to hold ref to mm
foo.mm = mm # create ref to bound method in foo
foo.mm() # prints 'I have been bound to <same instance id>'
This will do the same:
>>> Testcase.testName = testFunc
Yeah, it's really that simple.
Your line
>>> instanceMethod = new.instancemethod(testFunc, None, TestCase)
Is in practice (although not in theory) a noop. :) You could just as well do
>>> instanceMethod = testFunc
In fact, in Python 3 I'm pretty sure it would be the same in theory as well, but the new module is gone so I can't test it in practice.
To confirm that it's not needed to use new.instancemthod() at all since Python v2.4, here's an example how to replace an instance method. It's also not needed to use descriptors (even though it works).
class Ham(object):
def spam(self):
pass
h = Ham()
def fake_spam():
h._spam = True
h.spam = fake_spam
h.spam()
# h._spam should be True now.
Handy for unit testing.
Could you clarify some ideas behind Python classes and class instances?
Consider this:
class A():
name = 'A'
a = A()
a.name = 'B' # point 1 (instance of class A is used here)
print a.name
print A.name
prints:
B
A
if instead in point 1 I use class name, output is different:
A.name = 'B' # point 1 (updated, class A itself is used here)
prints:
B
B
Even if classes in Python were some kind of prototype for class instances, I'd expect already created instances to remain intact, i.e. output like this:
A
B
Can you explain what is actually going on?
First of all, the right way in Python to create fields of an instance (rather than class fields) is using the __init__ method. I trust that you know that already.
Python does not limit you in assigning values to non-declared fields of an object. For example, consider the following code:
class Empty: pass
e = Empty()
e.f = 5
print e.f # shows 5
So what's going in your code is:
You create the class A with a static field name assigned with A.
You create an instance of A, a.
You create a new field for the object a (but not for other instances of A) and assign B to it
You print the value of a.name, which is unique to the object a.
You print the value of the static field A.name, which belongs to the class
Perhaps this example may make things more help clarify. Recall that Python names are not storage (as variables are in other languages) but references to storage. You can find what a name refers to with id(name). The identity operator x is y tells whether two names point at the same object.
>>> class A(object):
... name = 'A'
...
>>> x = A()
>>> A.name is x.name
True
>>> x.name = 'fred' # x.name was bound to a new object (A.name wasn't)
>>> A.name is x.name
False
>>> x = A() # start over
>>> A.name is x.name
True # so far so good
>>> A.name = 'fred'
>>> A.name is x.name
True # this is somewhat counter-intuitive
You also should look at these SO threads for further explanations:
Static class variables in Python
In Python how can I access "static" class variables within class methods
And an official tutorial:
http://docs.python.org/tutorial/classes.html#SECTION0011320000000000000000
Keep in mind that the assignment "=" operator in python behaves differently than C++ or Java:
http://docs.python.org/reference/simple_stmts.html#assignment-statements
What is the best way to dynamically create a Python object instance when all you have is the Python class saved as a string?
For background, I am working in the Google Application Engine environment and I want to be able to load classes dynamically from a string version of the class.
problem = “1,2,3,4,5”
solvertext1 = “””class solver:
def solve(self, problemstring):
return len(problemstring) “””
solvertext2 = “””class solver:
def solve(self, problemstring):
return problemstring[0] “””
solver = #The solution code here (solvertext1)
answer = solver.solve(problem) #answer should equal 9
solver = #The solution code here (solvertext2)
answer = solver.solve(problem) # answer should equal 1
Alas, exec is your only choice, but at least do it right to avert disaster: pass an explicit dictionary (with an in clause, of course)! E.g.:
>>> class X(object): pass
...
>>> x=X()
>>> exec 'a=23' in vars(x)
>>> x.a
23
this way you KNOW the exec won't pollute general namespaces, and whatever classes are being defined are going to be available as attributes of x. Almost makes exec bearable...!-)
Use the exec statement to define your class and then instantiate it:
exec solvertext1
s = solver()
answer = s.solve(problem)
Simple example:
>>> solvertext1 = "def f(problem):\n\treturn len(problem)\n"
>>> ex_string = solvertext1 + "\nanswer = f(%s)"%('\"Hello World\"')
>>> exec ex_string
>>> answer
11