This question already has answers here:
How to get the original variable name of variable passed to a function [duplicate]
(13 answers)
Closed 7 years ago.
I'd like to be able to access the name of a variable that is passed to a function as e.g.
def f(x):
'''Returns name of list/dict variable passed to f'''
return magic(x)
>>a = [1,2,3]
>>print( f(a) )
'a'
>>print( f(2) )
None
I suspect this is possible using Python introspection but I don't know enough to understand the inspect module. (NB I know that the need for a function like magic() is questionable, but it is what I want.)
Actually, this is not possible. In Python names and values are quite separate. Inside f, you have access to the value of x, but it is not possible to find out what other names other functions might have given to that value.
Think of names as being somewhat like pointers in C. If you have a pointer, you can find out what object it points to. But if you have the object, you cannot find out what pointers are pointing to it.
Related
This question already has answers here:
Given a function with closure, can I refer back to it's closure scope?
(1 answer)
What exactly is contained within a obj.__closure__?
(4 answers)
Closed 2 years ago.
I would like to know if there is any method to check whether two functions have the same arguments at runtime in python 3.
Basically, I have this function (func) that takes another function and an argument. I want to check the values assigned to args in the lambda function
func(another_func, args):
return lambda(x : another_func(x, args))
It is not feasible to run the code before and check the results because I am implementing a lazy framework. My main goal is to be able to understand what are the arguments of the function because there is one variable argument that I do not care but there is one static that is created before running the function.
##EDIT
I actually solved this problem using the inspect module (getclosure) for those who are interested!
I actually solved this problem using the inspect module (getclosure) for those who are interested!
Extension (Martijn Pieters):
I think you are referring to getclosurevars(). You can also just access function.closure, and access the value of each cell via its cell_contents attribute.
This question already has answers here:
How to restore a builtin that I overwrote by accident?
(3 answers)
Closed 2 years ago.
I am new to python, and realized that i can assign print i.e. an inbuilt function as a variable, then when i use print('hello world')this shows the exact error that i faced
I am familiar to c++ and even in that we were never allowed to use an inbuilt function as a variable name.
those were the fundamental rules for naming a variable
If python.org has issued the new version I'm sure they would have done it for a reason, bbut i want to know how do i access my print statement after assigning a value to it?
you won't be able to access your print function unless you do hacky things, which I recommend not to do them in the middle of your code.
Also it is good to know that python (as c++) has scopes for variables, and variables "die" and they are no longer accessible when scope ends. For instance:
def change_print_value():
print = 3
change_print_value()
print('Print works as expected')
It is a good practice to avoid using reserved keywords as variable names. Any IDE has the keywords highlighted, so you can easily realize when you are using a keyword where you shouldn't.
print is not part of the reserved keywords list in python. Here's a comprehensive list of reserved words.
Functions are first class objects in python, so that means they can be treated and manipulated as objects. Since print is a function (and an object), when you call print = 1, you reassign the variable print to have a value of 1, so the functionality "disappears".
This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 8 years ago.
So what I'm trying to do is run a function using concatenation like this:
location = 1
"critter_" + location + "()"
and I was hoping that would run the function 'critter_1()' but apparently it doesn't work like that so I tried a couple of stuff since it gave me an error about str to int concatenation error. So what I tried was:
location = 1
"critter_" + int(location) + "()"
And it still didn't work so I came here to ask you guys if there is any way to actually do this.
Any ideas? Thanks!
You can use globals()[function_name] to get function object. Once you get the function object, call it like ordinary name.
func = globals()['critter_{}'.format(location)]
# OR func = globals()['critter_' + str(location)]
func()
You have two separate problems:
You need to get the correct name for the function, so you need to convert your integer 1 to the string '1'. The easiest way is to just use funcname = "critter_"+str(location), although you have more control over the way the conversion is done if you use the format method of the strings. (You've got the meaning of int almost exactly backwards -- it converts to an integer; str converts to a string!)
You need to call the function given by the string. For this, you can use a number of different methods. Simplest is probably just to call eval(funcname+"()"), although this isn't always safe. You can also use funcname to find the function in the dictionary which stores all globally defined function, globals()[funcname].
Alternately, you could make your own list or dictionary of critter_n functions, and select from that:
critter_functions = {1: critter_1, 2: critter_2} #etc...
# ...
location = 1
critter_functions[location]()
This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 8 years ago.
I'm writing a class in python that groups a bunch of similar variables together and then assembles them into a string. I'm hoping to avoid having to manually type out each variable in the generateString method, so I want to use something like:
for variable in dir(class):
if variable[:1] == '_':
recordString += variable
But currently it just returns a string that has all of the variable names. Is there a way to get at the value of the variable?
You can use the getattr() function to dynamically access attributes:
recordString += getattr(classobj, variable)
However, you probably do not want to use dir() here. dir() provides you with a list of attributes on the instance, class and base classes, while you appear to want to find only attributes found directly on the object.
You can use the vars() function instead, which returns a dictionary, letting you use items() to get both name and value:
for variable, value in vars(classobj).items():
if variable[:1] == '_':
recordString += value
This question already has answers here:
Local variables in nested functions
(4 answers)
Closed 9 years ago.
I'm looking into generating a Python class dynamically from data.
(The purpose is to let users specify some software tests in a simple file, without knowing any Python).
I have run into an effect I did not expect;
as a toy example to quickly check that I can create methods according to a naming scheme I did the following:
import unittest
attrdict = {}
for i in range(3):
attrdict["test%s"%i]= types.MethodType(lambda self: i)
attrdict["runTest"]=lambda self: [eval("self.test%s()"%i) for i in range(3)]
dynTC = type('dynTC', (unittest.TestCase,), attrdict )
now when I execute
dynTC().runTest()
... I would expect
[0,1,2]
as output, but the actual result is
[2,2,2]
I would expect the lambda definitions to bind a deep copy of the loop index, since it is just a number rather than a more complex structure, but clearly there's stuff going on here that I don't understand.
I have a feeling this may be a common 'gotcha' for new Python programmers, but all the terms I can think of to describe the problem are so generic that my searches only return a deluge of unrelated answers.
Could you please explain to me what is happening here instead of what I expected, and preferably also what I should have done to create the desired effect of several /different/ methods.
The problem is with this line...
attrdict["test%s"%i]= types.MethodType(lambda self: i)
When you define a lambda that references a variable which isn't one of its arguments, the variable will be resolved from the scope in which the lambda was defined at the point when it's actually called, so you'll always get whatever the current value of i is, rather than the value of i at the point when you defined the lambda.
In your case, the value of i will end up as 2 after the for i in range(3) loop completes, so you need to create a closure to bind i to a specific value when creating the lambda, by changing the line to...
attrdict["test%s"%i]= types.MethodType(lambda self, i=i: i)