I already read How to get a function name as a string?.
How can I do the same for a variable? As opposed to functions, Python variables do not have the __name__ attribute.
In other words, if I have a variable such as:
foo = dict()
foo['bar'] = 2
I am looking for a function/attribute, e.g. retrieve_name() in order to create a DataFrame in Pandas from this list, where the column names are given by the names of the actual dictionaries:
# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [retrieve_name(d) for d in list_of_dicts]
With Python 3.8 one can simply use f-string debugging feature:
>>> foo = dict()
>>> f'{foo=}'.split('=')[0]
'foo'
One drawback of this method is that in order to get 'foo' printed you have to add f'{foo=}' yourself. In other words, you already have to know the name of the variable. In other words, the above code snippet is exactly the same as just
>>> 'foo'
Even if variable values don't point back to the name, you have access to the list of every assigned variable and its value, so I'm astounded that only one person suggested looping through there to look for your var name.
Someone mentioned on that answer that you might have to walk the stack and check everyone's locals and globals to find foo, but if foo is assigned in the scope where you're calling this retrieve_name function, you can use inspect's current frame to get you all of those local variables.
My explanation might be a little bit too wordy (maybe I should've used a "foo" less words), but here's how it would look in code (Note that if there is more than one variable assigned to the same value, you will get both of those variable names):
import inspect
x, y, z = 1, 2, 3
def retrieve_name(var):
callers_local_vars = inspect.currentframe().f_back.f_locals.items()
return [var_name for var_name, var_val in callers_local_vars if var_val is var]
print(retrieve_name(y))
If you're calling this function from another function, something like:
def foo(bar):
return retrieve_name(bar)
foo(baz)
And you want the baz instead of bar, you'll just need to go back a scope further. This can be done by adding an extra .f_back in the caller_local_vars initialization.
See an example here: ideone
The only objects in Python that have canonical names are modules, functions, and classes, and of course there is no guarantee that this canonical name has any meaning in any namespace after the function or class has been defined or the module imported. These names can also be modified after the objects are created so they may not always be particularly trustworthy.
What you want to do is not possible without recursively walking the tree of named objects; a name is a one-way reference to an object. A common or garden-variety Python object contains no references to its names. Imagine if every integer, every dict, every list, every Boolean needed to maintain a list of strings that represented names that referred to it! It would be an implementation nightmare, with little benefit to the programmer.
TL;DR
Use the Wrapper helper from python-varname:
from varname.helpers import Wrapper
foo = Wrapper(dict())
# foo.name == 'foo'
# foo.value == {}
foo.value['bar'] = 2
For list comprehension part, you can do:
n_jobs = Wrapper(<original_value>)
users = Wrapper(<original_value>)
queues = Wrapper(<original_value>)
priorities = Wrapper(<original_value>)
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [d.name for d in list_of_dicts]
# ['n_jobs', 'users', 'queues', 'priorities']
# REMEMBER that you have to access the <original_value> by d.value
I am the author of the python-varname package. Please let me know if you have any questions or you can submit issues on Github.
The long answer
Is it even possible?
Yes and No.
We are retrieving the variable names at runtime, so we need a function to be called to enable us to access the previous frames to retrieve the variable names. That's why we need a Wrapper there. In that function, at runtime, we are parsing the source code/AST nodes in the previous frames to get the exact variable name.
However, the source code/AST nodes in the previous frames are not always available, or they could be modified by other environments (e.g: pytest's assert statement). One simple example is that the codes run via exec(). Even though we are still able to retrieve some information from the bytecode, it needs too much effort and it is also error-prone.
How to do it?
First of all, we need to identify which frame the variable is given. It's not always simply the direct previous frame. For example, we may have another wrapper for the function:
from varname import varname
def func():
return varname()
def wrapped():
return func()
x = wrapped()
In the above example, we have to skip the frame inside wrapped to get to the right frame x = wrapped() so that we are able to locate x. The arguments frame and ignore of varname allow us to skip some of these intermediate frames. See more details in the README file and the API docs of the package.
Then we need to parse the AST node to locate where the variable is assigned value (function call) to. It's not always just a simple assignment. Sometimes there could be complex AST nodes, for example, x = [wrapped()]. We need to identify the correct assignment by traversing the AST tree.
How reliable is it?
Once we identify the assignment node, it is reliable.
varname is all depending on executing package to look for the node. The node executing detects is ensured to be the correct one (see also this).
It partially works with environments where other AST magics apply, including pytest, ipython, macropy, birdseye, reticulate with R, etc. Neither executing nor varname is 100% working with those environments.
Do we need a package to do it?
Well, yes and no, again.
If your scenario is simple, the code provided by #juan Isaza or #scohe001 probably is enough for you to work with the case where a variable is defined at the direct previous frame and the AST node is a simple assignment. You just need to go one frame back and retrieve the information there.
However, if the scenario becomes complicated, or we need to adopt different application scenarios, you probably need a package like python-varname, to handle them. These scenarios may include to:
present more friendly messages when the source code is not available or AST nodes are not accessible
skip intermediate frames (allows the function to be wrapped or called in other intermediate frames)
automatically ignores calls from built-in functions or libraries. For example: x = str(func())
retrieve multiple variable names on the left-hand side of the assignment
etc.
How about the f-string?
Like the answer provided by #Aivar Paalberg. It's definitely fast and reliable. However, it's not at runtime, meaning that you have to know it's foo before you print the name out. But with varname, you don't have to know that variable is coming:
from varname import varname
def func():
return varname()
# In external uses
x = func() # 'x'
y = func() # 'y'
Finally
python-varname is not only able to detect the variable name from an assignment, but also:
Retrieve variable names directly, using nameof
Detect next immediate attribute name, using will
Fetch argument names/sources passed to a function using argname
Read more from its documentation.
However, the final word I want to say is that, try to avoid using it whenever you can.
Because you can't make sure that the client code will run in an environment where the source node is available or AST node is accessible. And of course, it costs resources to parse the source code, identify the environment, retrieve the AST nodes and evaluate them when needed.
On python3, this function will get the outer most name in the stack:
import inspect
def retrieve_name(var):
"""
Gets the name of var. Does it from the out most frame inner-wards.
:param var: variable to get name from.
:return: string
"""
for fi in reversed(inspect.stack()):
names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
if len(names) > 0:
return names[0]
It is useful anywhere on the code. Traverses the reversed stack looking for the first match.
I don't believe this is possible. Consider the following example:
>>> a = []
>>> b = a
>>> id(a)
140031712435664
>>> id(b)
140031712435664
The a and b point to the same object, but the object can't know what variables point to it.
def name(**variables):
return [x for x in variables]
It's used like this:
name(variable=variable)
>> my_var = 5
>> my_var_name = [ k for k,v in locals().items() if v == my_var][0]
>> my_var_name
'my_var'
In case you get an error if myvar points to another variable, try this (suggested by #mherzog)-
>> my_var = 5
>> my_var_name = [ k for k,v in locals().items() if v is my_var][0]
>> my_var_name
'my_var'
locals() - Return a dictionary containing the current scope's local variables.
by iterating through this dictionary we can check the key which has a value equal to the defined variable, just extracting the key will give us the text of variable in string format.
from (after a bit changes)
https://www.tutorialspoint.com/How-to-get-a-variable-name-as-a-string-in-Python
I wrote the package sorcery to do this kind of magic robustly. You can write:
from sorcery import dict_of
columns = dict_of(n_jobs, users, queues, priorities)
and pass that to the dataframe constructor. It's equivalent to:
columns = dict(n_jobs=n_jobs, users=users, queues=queues, priorities=priorities)
Here's one approach. I wouldn't recommend this for anything important, because it'll be quite brittle. But it can be done.
Create a function that uses the inspect module to find the source code that called it. Then you can parse the source code to identify the variable names that you want to retrieve. For example, here's a function called autodict that takes a list of variables and returns a dictionary mapping variable names to their values. E.g.:
x = 'foo'
y = 'bar'
d = autodict(x, y)
print d
Would give:
{'x': 'foo', 'y': 'bar'}
Inspecting the source code itself is better than searching through the locals() or globals() because the latter approach doesn't tell you which of the variables are the ones you want.
At any rate, here's the code:
def autodict(*args):
get_rid_of = ['autodict(', ',', ')', '\n']
calling_code = inspect.getouterframes(inspect.currentframe())[1][4][0]
calling_code = calling_code[calling_code.index('autodict'):]
for garbage in get_rid_of:
calling_code = calling_code.replace(garbage, '')
var_names, var_values = calling_code.split(), args
dyn_dict = {var_name: var_value for var_name, var_value in
zip(var_names, var_values)}
return dyn_dict
The action happens in the line with inspect.getouterframes, which returns the string within the code that called autodict.
The obvious downside to this sort of magic is that it makes assumptions about how the source code is structured. And of course, it won't work at all if it's run inside the interpreter.
This function will print variable name with its value:
import inspect
def print_this(var):
callers_local_vars = inspect.currentframe().f_back.f_locals.items()
print(str([k for k, v in callers_local_vars if v is var][0])+': '+str(var))
***Input & Function call:***
my_var = 10
print_this(my_var)
***Output**:*
my_var: 10
>>> locals()['foo']
{}
>>> globals()['foo']
{}
If you wanted to write your own function, it could be done such that you could check for a variable defined in locals then check globals. If nothing is found you could compare on id() to see if the variable points to the same location in memory.
If your variable is in a class, you could use className.dict.keys() or vars(self) to see if your variable has been defined.
I have a method, and while not the most efficient...it works! (and it doesn't involve any fancy modules).
Basically it compares your Variable's ID to globals() Variables' IDs, then returns the match's name.
def getVariableName(variable, globalVariables=globals().copy()):
""" Get Variable Name as String by comparing its ID to globals() Variables' IDs
args:
variable(var): Variable to find name for (Obviously this variable has to exist)
kwargs:
globalVariables(dict): Copy of the globals() dict (Adding to Kwargs allows this function to work properly when imported from another .py)
"""
for globalVariable in globalVariables:
if id(variable) == id(globalVariables[globalVariable]): # If our Variable's ID matches this Global Variable's ID...
return globalVariable # Return its name from the Globals() dict
In Python, the def and class keywords will bind a specific name to the object they define (function or class). Similarly, modules are given a name by virtue of being called something specific in the filesystem. In all three cases, there's an obvious way to assign a "canonical" name to the object in question.
However, for other kinds of objects, such a canonical name may simply not exist. For example, consider the elements of a list. The elements in the list are not individually named, and it is entirely possible that the only way to refer to them in a program is by using list indices on the containing list. If such a list of objects was passed into your function, you could not possibly assign meaningful identifiers to the values.
Python doesn't save the name on the left hand side of an assignment into the assigned object because:
It would require figuring out which name was "canonical" among multiple conflicting objects,
It would make no sense for objects which are never assigned to an explicit variable name,
It would be extremely inefficient,
Literally no other language in existence does that.
So, for example, functions defined using lambda will always have the "name" <lambda>, rather than a specific function name.
The best approach would be simply to ask the caller to pass in an (optional) list of names. If typing the '...','...' is too cumbersome, you could accept e.g. a single string containing a comma-separated list of names (like namedtuple does).
I think it's so difficult to do this in Python because of the simple fact that you never will not know the name of the variable you're using. So, in his example, you could do:
Instead of:
list_of_dicts = [n_jobs, users, queues, priorities]
dict_of_dicts = {"n_jobs" : n_jobs, "users" : users, "queues" : queues, "priorities" : priorities}
Many of the answers return just one variable name. But that won't work well if more than one variable have the same value. Here's a variation of Amr Sharaki's answer which returns multiple results if more variables have the same value.
def getVariableNames(variable):
results = []
globalVariables=globals().copy()
for globalVariable in globalVariables:
if id(variable) == id(globalVariables[globalVariable]):
results.append(globalVariable)
return results
a = 1
b = 1
getVariableNames(a)
# ['a', 'b']
just another way to do this based on the content of input variable:
(it returns the name of the first variable that matches to the input variable, otherwise None. One can modify it to get all variable names which are having the same content as input variable)
def retrieve_name(x, Vars=vars()):
for k in Vars:
if isinstance(x, type(Vars[k])):
if x is Vars[k]:
return k
return None
If the goal is to help you keep track of your variables, you can write a simple function that labels the variable and returns its value and type. For example, suppose i_f=3.01 and you round it to an integer called i_n to use in a code, and then need a string i_s that will go into a report.
def whatis(string, x):
print(string+' value=',repr(x),type(x))
return string+' value='+repr(x)+repr(type(x))
i_f=3.01
i_n=int(i_f)
i_s=str(i_n)
i_l=[i_f, i_n, i_s]
i_u=(i_f, i_n, i_s)
## make report that identifies all types
report='\n'+20*'#'+'\nThis is the report:\n'
report+= whatis('i_f ',i_f)+'\n'
report+=whatis('i_n ',i_n)+'\n'
report+=whatis('i_s ',i_s)+'\n'
report+=whatis('i_l ',i_l)+'\n'
report+=whatis('i_u ',i_u)+'\n'
print(report)
This prints to the window at each call for debugging purposes and also yields a string for the written report. The only downside is that you have to type the variable twice each time you call the function.
I am a Python newbie and found this very useful way to log my efforts as I program and try to cope with all the objects in Python. One flaw is that whatis() fails if it calls a function described outside the procedure where it is used. For example, int(i_f) was a valid function call only because the int function is known to Python. You could call whatis() using int(i_f**2), but if for some strange reason you choose to define a function called int_squared it must be declared inside the procedure where whatis() is used.
Maybe this could be useful:
def Retriever(bar):
return (list(globals().keys()))[list(map(lambda x: id(x), list(globals().values()))).index(id(bar))]
The function goes through the list of IDs of values from the global scope (the namespace could be edited), finds the index of the wanted/required var or function based on its ID, and then returns the name from the list of global names based on the acquired index.
Whenever I have to do it, mostly while communicating json schema and constants with the frontend I define a class as follows
class Param:
def __init__(self, name, value):
self.name = name
self.value = value
Then define the variable with name and value.
frame_folder_count = Param({'name':'frame_folder_count', 'value':10})
Now you can access the name and value using the object.
>>> frame_folder_count.name
'frame_folder_count'
>>> def varname(v, scope=None):
d = globals() if not scope else vars(scope); return [k for k in d if d[k] == v]
...
>>> d1 = {'a': 'ape'}; d2 = {'b': 'bear'}; d3 = {'c': 'cat'}
>>> ld = [d1, d2, d3]
>>> [varname(d) for d in ld]
[['d1'], ['d2'], ['d3']]
>>> d5 = d3
>>> [varname(d) for d in ld]
[['d1'], ['d2'], ['d3', 'd5']]
>>> def varname(v, scope=None):
d = globals() if not scope else vars(scope); return [k for k in d if d[k] is v]
...
>>> [varname(d) for d in ld]
[['d1'], ['d2'], ['d3', 'd5']]
As you see and is noted here, there can be multiple variables with the same value or even address, so using a wrapper to keep the names with the data is best.
Following method will not return the name of variable but using this method you can create data frame easily if variable is available in global scope.
class CustomDict(dict):
def __add__(self, other):
return CustomDict({**self, **other})
class GlobalBase(type):
def __getattr__(cls, key):
return CustomDict({key: globals()[key]})
def __getitem__(cls, keys):
return CustomDict({key: globals()[key] for key in keys})
class G(metaclass=GlobalBase):
pass
x, y, z = 0, 1, 2
print('method 1:', G['x', 'y', 'z']) # Outcome: method 1: {'x': 0, 'y': 1, 'z': 2}
print('method 2:', G.x + G.y + G.z) # Outcome: method 2: {'x': 0, 'y': 1, 'z': 2}
A = [0, 1]
B = [1, 2]
pd.DataFrame(G.A + G.B) # It will return a data frame with A and B columns
Some of the previous cases would fail if there are two variables with the same value. So it is convenient to alert it:
Defining function:
# Variable to string of variable name
def var_name(variable,i=0):
results = []
for name in globals():
if eval(name) == variable:
results.append(name)
if len(results) > 1:
print('Warning:' )
print(' var_name() has found',len(results), 'possible outcomes.')
print(' Please choose the suitable parameter "i". Where "i" is the index')
print(' that matches your choice from the list below.')
print(' ',results) ; print('')
return results[i]
Use:
var_1 = 10
var_name(var_1) # Output will be "var_1"
If you have 2 variables with the same value like var_1 = 8 and var_2 = 8, then a warning will appear.
var_1 = 8
var_2 = 8
var_name(var_2) # Output will be "var_1" too but Warning will appear
You can get your variable as kwargs and return it as string:
var=2
def getVarName(**kwargs):
return list(kwargs.keys())[0]
print (getVarName(var = var))
Note: variable name must be equal to itself.
I try to get name from inspect locals, but it cann't process var likes a[1], b.val.
After it, I got a new idea --- get var name from the code, and I try it succ!
code like below:
#direct get from called function code
def retrieve_name_ex(var):
stacks = inspect.stack()
try:
func = stacks[0].function
code = stacks[1].code_context[0]
s = code.index(func)
s = code.index("(", s + len(func)) + 1
e = code.index(")", s)
return code[s:e].strip()
except:
return ""
You can try the following to retrieve the name of a function you defined (does not work for built-in functions though):
import re
def retrieve_name(func):
return re.match("<function\s+(\w+)\s+at.*", str(func)).group(1)
def foo(x):
return x**2
print(retrieve_name(foo))
# foo
When finding the name of a variable from its value,
you may have several variables equal to the same value,
for example var1 = 'hello' and var2 = 'hello'.
My solution:
def find_var_name(val):
dict_list = []
global_dict = dict(globals())
for k, v in global_dict.items():
dict_list.append([k, v])
return [item[0] for item in dict_list if item[1] == val]
var1 = 'hello'
var2 = 'hello'
find_var_name('hello')
Outputs
['var1', 'var2']
Compressed version of iDilip's answer:
import inspect
def varname(x):
return [k for k,v in inspect.currentframe().f_back.f_locals.items() if v is x][0]
hi = 123
print(varname(hi))
It's totally possible to get the name of an instance variable, so long as it is the property of a class.
I got this from Effective Python by Brett Slatkin. Hope it helps someone:
The class must implement the get, set, and set_name dunder methods, which are part of the "Descriptor Protocol"
This worked when I ran it:
class FieldThatKnowsItsName():
def __init__(self):
self.name = None
self._value= None
self.owner = None
def __set_name__(self, owner, name):
self.name = name
self.owner = owner
self.owner.fields[self.name] = self
def __get__(self, instance, instance_type):
return self
def __set__(self, instance, value):
self = value
class SuperTable:
fields = {}
field_1=FieldThatKnowsItsName()
field_2=FieldThatKnowsItsName()
table = SuperTable()
print(table.field_1.name)
print(table.field_2.name)
You can then add methods and or extend your datatype as you like.
As a bonus, the set_name(self, owner, name) dunder also passes the parent instance, so the Field class instance can register itself with the parent.
I got this from Effective Python by Brett Slatkin. It took a while to figure out how to implement.
How can I do the same for a variable? As opposed to functions, Python variables do not have the __name__ attribute.
The problem comes up because you are confused about terminology, semantics or both.
"variables" don't belong in the same category as "functions". A "variable" is not a thing that takes up space in memory while the code is running. It is just a name that exists in your source code - so that when you're writing the code, you can explain which thing you're talking about. Python uses names in the source code to refer to (i.e., give a name to) values. (In many languages, a variable is more like a name for a specific location in memory where the value will be stored. But Python's names actually name the thing in question.)
In Python, a function is a value. (In some languages, this is not the case; although there are bytes of memory used to represent the actual executable code, it isn't a discrete chunk of memory that your program logic gets to interact with directly.) In Python, every value is an object, meaning that you can assign names to it freely, pass it as an argument, return it from a function, etc. (In many languages, this is not the case.) Objects in Python have attributes, which are the things you access using the . syntax. Functions in Python have a __name__ attribute, which is assigned when the function is created. Specifically, when a def statement is executed (in most languages, creation of a function works quite differently), the name that appears after def is used as a value for the __name__ attribute, and also, independently, as a variable name that will get the function object assigned to it.
But most objects don't have an attribute like that.
In other words, if I have a variable such as:
That's the thing: you don't "have" the variable in the sense that you're thinking of. You have the object that is named by that variable. Anything else depends on the information incidentally being stored in some other object - such as the locals() of the enclosing function. But it would be better to store the information yourself. Instead of relying on a variable name to carry information for you, explicitly build the mapping between the string name you want to use for the object, and the object itself.
Related
So I have created a function that applies an action (in this case point wise multiplication of an array with a sinusoid, but that does not matter for my question) to an array.
Now I have created another function with which I want to create a string of python code to apply the first function multiple times later-on. The input of the second function can be either a string or an array, so that I can use the second function on its own output as well, if need be. My method of getting the variable name in a string works outside of the function.
Input :
var = np.array([[1,3],[2,4]]) # or sometimes var = 'a string'
if type(var)==str:
var_name = var
else:
var_name = [ k for k,v in locals().items() if v is var][0]
var_name
Output :
'var'
So here var is the variable (either array or string) supplied to the function, in this case an array. The if statement nicely returns me its name.
However when I use this inside my function, no matter what input I give it, it actually seems to look for var in locals(). Somehow it does not take var from the function input.
Definition :
def functionTWO(var, listoflistsofargs=None):
if type(var)==str:
var_name = var
else:
var_name = [ k for k,v in locals().items() if v is var][0]
if listoflistsofargs==None:
return var_name
command = []
for i in range(len(listoflistsofargs)):
if i==0:
command.append('functionONE(')
command.append(var_name)
command.append(',%.17f, %.17f)' % tuple(listoflistsofargs[i]))
else:
command.insert(0,'functionONE(')
command.append(',%.17f, %.17f)' % tuple(listoflistsofargs[i]))
''.join(command)
command[0] = var_name + ' + ' + command[0]
return ''.join(command)
Input :
somearray = np.array([[1,2,3],[1,2,3],[1,2,3]])
args = [[1,3],[6,5]]
command = functionTWO(somearray, args)
command
Output :
NameError: name 'var' is not defined
Wanted output :
'functionONE(functionONE(somearray, 1, 3), 6, 5)'
Why is listoflistsofargs taken from the function input and var not? I specify var in the listcomprehension in the definition of functionTWO. Normally when I use list comprehensions with function inputs it works fine. Does anybody know why this isnt the case here? Thank you in advance!
EDIT : So I guess the answer is dont. The implementation of classes by Marcin looks much cleaner and about the same order of amount of code. Too bad I couldnt get this to work inside a function. For other donts (actually other ideas) about using variable names as strings there is this question, where I got the above list comprehension for variable names.
You cannot pass a variable as a string*, and you should not do so.
If you want to pass a value between functions, the normal way is to pass it in as a parameter, and out as a return value.
If that is inconvenient, the usual solution is an object: define a class which carries both the shared variable, and methods which act on the variable.
If you need to create command objects, it is much better to do so in a structured way. For example, if you want to pass a function, and parameters, you can literally just pass the function object and the parameters in a tuple:
def foo():
return (functionONE,somearray,1,3)
command = foo()
command[0](*command[1:])
If you want to embed such commands within commands, you'll likely want to wrap that up with a class, so you can recursively evaluate the parameters. In fact, here's a little evaluator:
def evaluator(object):
def __init__(self,func=None,params=None):
self.func = func
self.params = params
def eval(self,alternativeparams=None):
if alternativeparams is not None:
params = alternativeparams
else:
params = self.params
if params is not None:
evaluatedparams = (item() if callable(item) else item for item in params)
else: evaluatedparams = None
if func is not None:
return self.func(*(evaluatedparams or ()))
else: return evaluatedparams
def __call__(self, *params):
return self.eval(params if params else None)
Although there are hacks by which you can pass references to local variables out of a function, these are not a great idea, because you end up creating your own half-baked object system which is more difficult to understand.
* This is because a variable has a name (which is a string) and a context, which maps names to strings. So, you need, at least to pass a tuple to truly pass a variable.
presenter's answer works in python 3
def get_variable_name(*variable):
return [ k for k,v in globals().items() if v is variable[0]][0]
example:
>> test = 'sample string'
>> get_variable_name(test)
'test'
>>
The only issue is it is a little messy.
The reason you get the error NameError: name 'var' is not defined when you wrap it all into a function is the following: locals().items() refers to the locally defined variables. as a matter of fact, the locally defined variables in your functions are only the variables defined inside the function and those passed as arguments to the function.
As the name says, locals().items() is local, and will consist of different variables depending on where it is called in your script.
On the contrary globals().items() consists of all the global variables, so try using it instead in your functions, it should do the trick.
For more info, look up global and local variables as well as the scope of variables in Python.
I have a class, and I would like to be able to create multiple objects of that class and place them in an array. I did it like so:
rooms = []
rooms.append(Object1())
...
rooms.append(Object4())
I then have a dict of functions, and I would like to pass the object to the function. However, I'm encountering some problems..For example, I have a dict:
dict = {'look': CallLook(rooms[i])}
I'm able to pass it into the function, however; in the function if I try to call an objects method it gives me problems
def CallLook(current_room)
current_room.examine()
I'm sure that there has to be a better way to do what I'm trying to do, but I'm new to Python and I haven't seen a clean example on how to do this. Anyone have a good way to implement a list of objects to be passed into functions? All of the objects contain the examine method, but they are objects of different classes. (I'm sorry I didn't say so earlier)
The specific error states: TypeError: 'NoneType' object is not callable
Anyone have a good way to implement a list of objects to be passed into functions? All of the objects contain the examine method, but they are objects of different classes. (I'm sorry I didn't say so earlier)
This is Python's plain duck-typing.
class Room:
def __init__(self, name):
self.name = name
def examine(self):
return "This %s looks clean!" % self.name
class Furniture:
def __init__(self, name):
self.name = name
def examine(self):
return "This %s looks comfortable..." % self.name
def examination(l):
for item in l:
print item.examine()
list_of_objects = [ Room("Living Room"), Furniture("Couch"),
Room("Restrooms"), Furniture("Bed") ]
examination(list_of_objects)
Prints:
This Living Room looks clean!
This Couch looks comfortable...
This Restrooms looks clean!
This Bed looks comfortable...
As for your specific problem: probably you have forgotten to return a value from examine()? (Please post the full error message (including full backtrace).)
I then have a dict of functions, and I would like to pass the object to the function. However, I'm encountering some problems..For example, I have a dict:
my_dict = {'look': CallLook(rooms[i])} # this is no dict of functions
The dict you have created may evaluate to {'look': None} (assuming your examine() doesn't return a value.) Which could explain the error you've observed.
If you wanted a dict of functions you needed to put in a callable, not an actual function call, e.g. like this:
my_dict = {'look': CallLook} # this is a dict of functions
if you want to bind the 'look' to a specific room you could redefine CallLook:
def CallLook(current_room)
return current_room.examine # return the bound examine
my_dict = {'look': CallLook(room[i])} # this is also a dict of functions
Another issue with your code is that you are shadowing the built-in dict() method by naming your local dictionary dict. You shouldn't do this. This yields nasty errors.
Assuming you don't have basic problems (like syntax errors because the code you have pasted is not valid Python), this example shows you how to do what you want:
>>> class Foo():
... def hello(self):
... return 'hello'
...
>>> r = [Foo(),Foo(),Foo()]
>>> def call_method(obj):
... return obj.hello()
...
>>> call_method(r[1])
'hello'
Assuming you have a class Room the usual way to create a list of instances would be using a list comprehension like this
rooms = [Room() for i in range(num_rooms)]
I think there are some things you may not be getting about this:
dict = {'look': CallLook(rooms[i])}
This creates a dict with just one entry: a key 'look', and a value which is the result of evaluating CallLook(rooms[i]) right at the point of that statement. It also then uses the name dict to store this object, so you can no longer use dict as a constructor in that context.
Now, the error you are getting tells us that rooms[i] is None at that point in the programme.
You don't need CallLook (which is also named non-standardly) - you can just use the expression rooms[i].examine(), or if you want to evaluate the call later rooms[i].examine.
You probably don't need the dict at all.
That is not a must, but in some cases, using hasattr() is good... getattr() is another way to get an attribute off an object...
So:
rooms = [Obj1(),Obj2(),Obj3()]
if hasattr(rooms[i], 'examine'):#First check if our object has selected function or attribute...
getattr(rooms[i], 'examine') #that will just evaluate the function do not call it, and equals to Obj1().examine
getattr(rooms[i], 'examine')() # By adding () to the end of getattr function, we evalute and then call the function...
You may also pass parameters to examine function like:
getattr(rooms[i], 'examine')(param1, param2)
I'm not sure of your requirement, but you can use dict to store multiple object of a class.
May be this will help,
>>> class c1():
... print "hi"
...
hi
>>> c = c1()
>>> c
<__main__.c1 instance at 0x032165F8>
>>> d ={}
>>> for i in range (10):
... d[i] = c1()
...
>>> d[0]
<__main__.c1 instance at 0x032166E8>
>>> d[1]
<__main__.c1 instance at 0x032164B8>
>>>
It will create a object of c1 class and store it in dict. Obviously, in this case you can use list instead of dict.
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
I do scientific programming, and often want to show users prompts and variable pairs, let them edit the variables, and then do the calulations with the new variables. I do this so often, that I wrote a wxPython class to move this code out of the main program. You set up a list for each variable with the type of the variable (string, float, int), the prompt, and the variable's current value. You then place all of these lists in one big list, and my utility creates a neatly formated wxPython panel with prompts and the current values which can be edited.
When I started, I only had a few variables, so I would write out each variable.
s='this is a string'; i=1; f=3.14
my_list=[ ['s','your string here',s], ['i','your int here',i], ['f','your float here'],]
input_panel = Input(my_list)
# the rest of the window is created, the input_panel is added to the window, the user is
# allowed to make choices, and control returns when the user hits the calculate button
s,i,f = input_panel.results() # the .results() function returns the values in a list
Now I want to use this routine for a lot of variables (10-30), and this approach is breaking down. I can create the input list to the function over multiple lines using the list.append() statements. When the code returns from the function, though, I get this huge list that needs to be unpacked into the right variables. This is difficult to manage, and it looks like it will be easy to get the input list and output list out of sync. And worse than that, it looks kludgy.
What is the best way to pass lots of variables to a function in Python with extra information so that they can be edited, and then get the variables back so that I can use them in the rest of the program?
If I could pass the variables by reference into the function, then users could change them or not, and I would use the values once the program returned from the function. I would only need to build the input list over multiple lines, and there wouldn't be any possiblity of the input list getting out of sync with the output list. But Python doesn't allow this.
Should I break the big lists into smaller lists that then get combined into big lists for passing into and out of the functions? Or does this just add more places to make errors?
The simplest thing to do would be to create a class. Instead of dealing with a list of variables, the class will have attributes. Then you just use a single instance of the class.
There are two decent options that come to mind.
The first is to use a dictionary to gather all the variables in one place:
d = {}
d['var1'] = [1,2,3]
d['var2'] = 'asdf'
foo(d)
The second is to use a class to bundle all the arguments. This could be something as simple as:
class Foo(object):
pass
f = Foo()
f.var1 = [1,2,3]
f.var2 = 'asdf'
foo(f)
In this case I would prefer the class over the dictionary, simply because you could eventually provide a definition for the class to make its use clearer or to provide methods that handle some of the packing and unpacking work.
To me, the ideal solution is to use a class like this:
>>> class Vars(object):
... def __init__(self, **argd):
... self.__dict__.update(argd)
...
>>> x = Vars(x=1, y=2)
>>> x.x
1
>>> x.y
2
You can also build a dictionary and pass it like this:
>>> some_dict = {'x' : 1, 'y' : 2}
>>> #the two stars below mean to pass the dict as keyword arguments
>>> x = Vars(**some_dict)
>>> x.x
1
>>> x.y
2
You may then get data or alter it as need be when passing it to a function:
>>> def foo(some_vars):
... some_vars.z = 3 #note that we're creating the member z
...
>>> foo(x)
>>> x.z
3
If I could pass the variables by reference into the function, then users could change them or not, and I would use the values once the program returned from the function.
You can obtain much the same effect as "pass by reference" by passing a dict (or for syntactic convenience a Bunch, see http://code.activestate.com/recipes/52308/).
if you have a finite set of these cases, you could write specific wrapper functions for each one. Each wrapper would do the work of building and unpacking lists taht are passed to the internal function.
I would recommend using a dictionary
or a class to accumulate all details
about your variables
value
prompt text
A list to store the order in which you want them to be displayed
Then use good old iteration to prepare input and collect output
This way you will only be modifying a small manageable section of the code time and again.
Of course you should encapsulate all this into a class if your comfortable working with classes.
"""Store all variables
"""
vars = {}
"""Store the order of display
"""
order = []
"""Define a function that will store details and order of the variable definitions
"""
def makeVar(parent, order, name, value, prompt):
parent[name] = dict(zip(('value', 'prompt'), (value, prompt)))
order.append(name)
"""Create your variable definitions in order
"""
makeVar(vars, order, 's', 'this is a string', 'your string here')
makeVar(vars, order, 'i', 1, 'your int here')
makeVar(vars, order, 'f', 3.14, 'your float here')
"""Use a list comprehension to prepare your input
"""
my_list = [[name, vars[name]['prompt'], vars[name]['value']] for name in order]
input_panel = Input(my_list)
out_list = input_panel.results();
"""Collect your output
"""
for i in range(0, len(order)):
vars[order[i]]['value'] = out_list[i];
Suppose I have code like:
x = 0
y = 1
z = 2
my_list = [x, y, z]
for item in my_list:
print("handling object ", name(item)) # <--- what would go instead of `name`?
How can I get the name of each object in Python? That is to say: what could I write instead of name in this code, so that the loop will show handling object x and then handling object y and handling object z?
In my actual code, I have a dict of functions that I will call later after looking them up with user input:
def fun1():
pass
def fun2():
pass
def fun3():
pass
fun_dict = {'fun1': fun1,
'fun2': fun2,
'fun3': fun3}
# suppose that we get the name 'fun3' from the user
fun_dict['fun3']()
How can I create fun_dict automatically, without writing the names of the functions twice? I would like to be able to write something like
fun_list = [fun1, fun2, fun3] # and I'll add more as the need arises
fun_dict = {}
for t in fun_list:
fun_dict[name(t)] = t
to avoid duplicating the names.
Objects do not necessarily have names in Python, so you can't get the name.
When you create a variable, like the x, y, z above then those names just act as "pointers" or "references" to the objects. The object itself does not know what name(s) you are using for it, and you can not easily (if at all) get the names of all references to that object.
However, it's not unusual for objects to have a __name__ attribute. Functions do have a __name__ (unless they are lambdas), so we can build fun_dict by doing e.g.
fun_dict = {t.__name__: t for t in fun_list)
That's not really possible, as there could be multiple variables that have the same value, or a value might have no variable, or a value might have the same value as a variable only by chance.
If you really want to do that, you can use
def variable_for_value(value):
for n,v in globals().items():
if v == value:
return n
return None
However, it would be better if you would iterate over names in the first place:
my_list = ["x", "y", "z"] # x, y, z have been previously defined
for name in my_list:
print "handling variable ", name
bla = globals()[name]
# do something to bla
This one-liner works, for all types of objects, as long as they are in globals() dict, which they should be:
def name_of_global_obj(xx):
return [objname for objname, oid in globals().items()
if id(oid)==id(xx)][0]
or, equivalently:
def name_of_global_obj(xx):
for objname, oid in globals().items():
if oid is xx:
return objname
As others have mentioned, this is a really tricky question. Solutions to this are not "one size fits all", not even remotely. The difficulty (or ease) is really going to depend on your situation.
I have come to this problem on several occasions, but most recently while creating a debugging function. I wanted the function to take some unknown objects as arguments and print their declared names and contents. Getting the contents is easy of course, but the declared name is another story.
What follows is some of what I have come up with.
Return function name
Determining the name of a function is really easy as it has the __name__ attribute containing the function's declared name.
name_of_function = lambda x : x.__name__
def name_of_function(arg):
try:
return arg.__name__
except AttributeError:
pass`
Just as an example, if you create the function def test_function(): pass, then copy_function = test_function, then name_of_function(copy_function), it will return test_function.
Return first matching object name
Check whether the object has a __name__ attribute and return it if so (declared functions only). Note that you may remove this test as the name will still be in globals().
Compare the value of arg with the values of items in globals() and return the name of the first match. Note that I am filtering out names starting with '_'.
The result will consist of the name of the first matching object otherwise None.
def name_of_object(arg):
# check __name__ attribute (functions)
try:
return arg.__name__
except AttributeError:
pass
for name, value in globals().items():
if value is arg and not name.startswith('_'):
return name
Return all matching object names
Compare the value of arg with the values of items in globals() and store names in a list. Note that I am filtering out names starting with '_'.
The result will consist of a list (for multiple matches), a string (for a single match), otherwise None. Of course you should adjust this behavior as needed.
def names_of_object(arg):
results = [n for n, v in globals().items() if v is arg and not n.startswith('_')]
return results[0] if len(results) is 1 else results if results else None
If you are looking to get the names of functions or lambdas or other function-like objects that are defined in the interpreter, you can use dill.source.getname from dill. It pretty much looks for the __name__ method, but in certain cases it knows other magic for how to find the name... or a name for the object. I don't want to get into an argument about finding the one true name for a python object, whatever that means.
>>> from dill.source import getname
>>>
>>> def add(x,y):
... return x+y
...
>>> squared = lambda x:x**2
>>>
>>> print getname(add)
'add'
>>> print getname(squared)
'squared'
>>>
>>> class Foo(object):
... def bar(self, x):
... return x*x+x
...
>>> f = Foo()
>>>
>>> print getname(f.bar)
'bar'
>>>
>>> woohoo = squared
>>> plus = add
>>> getname(woohoo)
'squared'
>>> getname(plus)
'add'
Use a reverse dict.
fun_dict = {'fun1': fun1,
'fun2': fun2,
'fun3': fun3}
r_dict = dict(zip(fun_dict.values(), fun_dict.keys()))
The reverse dict will map each function reference to the exact name you gave it in fun_dict, which may or may not be the name you used when you defined the function. And, this technique generalizes to other objects, including integers.
For extra fun and insanity, you can store the forward and reverse values in the same dict. I wouldn't do that if you were mapping strings to strings, but if you are doing something like function references and strings, it's not too crazy.
Note that while, as noted, objects in general do not and cannot know what variables are bound to them, functions defined with def do have names in the __name__ attribute (the name used in def). Also if the functions are defined in the same module (as in your example) then globals() will contain a superset of the dictionary you want.
def fun1:
pass
def fun2:
pass
def fun3:
pass
fun_dict = {}
for f in [fun1, fun2, fun3]:
fun_dict[f.__name__] = f
Here's another way to think about it. Suppose there were a name() function that returned the name of its argument. Given the following code:
def f(a):
return a
b = "x"
c = b
d = f(c)
e = [f(b), f(c), f(d)]
What should name(e[2]) return, and why?
And the reason I want to have the name of the function is because I want to create fun_dict without writing the names of the functions twice, since that seems like a good way to create bugs.
For this purpose you have a wonderful getattr function, that allows you to get an object by known name. So you could do for example:
funcs.py:
def func1(): pass
def func2(): pass
main.py:
import funcs
option = command_line_option()
getattr(funcs, option)()
I know This is late answer.
To get func name , you can use func.__name__
To get the name of any python object that has no name or __name__ method. You can iterate over its module members.
Ex:.
# package.module1.py
obj = MyClass()
# package.module2.py
import importlib
def get_obj_name(obj):
mod = Obj.__module__ # This is necessary to
module = module = importlib.import_module(mod)
for name, o in module.__dict__.items():
if o == obj:
return name
Performance note: don't use it in large modules.
Variable names can be found in the globals() and locals() dicts. But they won't give you what you're looking for above. "bla" will contain the value of each item of my_list, not the variable.
Generally when you are wanting to do something like this, you create a class to hold all of these functions and name them with some clear prefix cmd_ or the like. You then take the string from the command, and try to get that attribute from the class with the cmd_ prefixed to it. Now you only need to add a new function/method to the class, and it's available to your callers. And you can use the doc strings for automatically creating the help text.
As described in other answers, you may be able to do the same approach with globals() and regular functions in your module to more closely match what you asked for.
Something like this:
class Tasks:
def cmd_doit(self):
# do it here
func_name = parse_commandline()
try:
func = getattr('cmd_' + func_name, Tasks())
except AttributeError:
# bad command: exit or whatever
func()
I ran into this page while wondering the same question.
As others have noted, it's simple enough to just grab the __name__ attribute from a function in order to determine the name of the function. It's marginally trickier with objects that don't have a sane way to determine __name__, i.e. base/primitive objects like basestring instances, ints, longs, etc.
Long story short, you could probably use the inspect module to make an educated guess about which one it is, but you would have to probably know what frame you're working in/traverse down the stack to find the right one. But I'd hate to imagine how much fun this would be trying to deal with eval/exec'ed code.
% python2 whats_my_name_again.py
needle => ''b''
['a', 'b']
[]
needle => '<function foo at 0x289d08ec>'
['c']
['foo']
needle => '<function bar at 0x289d0bfc>'
['f', 'bar']
[]
needle => '<__main__.a_class instance at 0x289d3aac>'
['e', 'd']
[]
needle => '<function bar at 0x289d0bfc>'
['f', 'bar']
[]
%
whats_my_name_again.py:
#!/usr/bin/env python
import inspect
class a_class:
def __init__(self):
pass
def foo():
def bar():
pass
a = 'b'
b = 'b'
c = foo
d = a_class()
e = d
f = bar
#print('globals', inspect.stack()[0][0].f_globals)
#print('locals', inspect.stack()[0][0].f_locals)
assert(inspect.stack()[0][0].f_globals == globals())
assert(inspect.stack()[0][0].f_locals == locals())
in_a_haystack = lambda: value == needle and key != 'needle'
for needle in (a, foo, bar, d, f, ):
print("needle => '%r'" % (needle, ))
print([key for key, value in locals().iteritems() if in_a_haystack()])
print([key for key, value in globals().iteritems() if in_a_haystack()])
foo()
You define a class and add the Unicode private function insert the class like
class example:
def __init__(self, name):
self.name = name
def __unicode__(self):
return self.name
Of course you have to add extra variable self.name which is the name of the object.
Here is my answer, I am also using globals().items()
def get_name_of_obj(obj, except_word = ""):
for name, item in globals().items():
if item == obj and name != except_word:
return name
I added except_word because I want to filter off some word used in for loop.
If you didn't add it, the keyword in for loop may confuse this function, sometimes the keyword like "each_item" in the following case may show in the function's result, depends on what you have done to your loop.
eg.
for each_item in [objA, objB, objC]:
get_name_of_obj(obj, "each_item")
eg.
>>> objA = [1, 2, 3]
>>> objB = ('a', {'b':'thi is B'}, 'c')
>>> for each_item in [objA, objB]:
... get_name_of_obj(each_item)
...
'objA'
'objB'
>>>
>>>
>>> for each_item in [objA, objB]:
... get_name_of_obj(each_item)
...
'objA'
'objB'
>>>
>>>
>>> objC = [{'a1':'a2'}]
>>>
>>> for item in [objA, objB, objC]:
... get_name_of_obj(item)
...
'objA'
'item' <<<<<<<<<< --------- this is no good
'item'
>>> for item in [objA, objB]:
... get_name_of_obj(item)
...
'objA'
'item' <<<<<<<<--------this is no good
>>>
>>> for item in [objA, objB, objC]:
... get_name_of_obj(item, "item")
...
'objA'
'objB' <<<<<<<<<<--------- now it's ok
'objC'
>>>
Hope this can help.
Based on what it looks like you're trying to do you could use this approach.
In your case, your functions would all live in the module foo. Then you could:
import foo
func_name = parse_commandline()
method_to_call = getattr(foo, func_name)
result = method_to_call()
Or more succinctly:
import foo
result = getattr(foo, parse_commandline())()
Python has names which are mapped to objects in a hashmap called a namespace. At any instant in time, a name always refers to exactly one object, but a single object can be referred to by any arbitrary number of names. Given a name, it is very efficient for the hashmap to look up the single object which that name refers to. However given an object, which as mentioned can be referred to by multiple names, there is no efficient way to look up the names which refer to it. What you have to do is iterate through all the names in the namespace and check each one individually and see if it maps to your given object. This can easily be done with a list comprehension:
[k for k,v in locals().items() if v is myobj]
This will evaluate to a list of strings containing the names of all local "variables" which are currently mapped to the object myobj.
>>> a = 1
>>> this_is_also_a = a
>>> this_is_a = a
>>> b = "ligma"
>>> c = [2,3, 534]
>>> [k for k,v in locals().items() if v is a]
['a', 'this_is_also_a', 'this_is_a']
Of course locals() can be substituted with any dict that you want to search for names that point to a given object. Obviously this search can be slow for very large namespaces because they must be traversed in their entirety.
Hi there is one way to get the variable name that stores an instance of a class
is to use
locals()
function, it returns a dictionary that contains the variable name as a string and its value