In Python how do I run an array of functions - python

Here is my problem I have a number of functions defined and I want to loop through a list of these functions and run them one at a time in the correct order.
def one():
print "One "
def two():
print "Two "
def three(): "Three "
print "Three "
arr = ('one','two','three')
for fnc in arr:
<some how run the function name in the variable fnc>
Any Help Appreciated, as I am a beginner with python and django.

Python functions are first order objects; just put them in the sequence:
arr = (one, two, three)
for fnc in arr:
fnc()
You could store strings too, but then you need to turn those back into the function object first. That'd just be extra busywork you don't really need to do.
You can still turn strings into objects; the globals() function gives you the current global namespace as a dictionary, so globals()['one'] gives you the object referenced by the name one, but this would also give you access to every global in your module; if you then made a mistake it could lead to hard to track bugs or even security holes (as end-users could potentially abuse functions you didn't intent to be called).
If you really need to map names to functions, because, say, you need to take input from something else that only produces strings, use a predefined dictionary:
functions = {
'one': one,
'two': two,
'three': three,
}
and map your string to the function:
function_to_call = 'one'
functions[function_to_call]()
Your function names do not need to match the string values here. By using a dedicated dictionary you limit what can be called.

It depends on where the functions are defined, but if they are in the current context, you can get a reference to them by retrieving them from the globals function:
def fn():
return ":)"
for f in['fn']:
print globals()[f]()

Seems to work...
method_name = 'one'
possibles = globals().copy()
possibles.update(locals())
method = possibles.get(method_name)
if not method:
raise Exception("Method %s not implemented" % method_name)
returned_value = method()

For your specific example, simply use eval:
arr = ('one','two','three')
for fnc in arr:
eval(fnc + '()')
Be aware that using eval() is considered bad practice by some.

Related

Trouble naming csv file I'm writing a dataframe to in pandas in Python [duplicate]

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.
>>> 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.
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
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.

Can I implement a function or better a decorator that makes func(a1)(a2)(a3)...(an) == func(a1, a2, a3,...,an)? [duplicate]

On Codewars.com I encountered the following task:
Create a function add that adds numbers together when called in succession. So add(1) should return 1, add(1)(2) should return 1+2, ...
While I'm familiar with the basics of Python, I've never encountered a function that is able to be called in such succession, i.e. a function f(x) that can be called as f(x)(y)(z).... Thus far, I'm not even sure how to interpret this notation.
As a mathematician, I'd suspect that f(x)(y) is a function that assigns to every x a function g_{x} and then returns g_{x}(y) and likewise for f(x)(y)(z).
Should this interpretation be correct, Python would allow me to dynamically create functions which seems very interesting to me. I've searched the web for the past hour, but wasn't able to find a lead in the right direction. Since I don't know how this programming concept is called, however, this may not be too surprising.
How do you call this concept and where can I read more about it?
I don't know whether this is function chaining as much as it's callable chaining, but, since functions are callables I guess there's no harm done. Either way, there's two ways I can think of doing this:
Sub-classing int and defining __call__:
The first way would be with a custom int subclass that defines __call__ which returns a new instance of itself with the updated value:
class CustomInt(int):
def __call__(self, v):
return CustomInt(self + v)
Function add can now be defined to return a CustomInt instance, which, as a callable that returns an updated value of itself, can be called in succession:
>>> def add(v):
... return CustomInt(v)
>>> add(1)
1
>>> add(1)(2)
3
>>> add(1)(2)(3)(44) # and so on..
50
In addition, as an int subclass, the returned value retains the __repr__ and __str__ behavior of ints. For more complex operations though, you should define other dunders appropriately.
As #Caridorc noted in a comment, add could also be simply written as:
add = CustomInt
Renaming the class to add instead of CustomInt also works similarly.
Define a closure, requires extra call to yield value:
The only other way I can think of involves a nested function that requires an extra empty argument call in order to return the result. I'm not using nonlocal and opt for attaching attributes to the function objects to make it portable between Pythons:
def add(v):
def _inner_adder(val=None):
"""
if val is None we return _inner_adder.v
else we increment and return ourselves
"""
if val is None:
return _inner_adder.v
_inner_adder.v += val
return _inner_adder
_inner_adder.v = v # save value
return _inner_adder
This continuously returns itself (_inner_adder) which, if a val is supplied, increments it (_inner_adder += val) and if not, returns the value as it is. Like I mentioned, it requires an extra () call in order to return the incremented value:
>>> add(1)(2)()
3
>>> add(1)(2)(3)() # and so on..
6
You can hate me, but here is a one-liner :)
add = lambda v: type("", (int,), {"__call__": lambda self, v: self.__class__(self + v)})(v)
Edit: Ok, how this works? The code is identical to answer of #Jim, but everything happens on a single line.
type can be used to construct new types: type(name, bases, dict) -> a new type. For name we provide empty string, as name is not really needed in this case. For bases (tuple) we provide an (int,), which is identical to inheriting int. dict are the class attributes, where we attach the __call__ lambda.
self.__class__(self + v) is identical to return CustomInt(self + v)
The new type is constructed and returned within the outer lambda.
If you want to define a function to be called multiple times, first you need to return a callable object each time (for example a function) otherwise you have to create your own object by defining a __call__ attribute, in order for it to be callable.
The next point is that you need to preserve all the arguments, which in this case means you might want to use Coroutines or a recursive function. But note that Coroutines are much more optimized/flexible than recursive functions, specially for such tasks.
Here is a sample function using Coroutines, that preserves the latest state of itself. Note that it can't be called multiple times since the return value is an integer which is not callable, but you might think about turning this into your expected object ;-).
def add():
current = yield
while True:
value = yield current
current = value + current
it = add()
next(it)
print(it.send(10))
print(it.send(2))
print(it.send(4))
10
12
16
Simply:
class add(int):
def __call__(self, n):
return add(self + n)
If you are willing to accept an additional () in order to retrieve the result you can use functools.partial:
from functools import partial
def add(*args, result=0):
return partial(add, result=sum(args)+result) if args else result
For example:
>>> add(1)
functools.partial(<function add at 0x7ffbcf3ff430>, result=1)
>>> add(1)(2)
functools.partial(<function add at 0x7ffbcf3ff430>, result=3)
>>> add(1)(2)()
3
This also allows specifying multiple numbers at once:
>>> add(1, 2, 3)(4, 5)(6)()
21
If you want to restrict it to a single number you can do the following:
def add(x=None, *, result=0):
return partial(add, result=x+result) if x is not None else result
If you want add(x)(y)(z) to readily return the result and be further callable then sub-classing int is the way to go.
The pythonic way to do this would be to use dynamic arguments:
def add(*args):
return sum(args)
This is not the answer you're looking for, and you may know this, but I thought I would give it anyway because if someone was wondering about doing this not out of curiosity but for work. They should probably have the "right thing to do" answer.

