how to unstringify arrays without external modules with python? - python

How to turn a string that contains an array into a normal array without using external modules? For example: “a[0]” into a[0]
edit:
I have seen a few complains about the amount of information in this post so I will add some more details about my problem for everyone watching this in future: My intention was to write a string that contains ”array[…]” somewhere in it but I need to execute this array somehow and my best choice was to remove the quotes around it but I don’t want to use eval() because of a few security issues
edit 2:
or tell me, how to express an equation in python without instantly solving it and without importing modules

one option is to use builtin eval function in python:
a = [ 'wowweeeee!' ]
print(eval('a[-1]')) # wowweeeee!
as #cards mentions in the comments, you can also pass a local dict object to restrict the scope of eval, to help address any security concerns:
try:
print(eval('a[-1]', {'a': a})) # wowweeeee!
except NameError as ne:
print('following variable is missing:', ne)

Related

Setting a variable to a parameter value inline when calling a function

In other languages, like Java, you can do something like this:
String path;
if (exists(path = "/some/path"))
my_path = path;
the point being that path is being set as part of specifying a parameter to a method call. I know that this doesn't work in Python. It is something that I've always wished Python had.
Is there any way to accomplish this in Python? What I mean here by "accomplish" is to be able to write both the call to exists and the assignment to path, as a single statement with no prior supporting code being necessary.
I'll be OK with it if a way of doing this requires the use of an additional call to a function or method, including anything I might write myself. I spent a little time trying to come up with such a module, but failed to come up with anything that was less ugly than just doing the assignment before calling the function.
UPDATE: #BrokenBenchmark's answer is perfect if one can assume Python 3.8 or better. Unfortunately, I can't yet do that, so I'm still searching for a solution to this problem that will work with Python 3.7 and earlier.
Yes, you can use the walrus operator if you're using Python 3.8 or above:
import os
if os.path.isdir((path := "/some/path")):
my_path = path
I've come up with something that has some issues, but does technically get me where I was looking to be. Maybe someone else will have ideas for improving this to make it fully cool. Here's what I have:
# In a utility module somewhere
def v(varname, arg=None):
if arg is not None:
if not hasattr(v, 'vals'):
v.vals = {}
v.vals[varname] = arg
return v.vals[varname]
# At point of use
if os.path.exists(v('path1', os.path.expanduser('~/.harmony/mnt/fetch_devqa'))):
fetch_devqa_path = v('path1')
As you can see, this fits my requirement of no extra lines of code. The "variable" involved, path1 in this example, is stored on the function that implements all of this, on a per-variable-name basis.
One can question if this is concise and readable enough to be worth the bother. For me, the verdict is still out. If not for the need to call the v() function a second time, I think I'd be good with it structurally.
The only functional problem I see with this is that it isn't thread-safe. Two copies of the code could run concurrently and run into a race condition between the two calls to v(). The same problem is greatly magnified if one fails to choose unique variable names every time this is used. That's probably the deal killer here.
Can anyone see how to use this to get to a similar solution without the drawbacks?

Using exec() to get class instances

I have a class and I need to use string input to create it and I've heard about exec(), so I tried using that and I put the string in properly yet it gives me errors, this is the exec line:
exec(" ".join(args[2:])).toString()
The first 2 parts of the list are not relevant. I debugged this string just to see it is correct and even tried to hardcode it and it worked, but it didn't when I used exec.
What is wrong with this and how can I make this right?
Appreciating all the comment :)
Edit:
The error I get is AttributeError saying it is a NoneType, although if I just hardcode it it works perfectly fine.
Solution 1: instead of passing a Python expression, either use argparse's subcommands or define your own easily-parsable mini-language. You can store relevant classes and functions in a dict to get them from strings (better than relying on globals as it lets you whitelist only what you want to expose)
Solution 2: use the full power of the ast module to parse the Python expression into an ast then write your own visitors to safely evaluate the ast.
Solution 3: keep on using exec or eval and wait until some script kiddie erases your full hard-drive or worse.

Converting a variable into a string creates EOF error

