I have a list of strings:
A = ['a','b']
I want to parse this list and write following expressions:
a = x**2
b = a*x
where x is a sympy symbol and later on I will use these expressions for other operations like differentiation and so on. The problem is that a and b are strings inside the list. I am not being able to use them as expressions! How can I do this?
In general, you don't. Trying to set up dynamic variable names is usually a sign of poor design. If you do need those symbols to represent things to the outside world, try keeping a label and a value. For instance, a dictionary can do something like this for you.
symbol = { 'a': x**2; 'b': x**3 }
You can add symbols from there, change values, etc. For instance,
symbol = { 'a': x**2 }
symbol['b'] = symbol['a'] * x
Granted, you can build an expression string and use eval on the contents, but this is generally dangerous and hard to maintain well.
A wider possibility is to manipulate string values and write the Python script you'd like to run. Write it to a file and then use the os or subprocess commands to execute it.
Does that get you moving?
Related
Having declared assertions on a solver, how can I get and exploit single assertions out of all of them? So, if s.assertions could be transformed to a list, we could access a single statement. This can not be done. I explain by the following assertions on 'BitVecs' and what I'd like to get out.
from z3 import *
s = Solver()
x,y,z,w = BitVecs("x y z w",7) #rows
a,b,c,d,e = BitVecs("a b c d e",7) #cols
constr = [x&a==a,x&b==b,x&c!=c,x&d!=d,x&e!=e,
y&a==a,y&b!=b,y&c!=c,y&d!=d,y&e==e,
z&a!=a,z&b==b,z&c==c,z&d==d,z&e!=e,
w&a!=a,w&b==b,w&c!=c,w&d==d,w&e==e ]
s.add(constr)
R = [x,y,z,w]
C = [a,b,c,d,e]
s.assertions()
I need a matrix (list of lists) that indicates wheter a R,C-pair has == or != type of 'constr'. So, the matrix for the declared constr is
[[1,1,0,0,0],
[1,0,0,0,1],
[0,1,1,1,0],
[0,1,0,1,1]]
.
This is rather an odd thing to want to do. You are constructing these assertions yourself, so it's much better to simply keep track of how you constructed them to find out what they contain.
If these are coming from some other source (possible, I suppose), then you'll have to "parse" them back into AST form and walk their structure to answer questions of the form "what are the variables", "what are the connectives" etc. Doing so will require an understanding of how z3py internally represents these objects. While this is possible, I very much doubt it's something you want to do unless you're working on a library that's supposed to handle everything. (i.e., since you know what you're constructing, simply keep track of it elsewhere.)
But, if you do want to analyze these expressions, the way to go is to study the AST structure. You'll have to become familiar with the contents of this file: https://github.com/Z3Prover/z3/blob/master/src/api/python/z3/z3.py, and especially the functions decl and children amongst others.
I'm performing data analysis on a large number of variables contained in an hdf5 file. The code I've written loops over a list of variables and then performs analyses and outputs some graphs. It would be nice to be able to use the code for combinations of variables (like A+B or sqrt((A**2)+(B**2)) without having to put in a bunch of if statements, i.e. execute the statement in the string when loading the variables from my hdf5 file. If possible, I would like to avoid using pandas, but I'm not completely against it if that's the only efficient way to do what I want.
My hdf5 file looks something like this :
HDF5 "blahblah.hdf5" {
FILE_CONTENTS {
group /
group /all
dataset /all/blargle
dataset /all/blar
}
}
And what I would like to do is this (this functionality doesn't exist in h5py, so it bugs) :
myfile = h5py.File('/myfile/blahblah.hdf5')
varlist = ['blargle', 'blar', 'blargle+blar']
savelist = [None]*len(varlist)
for ido, varname in enumerate(varlist):
savelist[ido] = myfile['all'][varname]
#would like to evaluate varname upon loading
First you have to ask yourself: Do I know the arithmetic operations only at runtime or already at programming time?
If you know it already now, just write a function in Python for it.
If you know it only at runtime, you will need a parser. While there are libraries specialized on this out there (example), Python itself is already a parser. With exec you can execute strings containing Python code.
Now all you need to define is some sort of grammar for specific language. You need some conventions. You have them already, it seems you want to convert myfile['all']['blargle+blar'] to myfile['all']['blargle']+myfile['all']['blar']. In order to make life easier I recommend.
Put names of data sets in brackets.
varlist = ['[blargle]', '[blar]', '[blargle]+[blar]', 'sqrt(([blargle]**2)+([blar]**2)']
Then simply replace all terms in brackets by myfile['all'][name_in_brackets] and then execute the string with exec.
import re
for ido, varname in enumerate(varlist):
term = re.sub(r'\[(.*?)\]', lambda x: "myfile['all']['{}']".format(x), varname, flag='g')
savelist[ido] = exec(term)
The line using regular expression to match the variable names re.sub is actually not tested by me.
And still another drawback. I'm not sure reading data sets from an hdf5 object is fast since the same data set may be read multiple times and if hdf5 is not caching it might be better to store the data sets intermediately before doing computation on them.
I need to assign a image to three variables i.e dsp1, dsp2, dsp3 by looping. On execution, I get a Syntax error.
SyntaxError: can't assign to operator.
for i in range(0,3):
dsp+str(i)=Image.open("L1.jpg")
What is the problem with 'str(i)' ?
Can any one explain with simple example ?
Instead of generating dynamic variables, place these images in a list:
images = []
for i in range(3):
images[i] = Image.open("L1.jpg")
Using this method, the L1.jpg is assigned to the following:
images[0]
images[1]
images[2]
Alternatively, you can use a dictionary to get closer to the variable name format you are using:
images = {}
for i in range(3):
images['dsp' + str(i)] = Image.open("L1.jpg")
This produces a dictionary that has the following layout:
{
'dsp2': <image object>,
'dsp1': <image object>,
'dsp0': <image object>
}
You can access any of these images by using the key (ie. image['dsp1'])
In both of these cases, you don't need to worry about dynamic variables. Instead, everything you will be using sits in either a single list or dictionary.
You can not assign to an operator.
Look at your code line:
dsp + str(i) = Image.open("L1.jpg")
You have dsp + str(i) on the left side, an expression containing the sum operator +. Even if that would get evaluated properly, the result would be a string like "dsp1" for example. You can't assign any value to a string.
And because such uses make no sense, Python does not support operators on the left side of an assignment.
You want to dynamically create a variable name instead of hard-coding it. Although this is possible using exec(), that is strongly discouraged, as it easily leads to bugs in your code, is hard to read and even harder to debug. It may even be a security risk (code injection) if anything getting evaluated this way is untrusted data like user input.
What you should use instead is a simple list:
dsp = []
for i in range(0,3):
dsp[i] = Image.open("L1.jpg") # for whatever reason you open the same file 3 times...
You create a list simply using the square brackets. If you want to initialize it with some values, simply write them inside, separated by commas:
my_list = ["zero", 1, 2, "three", 4.5, True]
You access elements of a list by specifying an index value, starting with 0 for the first element:
print(my_list[3]) # output: three
You can also easily loop over all elements of a list:
for item in my_list:
print(item)
# output:
# zero
# 1
# 2
# three
# 4.5
# True
You can't just string text together to create a variable name like that unfortunately. The problem is with dsp+str(i)=, not just str(i).
If you absolutely must do it this way, you can do it using globals like so:
for i in range(0,3):
globals()["dsp" + str(i)] = Image.open("L1.jpg")
print(dsp1) # This will contain something
This will allow you to access those variables as if you had created them the 'normal' way first.
Ideally though, you should probably assign your results to a list instead, rather than discrete variable names.
The problem is that you're trying to generate variable names on the fly.
If I were you I would try to use a dictionary instead of generation dynamic variable names. If you REALLY need dynamic variable names I would go for something like this:
exec("dsp%d = Image.open(\"L1.jpg\")" % (i));
but I really do not recommend it. Just use a dictonary!
I am having trouble figuring out where I'm going wrong. So I need to randomly replace words and re-write them to the text file, until it no longer makes sense to anyone else. I chose some words just to test it, and have written the following code which is not currently working:
# A program to read a file and replace words until it is no longer understandable
word_replacement = {'Python':'Silly Snake', 'programming':'snake charming', 'system':'table', 'systems':'tables', 'language':'spell', 'languages':'spells', 'code':'snake', 'interpreter':'charmer'}
main = open("INF108.txt", 'r+')
words = main.read().split()
main.close()
for x in word_replacement:
for y in words:
if word_replacement[x][0]==y:
y==x[1]
text = " ".join(words)
print text
new_main = open("INF108.txt", 'w')
new_main.write(text)
new_main.close()
This is the text in the file:
Python is a widely used general-purpose, high-level programming
language. It's design philosophy emphasizes code readability, and its
syntax allows programmers to express concepts in fewer lines of code
than would be possible in languages such as C++ or Java. The language
provides constructs intended to enable clear programs on both a small
and large scale.Python supports multiple programming paradigms,
including object-oriented, imperative and functional programming or
procedural styles. It features a dynamic type system and automatic
memory management and has a large and comprehensive standard
library.Python interpreters are available for installation on many
operating systems, allowing Python code execution on a wide variety
of systems. Using third- party tools, such as Py2exe or Pyinstaller,
Python code can be packaged into stand-alone executable programs for
some of the most popular operating systems, allowing for the
distribution of Python-based software for use on those environments
without requiring the installation of a Python interpreter.
I've tried a few methods of this but as someone new to Python it's been a matter of guessing, and the last two days spent researching it online, but most of the answers I've found are either far too complicated for me to understand, or are specific to that person's code and don't help me.
OK, let's take this step by step.
main = open("INF108.txt", 'r+')
words = main.read().split()
main.close()
Better to use the with statement here. Also, r is the default mode. Thus:
with open("INF108.txt") as main:
words = main.read().split()
Using with will make main.close() get called automatically for you when this block ends; you should do the same for the file write at the end as well.
Now for the main bit:
for x in word_replacement:
for y in words:
if word_replacement[x][0]==y:
y==x[1]
This little section has several misconceptions packed into it:
Iterating over a dictionary (for x in word_replacement) gives you its keys only. Thus, when you want to compare later on, you should just be checking if word_replacement[x] == y. Doing a [0] on that just gives you the first letter of the replacement.
Iterating over the dictionary is defeating the purpose of having a dictionary in the first place. Just loop over the words you want to replace, and check if they're in the dictionary using y in word_replacement.
y == x[1] is wrong in two ways. First of all, you probably meant to be assigning to y there, not comparing (i.e. y = x[1] -- note the single = sign). Second, assigning to a loop variable doesn't even do what you want. y will just get overwritten with a new value next time around the loop, and the words data will NOT get changed at all.
What you want to do is create a new list of possibly-replaced words, like so:
replaced = []
for y in words:
if y in word_replacement:
replaced.append(word_replacement[y])
else:
replaced.append(y)
text = ' '.join(replaced)
Now let's do some refinement. Dictionaries have a handy get method that lets you get a value if the key is present, or a default if it's not. If we just use the word itself as a default, we get a nifty reduction:
replaced = []
for y in words:
replacement = word_replacement.get(y, y)
replaced.append(replacement)
text = ' '.join(replaced)
Which you can just turn into a one-line list-comprehension:
text = ' '.join(word_replacement.get(y, y) for y in words)
And now we're done.
It looks like you want something like this as your if statement in the nested loops:
if x==y:
y=word_replacement[x]
When you loop over a dictionary, you get its keys, not key-value pairs:
>>> mydict={'Python':'Silly Snake', 'programming':'snake charming', 'system':'table'}
>>> for i in mydict:
... print i
Python
programming
system
You can then get the value with mydict[i].
This doesn't quite work, though, because assigning to y doesn't change that element of words. You can loop over its indices instead of elements to assign to the current element:
for x in word_replacement:
for y in range(len(words)):
if x==words[y]:
words[y]=word_replacement[x]
I'm using range() and len() here to get a list of indices of words ([0, 1, 2, ...])
Your issue is probably here:
if word_replacement[x][0]==y:
Here's a small example of what is actually happening, which is probably not what you intended:
w = {"Hello": "World", "Python": "Awesome"}
print w["Hello"]
print w["Hello"][0]
Which should result in:
"World"
"W"
You should be able to figure out how to correct the code from here.
You used word_replacement (which is a dictionary) in a wrong way. You should change for loop to something like this:
for y in words:
if y in word_replacement:
words[words.index(y)] = word_replacement[y]
I'm doing some work evaluating log data that has been saved as JSON objects to a file.
To facilitate my work I have created 2 small python scripts that filter out logged entries according to regular expressions and print out multiple fields from an event.
Now I'd like to be able to evaluate simple mathematical operations when printing fields. This way I could just say something like
./print.py type download/upload
and it would print the type and the upload to download ratio. My problem is that I can't use eval() because the values are actually inside a dict.
Is there a simple solution?
eval optionally takes a globals and locals dictionaries. You can therefore do this:
namespace = dict(foo=5, bar=6)
print eval('foo*bar', namespace)
Keep in mind that eval is "evil" because it's not safe if the executed string cannot be trusted. It should be fine for your helper script though.
For completness, there's also ast.literal_eval() which is safer but it evaluates literals only which means there's no way to give it a dict.
You could pass the dict to eval() as the locals. That will allow it to resolve download and upload as names if they are keys in the dict.
>>> d = {'a': 1, 'b': 2}
>>> eval('a+b', globals(), d)
3