Getting the name of a variable as a string

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.

Switch in Python [duplicate]

This question already has answers here:
Replacements for switch statement in Python?
(44 answers)
Closed 27 days ago.
I have tried making a switch like statement in python, instead of having a lot of if statements.
The code looks like this:
def findStuff(cds):
L=[]
c=0
for i in range(0, len(cds), 3):
a=differencesTo(cds[i:i+3])
result = {
a[2][0]==1: c=i+1,
a[2][1]==1: c=i+2,
a[2][2]==1: c=i+3,
a[1]==1: L.append((cds[i:i+3], a[0], c))
}
return L
My problem is, that this does not work. (Works with if statements, but this would in my opinion be more pretty).
I have found some examples of switches in Python, and they follow this structure. Can anyone help me?
(a) I fail to see what is wrong with if...elif...else
(b) I assume that python does not have a switch statement for the same reason that Smalltalk doesn't: it's almost completely redundant, and in the case where you want to switch on types, you can add an appropriate method to your classes; and likewise switching on values should be largely redundant.
Note: I am informed in the comments that whatever Guido's reason for not creating a switch in the first place, PEPs to have it added were rejected on the basis that support for adding such a statement is extremely limited. See: http://www.python.org/dev/peps/pep-3103/
(c) If you really need switching behaviour, use a hashtable (dict) to store callables. The structure is:
switch_dict = {
Foo: self.doFoo,
Bar: self.doBar,
}
func = switch_dict[switch_var]
result = func() # or if they take args, pass args
There's nothing wrong with a long if:
if switch == 'case0':
do_case0()
elif switch == 'case1':
do_case1()
elif switch == 'case2':
do_case2()
...
If that's too long winded, or if you have a lot of cases, put them in a dictionary:
switch = {'case0': do_case0, 'case1': do_case1, 'case2': do_case2, ...}
switch[case_variable]()
// Alternative:
(switch[case_variable]).__call__()
If your conditions are a bit more complex, you need to think a little about your data structures. e.g.:
switch = {
(0,21): 'never have a pension',
(21,50): 'might have a pension',
(50,65): 'definitely have a pension',
(65, 200): 'already collecting pension'
}
for key, value in switch.items():
if key[0] <= case_var < key[1]:
print(value)
Other ans are suitable for older version of python. For python v3.10+ you can use match/case which is more powerful than general switch/case construct.
def something(val):
match val:
case "A":
return "A"
case "B":
return "B"
case "C":
return "C"
case _:
return "Default"
something("A")
Assignment in Python is a statement, and cannot be a part of expression. Also, using literal in this way evaluates everything at once, which is probably not what you want. Just use ifs, you won't gain any readability by using this.
I don't know which article you've found to do something like this, but this is really messy: the whole result diction will be always evaluated, and instead of doing only part of the work (as a switch / if do), you'll do the whole work everytime. (even if you use only a part of the result).
Really, a fast switch statement in Python is using "if":
if case == 1:
pass
elif case == 2:
pass
elif case == 3:
pass
else:
# default case
pass
With "get" method, you can have the same effect as "switch..case" in C.
Marcin example :
switch_dict = {
Foo: self.doFoo,
Bar: self.doBar,
}
func = switch_dict.get(switch_var, self.dodefault)
result = func() # or if they take args, pass args
You can do something like what you want, but you shouldn't. That said, here's how; you can see how it does not improve things.
The biggest problem with the way you have it is that Python will evaluate your tests and results once, at the time you declare the dictionary. What you'd have to do instead is make all conditions and the resulting statements functions; this way, evaluation is deferred until you call them. Fortunately there is a way to do this inline for simple functions using the lambda keyword. Secondly, the assignment statement can't be used as a value in Python, so our action functions (which are executed if the corresponding condition function returns a truthy value) have to return a value that will be used to increment c; they can't assign to c themselves.
Also, the items in a dictionary aren't ordered, so your tests won't necessarily be performed in the order you define them, meaning you probably should use something other than a dictionary that preserves order, such as a tuple or a list. I am assuming you want only ever one case to execute.
So, here we go:
def findStuff(cds):
cases = [ (lambda: a[2][0] == 1, lambda: i + 1),
(lambda: a[2][1] == 1, lambda: i + 2),
(lambda: a[2][2] == 1, lambda: i + 3),
(lambda: a[1] == 1, lambda: L.append(cds[i:i+3], a[0], c) or 0)
]
L=[]
c=0
for i in range(0, len(cds), 3):
a=differencesTo(cds[i:i+3])
for condition, action in cases:
if condition():
c += action()
break
return L
Is this more readable than a sequence of if/elif statements? Nooooooooooooo. In particular, the fourth case is far less comprehensible than it should be because we are having to rely on a function that returns the increment for c to modify a completely different variable, and then we have to figure out how to get it to return a 0 so that c won't actually be modified. Uuuuuugly.
Don't do this. In fact this code probably won't even run as-is, as I deemed it too ugly to test.
While there is nothing wrong with if..else, I find "switch in Python" still an intriguing problem statement. On that, I think Marcin's (deprecated) option (c) and/or Snim2's second variant can be written in a more readable way.
For this we can declare a switch class, and exploit the __init__() to declare the case we want to switch, while __call__() helps to hand over a dict listing the (case, function) pairs:
class switch(object):
def __init__(self, case):
self._case = case
def __call__(self, dict_):
try:
return dict_[self._case]()
except KeyError:
if 'else' in dict_:
return dict_['else']()
raise Exception('Given case wasn\'t found.')
Or, respectively, since a class with only two methods, of which one is __init__(), isn't really a class:
def switch(case):
def cases(dict_):
try:
return dict_[case]()
except KeyError:
if 'else' in dict_:
return dict_['else']()
raise Exception('Given case wasn\'t found.')
return cases
(note: choose something smarter than Exception)
With for example
def case_a():
print('hello world')
def case_b():
print('sth other than hello')
def default():
print('last resort')
you can call
switch('c') ({
'a': case_a,
'b': case_b,
'else': default
})
which, for this particular example would print
last resort
This doesn't behave like a C switch in that there is no break for the different cases, because each case executes only the function declared for the particular case (i.e. break is implicitly always called). Secondly, each case can list exactly only one function that will be executed upon a found case.