def evaluate(x):
number = str(eval(entry_drones.get()))
if x == drones :
create_drone(number)
entry_drones = Entry(frame, text = "1")
entry_drones.bind("<Return>", evaluate(drones))
I have a program that creates an error along the lines of:
number = str(eval(entry_drones.get()))
File "<string>", line 0
^
SyntaxError: unexpected EOF while parsing
I tried searching for the answer online, but they say I'm either missing a parenthesis (I've been unable to spot where it is needed) or I'm using input instead of raw_input (Neither appear to be the cause of this error, at least to my knowledge)
I posted just the code that I think is relevant to the issue, but I can provide more if needed. Take note, I have math and Tkinter imported, as well as other things.
I used eval because it is the only way I know (out of limited experience) to take the input from my Entry widget and simplify it before I run it through another function.
As for drones, it lets my evaluate function know which function to pass number to. I snipped out all of the other options because it is repetitive and it all leads to this function. entry_drones can have basic expressions put into it such as 10 * 10 or something. In my code I set k = 1000 and so forth, allowing me to use letters to abbreviate.
The entry_drones.get() should (if I'm not mistaken) grab whatever is typed into the Entry widget whenever the Enter key is pressed.
The eval function interprets the string you pass to it as Python code. You'll get a SyntaxError if anything is typed in your text entry box that isn't a valid Python expression (such as an empty string, for instance). You might get other exceptions too, if you type something that could be valid, but has other problems (for instance, calling eval on a random string that could be a variable name will probably raise a NameError since there is no such variable).
If that's the only problem, you probably just want to catch exceptions from the eval call and either ignore them or give an appropriate error message in your program.
Be aware too that calling eval on user input can be really dangerous. If a user types in something like __import__("os").system("rm -Rf /") your program might quietly delete the entire contents of your hard drive (don't try this!). This is obviously a much bigger deal if your program is running with more permissions on your system than the user would have by themselves (probably not likely for a GUI app, but very common for a web app), but even if you're only capable of doing things that the user could do anyway from a command prompt, it's a bad idea to use eval on untrusted input.
Unfortunately there isn't really a trivial way to do what I think you want (simplifying mathematical expressions, possibly including calls to functions like math.sqrt) without a bunch of work. One option would be to pass the string to ast.parse to get an abstract syntax tree, and then walk the tree to make sure it only does stuff you want to allow (such as using mathematical operators, and calling specific whitelisted functions (e.g. the ones in the math module). You can then pass the validated AST to compile and then eval it with confidence that it won't do anything bad.
eval() is very dangerous as #Blckknght explained well.
On a side note, Just to point out the actual root cause of the issue , it should be because of the line -
entry_drones.bind("<Return>", evaluate(drones))
This would run the function evalute() when this line is executed, and that is most probably before the app has even completely started, so the entry entry_drones is empty causing the issue. Then if it were to run successfully, it would pass the returned value to the bind method, in this case, None would be returned.
I believe if you want to send a parameter to your evaluate() function, then you should first make it accept more than one paraemter, since bind itself sends it event parameter. Example -
def evaluate(event, x):
...
Then use lambda expression with default value to pass the drones into x. Example -
entry_drones.bind("<Return>", lambda event, x=drones: evaluate(event, x))

How to use %s to name a list

I'm trying to create a system on Python that allows me to create a list called (user)total, 'user' being the name of the user before total. However this is subjective as any account with any username could be made within my program.
I have tried to use
%stotal = [''] %user
however this comes up with a syntax error. How would I manage to do this?
You can't do that kind of meta-programming in python! (not with the syntax you posted)
But instead you can create a dictionary of lists indexed by the user name:
total = {}
total['username1'] = [''] #list for this username total
total['username2'] = ['']
etc.
It is possible. Hopefully seeing how will help to illustrate why, as Hyperboreus says, it's not a good idea.
If you do dir() in your interactive Python environment, you'll get a list of names that are available in your current scope. There will always be one called __builtins__, which exposes all of the functions and constants in the builtins module. These functions and constants are defined to be exactly the same ones that are available right from the start of your Python session in the global namespace, which you can take a look at with the builtin function globals().
In accordance with the Python data model, every Python object has an element named __dict__ that's a dictionary object whose keys are member names. If obj is the name of some Python object in the current scope, obj.__dict__["keyname"] will access the same member that you could get to more simply through obj.keyname.
So putting this together, you can set key/value pairs in __builtins__.__dict__ directly:
>>> __builtins__.__dict__["testvarname"] = "testval"
>>> print testvarname
testval
Whew! Getting pretty abstract pretty quick here. This might be useful for defining behavior based on user input or something else that you might not know until runtime... but you can probably see how you're working through a lot of complexity to get there and sort of circumventing the normal rules that Python sets out to try to help you keep your programs organized and easy to understand. xndrme's answer is likely to be the more straightforward way to solve the bigger problem you're facing.

Analogue of devar in Python

When writing Python code, I often find myself wanting to get behavior similar to Lisp's defvar. Basically, if some variable doesn't exist, I want to create it and assign a particular value to it. Otherwise, I don't want to do anything, and in particular, I don't want to override the variable's current value.
I looked around online and found this suggestion:
try:
some_variable
except NameError:
some_variable = some_expensive_computation()
I've been using it and it works fine. However, to me this has the look of code that's not paradigmatically correct. The code is four lines, instead of the 1 that would be required in Lisp, and it requires exception handling to deal with something that's not "exceptional."
The context is that I'm doing interactively development. I'm executing my Python code file frequently, as I improve it, and I don't want to run some_expensive_computation() each time I do so. I could arrange to run some_expensive_computation() by hand every time I start a new Python interpreter, but I'd rather do something automated, particularly so that my code can be run non-interactively. How would a season Python programmer achieve this?
I'm using WinXP with SP3, Python 2.7.5 via Anaconda 1.6.2 (32-bit), and running inside Spyder.
It's generally a bad idea to rely on the existence or not of a variable having meaning. Instead, use a sentinel value to indicate that a variable is not set to an appropriate value. None is a common choice for this kind of sentinel, though it may not be appropriate if that is a possible output of your expensive computation.
So, rather than your current code, do something like this:
# early on in the program
some_variable = None
# later:
if some_variable is None:
some_variable = some_expensive_computation()
# use some_variable here
Or, a version where None could be a significant value:
_sentinel = object()
some_variable = _sentinel # this means it doesn't have a meaningful value
# later
if some_variable is _sentinel:
some_variable = some_expensive_computation()
It is hard to tell which is of greater concern to you, specific language features or a persistent session. Since you say:
The context is that I'm doing interactively development. I'm executing my Python code file frequently, as I improve it, and I don't want to run some_expensive_computation() each time I do so.
You may find that IPython provides a persistent, interactive environment that is pleasing to you.
Instead of writing Lisp in Python, just think about what you're trying to do. You want to avoid calling an expensive function twice and having it run two times. You can write your function do to that:
def f(x):
if x in cache:
return cache[x]
result = ...
cache[x] = result
return result
Or make use of Python's decorators and just decorate the function with another function that takes care of the caching for you. Python 3.3 comes with functools.lru_cache, which does just that:
import functools
#functools.lru_cache()
def f(x):
return ...
There are quite a few memoization libraries in the PyPi for 2.7.
For the use case you give, guarding with a try ... except seems like a good way to go about it: Your code is depending on leftover variables from a previous execution of your script.
But I agree that it's not a nice implementation of the concept "here's a default value, use it unless the variable is already set". Python does not directly support this for variables, but it does have a default-setter for dictionary keys:
myvalues = dict()
myvalues.setdefault("some_variable", 42)
print some_variable # prints 42
The first argument of setdefault must be a string containing the name of the variable to be defined.
If you had a complicated system of settings and defaults (like emacs does), you'd probably keep the system settings in their own dictionary, so this is all you need. In your case, you could also use setdefault directly on global variables (only), with the help of the built-in function globals() which returns a modifiable dictionary:
globals().setdefault("some_variable", 42)
But I would recommend using a dictionary for your persistent variables (you can use the try... except method to create it conditionally). It keeps things clean and it seems more... pythonic somehow.
Let me try to summarize what I've learned here:
Using exception handling for flow control is fine in Python. I could do it once to set up a dict in which I can store what ever I want.
There are libraries and language features that are designed for some form of persistence; these can provide "high road" solutions for some applications. The shelve module is an obvious candidate here, but I would construe "some form of persistence" broadly enough to include #Blender's suggest to use memoization.

Categories

Resources