I have a function names "myfunction". I have a string "a", I need to pass it to "myfunction" so it will give the same result as if my string was a python object name, myfunction(a)
So I have
def myfunction(var):
print var
a = 1
mystring = "a"
I need to pass "mystring" to "myfuntion" so it will behave as variable "a" was passed to it.
I thought of something like this, but it won't work:
myfunction(exec(mystring))
PS. Yes, I know of the consequences of exec(), please there is no need to explain that.
It would be eval(), not exec:
myfunction(eval(mystring))
Alternatively:
myfunction(locals()[mystring])
Most probably you have a fundamental design problem if you think you need something like this.
No needs in exec or eval:
>>> def myfunc(var):
... print globals()[var] * 2
...
>>> a = 12
>>> myfunc('a')
24
Related
Suppose I have
x = 3
s = "f'12{x}4'"
How to consider s as f-string to print 1234, like writing print(f'12{x}4')
when I print s, it prints it as it as: f'12{x}4'
Remve the double quotations that should fix the issue because the f in a f string needs to be outside the actuall string
You are missing two concepts.
The first one, is how you tell python your string is an f-string. The way to do this, is by adding the character 'f' before the first quotation mark:
f"this will be a f-string"
Whatever you have between {}, it will be a previously defined variable:
x = "something"
f"this will be {x}"
Assuming you ask this because you can not use actual f-strings, but also don't want to pass the parameters explicitly using format, maybe because you do not know which parameter are in the not-really-an-f-string, and also assuming you don't want to use eval, because, well, eval.
You could pass the variables in the locals or globals scope to format:
>>> x = 3
>>> s = '12{x}4'
>>> s.format(**globals())
'1234'
>>> s.format(**locals())
'1234'
Depending on where s is coming from (user input perhaps?) This might still be a bit risky, though, and it might be better to define a dict of "allowed" variables and use that in format. As with globals and locals, any unused variables do not matter.
>>> vars = {"x": x, "y": y, "z": z}
>>> s.format(**vars)
Note that this does not give you the full power of f-strings, though, which will also evaluate expressions. For instance, the above will not work for s = '12{x*x}4'.
You'd do this -
x = 3
s = f'12{x}4'
This can also work.
x = 3
s = "12{}4"
print(s.format(x))
Just remove extra commas
s = f'12{x}4'
x = 3
s = '12{}4'.format(x)
or
x = 3
print('12%s4' %x)
This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 1 year ago.
This is probably a really novice question, so forgive me.
If I know the name of an instance/variable - let's say I have a string called "variable_name" and a variable with the same name, how would I go about writing a piece of code that takes that string and converts it into something I can actually use and use class methods on, etc? Is that a thing that can happen at all?
Edit: Added some code to better articulate my question. I've got a code setup kind of like this (simplified for space):
class Class_Name:
count = 0
def __init__(self, foo, bar):
self.__class__.count += 1
self.foo = foo
self.bar = bar
def find_variable_name(class_name, number):
variable_name = "variable" + str(number)
return variable_name
variable1 = Class_Name("foo", "bar")
variable2 = Class_Name("foo2", "bar2")
variable3 = Class_Name("foo3", "bar3")
for instances in range(Class_Name.count):
print (find_variable_name(Class_Name, instances+1).foo)
This would give me the error "AttributeError: 'str' object has no attribute 'foo'" - how would I turn the object from a string to something I can work with?
You can simply use exec() function:
k = "my_str" # a string
exec(k + " = k") # my_str = "my_str"
Then, the output is:
>>> print(my_str)
'my_str'
The exec() function executes the string given it.
So, when we do exec(k + " = k"), it means, exec("my_str = k"), which assigns the value of the variable k to my_str.
This makes my_str = "my_str".
NOTE:
Be a little wary of the exec() function, especially if the value of the variable is user-inputted. Then, it could be dangerous to use.
locals() returns a dictionary of the variable bindings of the current scope.
The keys of the dictionary are strs so you can do lookup using the variable name. E.g.
>>> somevariable = 1
>>> locals()["somevariable"]
1
Of course it may be that the variable you want is not in the current scope, then it will not be in locals(). However, if it is in the global scope, you can use globals() in the same way. E.g.
>>> somevariable = 1
>>> globals()["somevariable"]
1
So in your example above, you might use a function like:
def find_variable_name(number):
return globals()["variable" + str(number)]
Which you can use as:
>>> variable1 = Class_Name("foo", "bar")
>>> find_variable_name(1).foo
'foo'
NOTE THAT this type of thing is not good programming practice. Doing this makes code harder to read and understand and maintain. Depending on your application, it might be better just to keep a Dict of your objects, indexing with the counts. E.g.
>>> d = {i: Class_Name("foo", "bar") for i in range(10)}
>>> d[1].foo
'foo'
This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 3 years ago.
I noticed that my code has many statements like this:
var = "some_string"
var = some_func(var)
var = another_func(var)
print(var) # outputs "modified_string"
It's really annoying me, it just looks awful (in the opposite of whole Python).
How to avoid using that and start using it in a way like this:
var = "some_string"
modify(var, some_func)
modify(var, another_func)
print(var) # outputs "modified_string"
That might not be the most "pythonic" thing to do, but you could "wrap" your string in a list, since lists are mutable in Python.
For example:
var = "string"
var_wrapper = [var]
Now you can pass that list to functions and access its only element. When changed, it will be visible outside of the function:
def change_str(lst):
lst[0] = lst[0] + " changed!"
and you'll get:
>>> change_str(var_wrapper)
>>> var_wrapper[0]
"string changed!"
To make things a bit more readable, you could take it one step further and create a "wrapper" class:
class my_str:
def __init__(self, my_string):
self._str = my_string
def change_str(self, new_str):
self._str = new_str
def __repr__(self):
return self._str
Now let's run the same example:
>>> var = my_str("string")
>>> var
string
>>> var.change_str("new string!")
>>> var
new string!
* Thanks for #Error-SyntacticalRemorse for the remark of making a class.
The problem is that str, int and float (long too, if you're in Py 2.x (True and False are really ints, so them too)) are what you call 'immutable types' in Python. That means that you can't modify their internal states: all manipulations of an str (or int or float) will result in a "new" instance of the str (or whatever) while the old value will remain in Python's cache until the next garbage collection cycle.
Basically, there's nothing you can do. Sorry.
In fact, there's been at least one attempt to add a compose function to functools. I guess I understand why they didn't... But hey, that doesn't mean we can't make one ourselves:
def compose(f1, f2):
def composition(*args, **kwargs):
return f1(f2(*args, **kwargs))
return composition
def compose_many(*funcs):
if len(funcs) == 1:
return funcs[0]
if len(funcs) == 2:
return compose(funcs[0], funcs[1])
else:
return compose(funcs[0], compose_many(*funcs[1:]))
Tested:
>>> def append_foo(s):
... return s + ' foo'
...
>>> def append_bar(s):
... return s + ' bar'
...
>>> append_bar(append_foo('my'))
'my foo bar'
>>> compose(append_bar, append_foo)('my')
'my foo bar'
>>> def append_baz(s):
... return s + ' baz'
...
>>> compose_many(append_baz, append_bar, append_foo)('my')
'my foo bar baz'
Come to think of it, this probably isn't the best solution to your problem. But it was fun to write.
the others already explained why that's not possible, but you could:
for modify in some_func, other_func, yet_another_func:
var = modify(var)
or as pst said:
var = yet_another_func(other_func(some_func(var)))
There is a way to modify an immutable variable, by rewriting it in the local symbol table, however, I think that it's not very nice and should be avoided as much as possible.
def updatevar(obj, value, callingLocals=locals()):
callingLocals[next(k for k, o in callingLocals.items() if o is obj)] = value
Another way, even less pythonic, is to use exec with a formatted instruction. It gets the variable name as a string thanks to this solution:
def getname(obj, callingLocals=locals()):
"""
a quick function to print the name of input and value.
If not for the default-Valued callingLocals, the function would always
get the name as "obj", which is not what I want.
"""
return next(k for k, v in callingLocals.items() if v is obj)
def updatevar2(k, v, callingLocals=locals()):
n = getname(k, callingLocals)
exec('global {};{}={}'.format(n, n, repr(v)))
The result is as expected:
var = "some_string"
updatevar(var, "modified_string")
print(var) # outputs "modified_string"
updatevar2(var, var + '2')
print(var) # outputs "modified_string2"
Strings are immutable in python, so your second example can't work. In the first example you are binding the name var to a completely new object on each line.
Typically multiple assignments to a single name like that are a code smell. Perhaps if you posted a larger sample of code someone here could show you a better way?
I'm just gonna put this right here (since none of the answers seem to have addressed it yet)
If you're commonly repeating the same sequences of functions, consider wrapping them in a higher level function:
def metafunc(var):
var = somefunc(var)
var = otherfunc(var)
var = thirdfunc(var)
return lastfunc(var)
Then when you call the function metafunc you know exactly what's happening to your var: nothing. All you get out of the function call is whatever metafunc returns.
Additionally you can be certain that nothing is happening in parts of your program that you forgot about. This is really important especially in scripting languages where there's usually a lot going on behind the scenes that you don't know about/remember.
There are benefits and drawbacks to this, the theoretical discussion is under the category of pure functional programming. Some real-world interactions (such as i/o operations) require non-pure functions because they need real-world implications beyond the scope of your code's execution.
The principle behind this is defined briefly here:
http://en.wikipedia.org/wiki/Functional_programming#Pure_functions
I have the following piece of code:
NameX.functionA(functionB(Dictionary["___"]))
Instead of _ I would like to make a reference to NameX in the form of a string, so that the program interprets it as
NameX.functionA(functionB(Dictionary["NameX"]))
How can I do this? I tried to use str(self), but it is clearly wrong.
Thanks
Is NameX.__name__ perhaps what you want?
You can use
Name.__name__
on an uninitialized object and
Name.__class__.__name__
on an initialized object.
Abusive but it works:
>>> def getvarname(var):
d = globals()
for n in d:
if d[n] is var:
return n
return None
>>> class NameX: pass
>>> getvarname(NameX)
'NameX'
Works on things that aren't just classes, too:
>>> inst1 = NameX()
>>> getvarname(inst1)
'inst1'
You might be shot if this ends up in real code, though.
Is there a way to know, during run-time, a variable's name (from the code)?
Or do variable's names forgotten during compilation (byte-code or not)?
e.g.:
>>> vari = 15
>>> print vari.~~name~~()
'vari'
Note: I'm talking about plain data-type variables (int, str, list etc.)
Variable names don't get forgotten, you can access variables (and look which variables you have) by introspection, e.g.
>>> i = 1
>>> locals()["i"]
1
However, because there are no pointers in Python, there's no way to reference a variable without actually writing its name. So if you wanted to print a variable name and its value, you could go via locals() or a similar function. ([i] becomes [1] and there's no way to retrieve the information that the 1 actually came from i.)
Variable names persist in the compiled code (that's how e.g. the dir built-in can work), but the mapping that's there goes from name to value, not vice versa. So if there are several variables all worth, for example, 23, there's no way to tell them from each other base only on the value 23 .
Here is a function I use to print the value of variables, it works for local as well as globals:
import sys
def print_var(var_name):
calling_frame = sys._getframe().f_back
var_val = calling_frame.f_locals.get(var_name, calling_frame.f_globals.get(var_name, None))
print (var_name+':', str(var_val))
So the following code:
global_var = 123
def some_func():
local_var = 456
print_var("global_var")
print_var("local_var")
print_var("some_func")
some_func()
produces:
global_var: 123
local_var: 456
some_func: <function some_func at 0x10065b488>
here a basic (maybe weird) function that shows the name of its argument...
the idea is to analyze code and search for the calls to the function (added in the init method it could help to find the instance name, although with a more complex code analysis)
def display(var):
import inspect, re
callingframe = inspect.currentframe().f_back
cntext = "".join(inspect.getframeinfo(callingframe, 5)[3]) #gets 5 lines
m = re.search("display\s+\(\s+(\w+)\s+\)", cntext, re.MULTILINE)
print m.group(1), type(var), var
please note:
getting multiple lines from the calling code helps in case the call was split as in the below example:
display(
my_var
)
but will produce unexpected result on this:
display(first_var)
display(second_var)
If you don't have control on the format of your project you can still improve the code to detect and manage different situations...
Overall I guess a static code analysis could produce a more reliable result, but I'm too lazy to check it now
This will work for simple data types (str, int, float, list etc.)
def my_print(var_str) :
print var_str+':', globals()[var_str]
You can do it, it's just not pretty.
import inspect, sys
def addVarToDict(d, variable):
lineNumber = inspect.currentframe().f_back.f_lineno
with open(sys.argv[0]) as f:
lines = f.read().split("\n")
line = lines[lineNumber-1]
varName = line.split("addVarToDict")[1].split("(")[1].split(",")[1].split(")")[0].strip()
d[varName] = variable
d = {}
a=1
print d # {}
addVarToDict(d,a)
print d # {'a': 1}
I tried the following link from the post above with no success:
Googling returned this one.
http://pythonic.pocoo.org/2009/5/30/finding-objects-names
Just yesterday I saw a blog post with working code that does just this. Here's the link:
http://pyside.blogspot.com/2009/05/finding-objects-names.html
Nice easy solution using f-string formatting, which is native to Python 3.6 and later:
vari = 15
vari_name = f"{vari=}".split("=")[0]
print(vari_name)
Produces:
vari