Convert Variable Name to String?

I would like to convert a python variable name into the string equivalent as shown. Any ideas how?
var = {}
print ??? # Would like to see 'var'
something_else = 3
print ??? # Would print 'something_else'
TL;DR: Not possible. See 'conclusion' at the end.
There is an usage scenario where you might need this. I'm not implying there are not better ways or achieving the same functionality.
This would be useful in order to 'dump' an arbitrary list of dictionaries in case of error, in debug modes and other similar situations.
What would be needed, is the reverse of the eval() function:
get_indentifier_name_missing_function()
which would take an identifier name ('variable','dictionary',etc) as an argument, and return a
string containing the identifier’s name.
Consider the following current state of affairs:
random_function(argument_data)
If one is passing an identifier name ('function','variable','dictionary',etc) argument_data to a random_function() (another identifier name), one actually passes an identifier (e.g.: <argument_data object at 0xb1ce10>) to another identifier (e.g.: <function random_function at 0xafff78>):
<function random_function at 0xafff78>(<argument_data object at 0xb1ce10>)
From my understanding, only the memory address is passed to the function:
<function at 0xafff78>(<object at 0xb1ce10>)
Therefore, one would need to pass a string as an argument to random_function() in order for that function to have the argument's identifier name:
random_function('argument_data')
Inside the random_function()
def random_function(first_argument):
, one would use the already supplied string 'argument_data' to:
serve as an 'identifier name' (to display, log, string split/concat, whatever)
feed the eval() function in order to get a reference to the actual identifier, and therefore, a reference to the real data:
print("Currently working on", first_argument)
some_internal_var = eval(first_argument)
print("here comes the data: " + str(some_internal_var))
Unfortunately, this doesn't work in all cases. It only works if the random_function() can resolve the 'argument_data' string to an actual identifier. I.e. If argument_data identifier name is available in the random_function()'s namespace.
This isn't always the case:
# main1.py
import some_module1
argument_data = 'my data'
some_module1.random_function('argument_data')
# some_module1.py
def random_function(first_argument):
print("Currently working on", first_argument)
some_internal_var = eval(first_argument)
print("here comes the data: " + str(some_internal_var))
######
Expected results would be:
Currently working on: argument_data
here comes the data: my data
Because argument_data identifier name is not available in the random_function()'s namespace, this would yield instead:
Currently working on argument_data
Traceback (most recent call last):
File "~/main1.py", line 6, in <module>
some_module1.random_function('argument_data')
File "~/some_module1.py", line 4, in random_function
some_internal_var = eval(first_argument)
File "<string>", line 1, in <module>
NameError: name 'argument_data' is not defined
Now, consider the hypotetical usage of a get_indentifier_name_missing_function() which would behave as described above.
Here's a dummy Python 3.0 code: .
# main2.py
import some_module2
some_dictionary_1 = { 'definition_1':'text_1',
'definition_2':'text_2',
'etc':'etc.' }
some_other_dictionary_2 = { 'key_3':'value_3',
'key_4':'value_4',
'etc':'etc.' }
#
# more such stuff
#
some_other_dictionary_n = { 'random_n':'random_n',
'etc':'etc.' }
for each_one_of_my_dictionaries in ( some_dictionary_1,
some_other_dictionary_2,
...,
some_other_dictionary_n ):
some_module2.some_function(each_one_of_my_dictionaries)
# some_module2.py
def some_function(a_dictionary_object):
for _key, _value in a_dictionary_object.items():
print( get_indentifier_name_missing_function(a_dictionary_object) +
" " +
str(_key) +
" = " +
str(_value) )
######
Expected results would be:
some_dictionary_1 definition_1 = text_1
some_dictionary_1 definition_2 = text_2
some_dictionary_1 etc = etc.
some_other_dictionary_2 key_3 = value_3
some_other_dictionary_2 key_4 = value_4
some_other_dictionary_2 etc = etc.
......
......
......
some_other_dictionary_n random_n = random_n
some_other_dictionary_n etc = etc.
Unfortunately, get_indentifier_name_missing_function() would not see the 'original' identifier names (some_dictionary_,some_other_dictionary_2,some_other_dictionary_n). It would only see the a_dictionary_object identifier name.
Therefore the real result would rather be:
a_dictionary_object definition_1 = text_1
a_dictionary_object definition_2 = text_2
a_dictionary_object etc = etc.
a_dictionary_object key_3 = value_3
a_dictionary_object key_4 = value_4
a_dictionary_object etc = etc.
......
......
......
a_dictionary_object random_n = random_n
a_dictionary_object etc = etc.
So, the reverse of the eval() function won't be that useful in this case.
Currently, one would need to do this:
# main2.py same as above, except:
for each_one_of_my_dictionaries_names in ( 'some_dictionary_1',
'some_other_dictionary_2',
'...',
'some_other_dictionary_n' ):
some_module2.some_function( { each_one_of_my_dictionaries_names :
eval(each_one_of_my_dictionaries_names) } )
# some_module2.py
def some_function(a_dictionary_name_object_container):
for _dictionary_name, _dictionary_object in a_dictionary_name_object_container.items():
for _key, _value in _dictionary_object.items():
print( str(_dictionary_name) +
" " +
str(_key) +
" = " +
str(_value) )
######
In conclusion:
Python passes only memory addresses as arguments to functions.
Strings representing the name of an identifier, can only be referenced back to the actual identifier by the eval() function if the name identifier is available in the current namespace.
A hypothetical reverse of the eval() function, would not be useful in cases where the identifier name is not 'seen' directly by the calling code. E.g. inside any called function.
Currently one needs to pass to a function:
the string representing the identifier name
the actual identifier (memory address)
This can be achieved by passing both the 'string' and eval('string') to the called function at the same time. I think this is the most 'general' way of solving this egg-chicken problem across arbitrary functions, modules, namespaces, without using corner-case solutions. The only downside is the use of the eval() function which may easily lead to unsecured code. Care must be taken to not feed the eval() function with just about anything, especially unfiltered external-input data.
Totally possible with the python-varname package (python3):
from varname import nameof
s = 'Hey!'
print (nameof(s))
Output:
s
Install:
pip3 install varname
Or get the package here:
https://github.com/pwwang/python-varname
I searched for this question because I wanted a Python program to print assignment statements for some of the variables in the program. For example, it might print "foo = 3, bar = 21, baz = 432". The print function would need the variable names in string form. I could have provided my code with the strings "foo","bar", and "baz", but that felt like repeating myself. After reading the previous answers, I developed the solution below.
The globals() function behaves like a dict with variable names (in the form of strings) as keys. I wanted to retrieve from globals() the key corresponding to the value of each variable. The method globals().items() returns a list of tuples; in each tuple the first item is the variable name (as a string) and the second is the variable value. My variablename() function searches through that list to find the variable name(s) that corresponds to the value of the variable whose name I need in string form.
The function itertools.ifilter() does the search by testing each tuple in the globals().items() list with the function lambda x: var is globals()[x[0]]. In that function x is the tuple being tested; x[0] is the variable name (as a string) and x[1] is the value. The lambda function tests whether the value of the tested variable is the same as the value of the variable passed to variablename(). In fact, by using the is operator, the lambda function tests whether the name of the tested variable is bound to the exact same object as the variable passed to variablename(). If so, the tuple passes the test and is returned by ifilter().
The itertools.ifilter() function actually returns an iterator which doesn't return any results until it is called properly. To get it called properly, I put it inside a list comprehension [tpl[0] for tpl ... globals().items())]. The list comprehension saves only the variable name tpl[0], ignoring the variable value. The list that is created contains one or more names (as strings) that are bound to the value of the variable passed to variablename().
In the uses of variablename() shown below, the desired string is returned as an element in a list. In many cases, it will be the only item in the list. If another variable name is assigned the same value, however, the list will be longer.
>>> def variablename(var):
... import itertools
... return [tpl[0] for tpl in
... itertools.ifilter(lambda x: var is x[1], globals().items())]
...
>>> var = {}
>>> variablename(var)
['var']
>>> something_else = 3
>>> variablename(something_else)
['something_else']
>>> yet_another = 3
>>> variablename(something_else)
['yet_another', 'something_else']
as long as it's a variable and not a second class, this here works for me:
def print_var_name(variable):
for name in globals():
if eval(name) == variable:
print name
foo = 123
print_var_name(foo)
>>>foo
this happens for class members:
class xyz:
def __init__(self):
pass
member = xyz()
print_var_name(member)
>>>member
ans this for classes (as example):
abc = xyz
print_var_name(abc)
>>>abc
>>>xyz
So for classes it gives you the name AND the properteries
This is not possible.
In Python, there really isn't any such thing as a "variable". What Python really has are "names" which can have objects bound to them. It makes no difference to the object what names, if any, it might be bound to. It might be bound to dozens of different names, or none.
Consider this example:
foo = 1
bar = 1
baz = 1
Now, suppose you have the integer object with value 1, and you want to work backwards and find its name. What would you print? Three different names have that object bound to them, and all are equally valid.
In Python, a name is a way to access an object, so there is no way to work with names directly. There might be some clever way to hack the Python bytecodes or something to get the value of the name, but that is at best a parlor trick.
If you know you want print foo to print "foo", you might as well just execute print "foo" in the first place.
EDIT: I have changed the wording slightly to make this more clear. Also, here is an even better example:
foo = 1
bar = foo
baz = foo
In practice, Python reuses the same object for integers with common values like 0 or 1, so the first example should bind the same object to all three names. But this example is crystal clear: the same object is bound to foo, bar, and baz.
Technically the information is available to you, but as others have asked, how would you make use of it in a sensible way?
>>> x = 52
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__',
'x': 52, '__doc__': None, '__package__': None}
This shows that the variable name is present as a string in the globals() dictionary.
>>> globals().keys()[2]
'x'
In this case it happens to be the third key, but there's no reliable way to know where a given variable name will end up
>>> for k in globals().keys():
... if not k.startswith("_"):
... print k
...
x
>>>
You could filter out system variables like this, but you're still going to get all of your own items. Just running that code above created another variable "k" that changed the position of "x" in the dict.
But maybe this is a useful start for you. If you tell us what you want this capability for, more helpful information could possibly be given.
By using the the unpacking operator:
>>> def tostr(**kwargs):
return kwargs
>>> var = {}
>>> something_else = 3
>>> tostr(var = var,something_else=something_else)
{'var' = {},'something_else'=3}
You somehow have to refer to the variable you want to print the name of. So it would look like:
print varname(something_else)
There is no such function, but if there were it would be kind of pointless. You have to type out something_else, so you can as well just type quotes to the left and right of it to print the name as a string:
print "something_else"
What are you trying to achieve? There is absolutely no reason to ever do what you describe, and there is likely a much better solution to the problem you're trying to solve..
The most obvious alternative to what you request is a dictionary. For example:
>>> my_data = {'var': 'something'}
>>> my_data['something_else'] = 'something'
>>> print my_data.keys()
['var', 'something_else']
>>> print my_data['var']
something
Mostly as a.. challenge, I implemented your desired output. Do not use this code, please!
#!/usr/bin/env python2.6
class NewLocals:
"""Please don't ever use this code.."""
def __init__(self, initial_locals):
self.prev_locals = list(initial_locals.keys())
def show_new(self, new_locals):
output = ", ".join(list(set(new_locals) - set(self.prev_locals)))
self.prev_locals = list(new_locals.keys())
return output
# Set up
eww = None
eww = NewLocals(locals())
# "Working" requested code
var = {}
print eww.show_new(locals()) # Outputs: var
something_else = 3
print eww.show_new(locals()) # Outputs: something_else
# Further testing
another_variable = 4
and_a_final_one = 5
print eww.show_new(locals()) # Outputs: another_variable, and_a_final_one
Does Django not do this when generating field names?
http://docs.djangoproject.com/en/dev//topics/db/models/#verbose-field-names
Seems reasonable to me.
I think this is a cool solution and I suppose the best you can get. But do you see any way to handle the ambigious results, your function may return?
As "is" operator behaves unexpectedly with integers shows, low integers and strings of the same value get cached by python so that your variablename-function might priovide ambigous results with a high probability.
In my case, I would like to create a decorator, that adds a new variable to a class by the varialbename i pass it:
def inject(klass, dependency):
klass.__dict__["__"+variablename(dependency)]=dependency
But if your method returns ambigous results, how can I know the name of the variable I added?
var any_var="myvarcontent"
var myvar="myvarcontent"
#inject(myvar)
class myclasss():
def myclass_method(self):
print self.__myvar #I can not be sure, that this variable will be set...
Maybe if I will also check the local list I could at least remove the "dependency"-Variable from the list, but this will not be a reliable result.
Here is a succinct variation that lets you specify any directory.
The issue with using directories to find anything is that multiple variables can have the same value. So this code returns a list of possible variables.
def varname( var, dir=locals()):
return [ key for key, val in dir.items() if id( val) == id( var)]
I don't know it's right or not, but it worked for me
def varname(variable):
for name in list(globals().keys()):
expression = f'id({name})'
if id(variable) == eval(expression):
return name
it is possible to a limited extent. the answer is similar to the solution by #tamtam .
The given example assumes the following assumptions -
You are searching for a variable by its value
The variable has a distinct value
The value is in the global namespace
Example:
testVar = "unique value"
varNameAsString = [k for k,v in globals().items() if v == "unique value"]
#
# the variable "varNameAsString" will contain all the variable name that matches
# the value "unique value"
# for this example, it will be a list of a single entry "testVar"
#
print(varNameAsString)
Output : ['testVar']
You can extend this example for any other variable/data type
I'd like to point out a use case for this that is not an anti-pattern, and there is no better way to do it.
This seems to be a missing feature in python.
There are a number of functions, like patch.object, that take the name of a method or property to be patched or accessed.
Consider this:
patch.object(obj, "method_name", new_reg)
This can potentially start "false succeeding" when you change the name of a method. IE: you can ship a bug, you thought you were testing.... simply because of a bad method name refactor.
Now consider: varname. This could be an efficient, built-in function. But for now it can work by iterating an object or the caller's frame:
Now your call can be:
patch.member(obj, obj.method_name, new_reg)
And the patch function can call:
varname(var, obj=obj)
This would: assert that the var is bound to the obj and return the name of the member. Or if the obj is not specified, use the callers stack frame to derive it, etc.
Could be made an efficient built in at some point, but here's a definition that works. I deliberately didn't support builtins, easy to add tho:
Feel free to stick this in a package called varname.py, and use it in your patch.object calls:
patch.object(obj, varname(obj, obj.method_name), new_reg)
Note: this was written for python 3.
import inspect
def _varname_dict(var, dct):
key_name = None
for key, val in dct.items():
if val is var:
if key_name is not None:
raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
key_name = key
return key_name
def _varname_obj(var, obj):
key_name = None
for key in dir(obj):
val = getattr(obj, key)
equal = val is var
if equal:
if key_name is not None:
raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
key_name = key
return key_name
def varname(var, obj=None):
if obj is None:
if hasattr(var, "__self__"):
return var.__name__
caller_frame = inspect.currentframe().f_back
try:
ret = _varname_dict(var, caller_frame.f_locals)
except NameError:
ret = _varname_dict(var, caller_frame.f_globals)
else:
ret = _varname_obj(var, obj)
if ret is None:
raise NameError("Name not found. (Note: builtins not supported)")
return ret
This will work for simnple data types (str, int, float, list etc.)
>>> def my_print(var_str) :
print var_str+':', globals()[var_str]
>>> a = 5
>>> b = ['hello', ',world!']
>>> my_print('a')
a: 5
>>> my_print('b')
b: ['hello', ',world!']
It's not very Pythonesque but I was curious and found this solution. You need to duplicate the globals dictionary since its size will change as soon as you define a new variable.
def var_to_name(var):
# noinspection PyTypeChecker
dict_vars = dict(globals().items())
var_string = None
for name in dict_vars.keys():
if dict_vars[name] is var:
var_string = name
break
return var_string
if __name__ == "__main__":
test = 3
print(f"test = {test}")
print(f"variable name: {var_to_name(test)}")
which returns:
test = 3
variable name: test
To get the variable name of var as a string:
var = 1000
var_name = [k for k,v in locals().items() if v == var][0]
print(var_name) # ---> outputs 'var'
Thanks #restrepo, this was exactly what I needed to create a standard save_df_to_file() function. For this, I made some small changes to your tostr() function. Hope this will help someone else:
def variabletostr(**df):
variablename = list(df.keys())[0]
return variablename
variabletostr(df=0)
The original question is pretty old, but I found an almost solution with Python 3. (I say almost because I think you can get close to a solution but I do not believe there is a solution concrete enough to satisfy the exact request).
First, you might want to consider the following:
objects are a core concept in Python, and they may be assigned a variable, but the variable itself is a bound name (think pointer or reference) not the object itself
var is just a variable name bound to an object and that object could have more than one reference (in your example it does not seem to)
in this case, var appears to be in the global namespace so you can use the global builtin conveniently named global
different name references to the same object will all share the same id which can be checked by running the id builtin id like so: id(var)
This function grabs the global variables and filters out the ones matching the content of your variable.
def get_bound_names(target_variable):
'''Returns a list of bound object names.'''
return [k for k, v in globals().items() if v is target_variable]
The real challenge here is that you are not guaranteed to get back the variable name by itself. It will be a list, but that list will contain the variable name you are looking for. If your target variable (bound to an object) is really the only bound name, you could access it this way:
bound_names = get_variable_names(target_variable)
var_string = bound_names[0]
Possible for Python >= 3.8 (with f'{var=}' string )
Not sure if this could be used in production code, but in Python 3.8(and up) you can use f' string debugging specifier. Add = at the end of an expression, and it will print both the expression and its value:
my_salary_variable = 5000
print(f'{my_salary_variable = }')
Output:
my_salary_variable = 5000
To uncover this magic here is another example:
param_list = f'{my_salary_variable=}'.split('=')
print(param_list)
Output:
['my_salary_variable', '5000']
Explanation: when you put '=' after your var in f'string, it returns a string with variable name, '=' and its value. Split it with .split('=') and get a List of 2 strings, [0] - your_variable_name, and [1] - actual object of variable.
Pick up [0] element of the list if you need variable name only.
my_salary_variable = 5000
param_list = f'{my_salary_variable=}'.split('=')
print(param_list[0])
Output:
my_salary_variable
or, in one line
my_salary_variable = 5000
print(f'{my_salary_variable=}'.split('=')[0])
Output:
my_salary_variable
Works with functions too:
def my_super_calc_foo(number):
return number**3
print(f'{my_super_calc_foo(5) = }')
print(f'{my_super_calc_foo(5)=}'.split('='))
Output:
my_super_calc_foo(5) = 125
['my_super_calc_foo(5)', '125']
Process finished with exit code 0
This module works for converting variables names to a string:
https://pypi.org/project/varname/
Use it like this:
from varname import nameof
variable=0
name=nameof(variable)
print(name)
//output: variable
Install it by:
pip install varname
print "var"
print "something_else"
Or did you mean something_else?

Categories

Resources