eval in template strings - string

I'm considering porting a rather unwieldy bash script to python but I'm stuck on how to handle the following aspect: The point of the script is to generate a png image depending on dynamically fetched data. The bash script grabs the data, and builds a very long invocation of the convert utility, with lots of options. It seemed like python's template strings would be a good solution (I would vastly prefer to stay within the standard library, since I'll be deploying to shared hosting), but I discovered that you can't evaluate expressions as you can in bash:
>>> from string import Template
>>> s = Template('The width times one is ${width}')
>>> s.substitute(width=45)
'The width times one is 45'
>>> t = Template('The width times two is ${width*2}')
>>> t.substitute(width=45)
# Raises ValueError
Since my bash script depends quite heavily on such arithmetic (otherwise the number of variables to keep track of would increase exponentially) I'd like to know if there's a way to emulate this behavior in python. I saw that this question, asking roughly the same, has a comment, reading:
This would be very unPythonic, because it's counterintuitive -- strings are just
strings, they shouldn't run code!
If this is the case, what would be a more idiomatic way to approach this problem?
The proposed answer to the question linked above is to use string formatting with either the % syntax or the format() function, but I don't think that would work well with the number of variables in my string (around 50).

Why not use built-in string formatting?
width = 45
"Width times one is {width}".format(width=width)
"Width times two is {width}".format(width=2*width)
results in
Width times one is 45
Width times two is 90

The Pythonic solution to this problem is to forget about string formatting and pass a list of arguments to one of the subprocess functions, e.g.
# I have no idea about convert's command line usage,
# so here's an example using echo.
subprocess.call(["echo", str(1 + 1), "bla"])
That way, there's no need to build a single string and no need to worry about quoting.

You probably need a better templating engine. Jinja2 supports this kind of stuff and a lot more. I don't think the standard library has anything equally powerful, but from what I figured, the library is pure Python, so you can integrate it into your application by just copying it along.
If Jinja doesn't fit you for some reason, have a look at the Python wiki, which has a section specifically for those kinds of libraries. Amongst them is the very lightweight Templite, which is only one class and seems to do exactly what you need.

The task is not that hard, why don't you just make some coding for fun? And here is the function almost does what you want.
import re
def TempEval(template,**kwargs):
mark = re.compile('\${(.*?)}')
for key in kwargs:
exec('%s=%s'%(key,kwargs[key]))
for item in mark.findall(template):
template=template.replace('${%s}'%item,str(eval(item)))
return template
print TempEval('The width times one is ${width}',width=5)
#The width times one is 5
print TempEval('The width times two is ${width*2}',width=5)
#The width times two is 10

Related

python beginner : Dynamically modifying a python list with indexing/slicing to preform arithmetic operators [duplicate]

This question already has answers here:
Sum a list of numbers in Python
(26 answers)
Closed last month.
I have been stuck trying to write code that will dynamically take user input from a list and preform general arithmetic operators. In order to work around this I used indexing and slicing which did solve my problem temporarily but a new problem rose from doing this.
listgrades= []
num_students = int(input("How many students are you evaluating?"))
def student_info():
for i in range(0, num_students):
student_name=input("Enter your name here: ")
studnet_age=input("Enter your age here: ")
student_total_grade=int(float(input("What is your total grade")))
listgrades.append(student_total_grade)
student_info()
grades_sum= (listgrades[0] + listgrades[1] + listgrades[2]) / num_students
print(f"The average of all the student grades is {grades_sum}")
`
I'm trying to change the (listgrades[0] + listgrades[1] + listgrades[2]) to something more changeable, workable and scalable
I was trying to look and find a solution or a way to work around this but I hit a dead end and I ran out of ideas at this point.
I think a loop of some sorts might work for this but I'm not sure.
side note: I kinda looked into numpy and I can't use it since my school lab computers won't allow anything out of the default python module library.
I have some general advice and some specific suggestions.
For general advice, to see what built in methods are available is to use python itself.
At the command line type python3
then, within python type dir(list)
and you will see the available methods for lists.
You get more detailed information about any specific method by typing help and the class you are interested in followed by a dot, than the method name. For example help(list.count).
You can also type help(list) to get a more in depth list of all the functions and instructions for use. Type space to continue to the next screen, and b to backup a screen. Type q to end the help screens.
To exit python type exit()
More specifically, I agree that a loop would be a more dynamic direction to go, given you are asking how many students to evaluate in your input.
One way to loop through your list would be:
for x in listgrades:
sum = sum + x
Of course, you can perform other math operations inside the loop, or in similar loops. Presumably you will initialize your value before the loop.
At some point you may need to count how many grades are in your list. Fortunately, there's a built-in method for lists that gives you that information called count. You'll see this if you use python's dir(list) or help(list).
number_of_grades = listgrades.count
I think this will point you in the direction you were thinking with the code, without giving away much in exactly how, which is what you are learning. Best of luck!

Stuck on a Python 3 Parable iteration

Well, we got parables exam preparations and instead of me typing everything a million times, I thought of rather making a little Python script. It's done, but something's bugged. I've been stuck on it for around 30 minutes and just can't figure it out as my Python is a bit rusty.
You can find my code at: https://repl.it/#Rrrei/CurvySecondaryService
As mentioned before, for x in x: is indeed bad naming :p. You can easily get confused about what x you are talking about, the inner or the outer one.
Also a = input(..) makes a a string, a string multiplied by a number repeats the string in Python. e.g.:
'1'*5 == '11111'
To solve this, wrap input in a int: a=int(input(...))
You are going to append the string values. Python is not typesafe and a is a string after calling input()...
Here you can see a safe example with corrected values and better names (cleancode).
check my code
It´s the correct version of yours.
If you want the same form b=0 c=0....

Can I perform mathematics on a selection in Sublime Text?

Short of writing my own plugin to do so, does there exist a mechanism with which I can add/subtract from multiple selected numbers?
I need to apply the same equation (in this case, subtract 5) to many values; and I'd rather not do it individually. Could this perhaps be a job for another program?
If you already use Emmet (which I highly suggest), use its Evaluate Math function. No need to install more plugins. Only issue is that it cuts the result at 2 decimal digits.
There's plugin called Sublime-Evaluate which allows you to evaluate bits of Python, and output it straight into your buffer. For example, [i for i in range(5)] evaluated turns itself into [0, 1, 2, 3, 4]. That can be used for arithmetic operations as well, just use those multiple selections and write +5 after each value, then select it all and evaluate. The plugin usually screws positions of your cursors, don't get confused by that.
Sublime Calculate evaluates selected text, and looks great for small calculations, especially paired with the replace option: https://github.com/colinta/SublimeCalculate
As stated before, Sublime Evaluate has python evaluation covered: https://github.com/jbrooksuk/Sublime-Evaluate
Saw this yesterday and thought I would take a shot at it. Basically does the same thing as the Sublime-Evaluate (to bad I didn't see that earlier, could have saved some time). Anyways, the benefit of mine is it allows you to predefine python snippets to run. It also does some variable substitution of the content selected by the cursor. It doesn't do any expansion so you will have to select the content to insert. I was thinking of creating a setting to modify the word separator for the plugin, but hadn't decided yet. If you have an opinion on it, let me know.
https://github.com/skuroda/EvalInsert

String Class Methods Most Commonly Used

Any programming language. I'm interested in knowing what top 5 methods in a string class are used on data manipulations. Or what top 5 methods does one need to know to be able to handle data manipulation. I know probably all the methods together should be used, but I'm interested to see the 5 most common methods people use.
Thanks for your time.
I'd say
String.Format()
String.Split()
String.IndexOf()
String.Substring()
String.ToUpper()
Adam's top 5 are pretty much mine. I might replace IndexOf() with Trim(); I use this EVERY TIME I get a value from the user. String.Compare() using the IgnoreCase values of the StringComparison enumeration would replace most of the uses I've seen for ToUpper().
Format, HEAVILY used in logs and other user messages (far more efficient for templated messages than a bunch of += statements or a StringBuilder()). Split and Substring, ditto, especially in file processing.
Adam's + KeithS. But don't forget the under the hood calls to
String.hashCode(),
String.equals(String rhs)
and its ilk.

Identifying frequent formulas in a codebase

My company maintains a domain-specific language that syntactically resembles the Excel formula language. We're considering adding new builtins to the language. One way to do this is to identify verbose commands that are repeatedly used in our codebase. For example, if we see people always write the same 100-character command to trim whitespace from the beginning and end of a string, that suggests we should add a trim function.
Seeing a list of frequent substrings in the codebase would be a good start (though sometimes the frequently used commands differ by a few characters because of different variable names used).
I know there are well-established algorithms for doing this, but first I want to see if I can avoid reinventing the wheel. For example, I know this concept is the basis of many compression algorithms, so is there a compression module that lets me retrieve the dictionary of frequent substrings? Any other ideas would be appreciated.
The string matching is just the low hanging fruit, the obvious cases. The harder cases are where you're doing similar things but in different order. For example suppose you have:
X+Y
Y+X
Your string matching approach won't realize that those are effectively the same. If you want to go a bit deeper I think you need to parse the formulas into an AST and actually compare the AST's. If you did that you could see that the tree's are actually the same since the binary operator '+' is commutative.
You could also apply reduction rules so you could evaluate complex functions into simpler ones, for example:
(X * A) + ( X * B)
X * ( A + B )
Those are also the same! String matching won't help you there.
Parse into AST
Reduce and Optimize the functions
Compare the resulting AST to other ASTs
If you find a match then replace them with a call to a shared function.
I would think you could use an existing full-text indexer like Lucene, and implement your own Analyzer and Tokenizer that is specific to your formula language.
You then would be able to run queries, and be able to see the most used formulas, which ones appear next to each other, etc.
Here's a quick article to get you started:
Lucene Analyzer, Tokenizer and TokenFilter
You might want to look into tag-cloud generators. I couldn't find any source in the minute that I spent looking, but here's an online one:
http://tagcloud.oclc.org/tagcloud/TagCloudDemo which probably won't work since it uses spaces as delimiters.

Resources