get name of a variable or parameter
Pre C# 6.0 solution
You can use this to get a name of any provided member:
public static class MemberInfoGetting
{
public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
{
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
return expressionBody.Member.Name;
}
}
To get name of a variable:
string testVariable = "value";
string nameOfTestVariable = MemberInfoGetting.GetMemberName(() => testVariable);
To get name of a parameter:
public class TestClass
{
public void TestMethod(string param1, string param2)
{
string nameOfParam1 = MemberInfoGetting.GetMemberName(() => param1);
}
}
C# 6.0 and higher solution
You can use the nameof operator for parameters, variables and properties alike:
string testVariable = "value";
string nameOfTestVariable = nameof(testVariable);
Get a the name of the variable that was sent as a parameter
No, it's not possible. Variable names only exist in the scope of the method that declare them.
What is passed to the method is not the variable itself, but the value of the variable, so you can't access the name. And even in the case of ref
parameters, what is passed is the memory location of the variable, without its name.
Getting the calling variable name of a parameter
You can use a method which is taking an Expression<Func<object>>
as parameter:
public void WhatDoesTheAnimalSay_WANTED(Expression<Func<object>> expression)
{
var body = (MemberExpression)expression.Body;
var variableName = body.Member.Name;
var func = expression.Compile();
var variableValue = func();
MessageBox.Show("The "+ variableName + " says: " + variableValue);
}
Using this approach gives the ability to process a variety of variables (static members, instance members, parameters, local variables etc.), also properties are possible.
Call it like:
WhatDoesTheAnimalSay_WANTED(() => dog)
WhatDoesTheAnimalSay_WANTED(() => Cow)
WhatDoesTheAnimalSay_WANTED(() => Cat)
WhatDoesTheAnimalSay_WANTED(() => kiwi)
Constants are not possible, because the compiler will substitute the constant placeholder by its value, given at compile time:
const string constValue = "Constant Value";
WhatDoesTheAnimalSay_WANTED(() => constValue)
would be transformed to
WhatDoesTheAnimalSay_WANTED(() => "Constant Value")
making the expression.Body
of type ConstantExpression
, which would yield an exception at runtime.
So you have to be careful what you provide as expression to that method.
Additional Remarks
As you can notice from the comments below, the use of lambda expressions to gather variable names seems controversial.
As @CodeCaster pointed out in one of his comments, there is no officially specified need for the compiler to take the same name of a local variable for the captured member in the anonymous wrapping class.
However, I found this in the remarks of Expression<TDelegate>:
The ability to treat expressions as data structures enables APIs to receive user code in a format that can be inspected, transformed, and processed in a custom manner.
For me this is a sign that the expression trees are exactly designed for purposes like that.
Although it is possible that Microsoft changes this behavior for some reason, there does not seem to be a logical need for doing so. Relying on the principle of least astonishment I'd say it is safe to assume that for an expression from ()=> dog
whose Body
property is of type MemberExpression
, that body.Member.Name
resolves to dog.
If it is necessary to have other types for Body
also, the method has to be worked out a little bit more. And also it is possible that this will not work in certain circumstances anyways.
Getting the name of a variable as a string
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.
Get name of variable passed as function parameter
Perhaps decorate that variable with a "comment" attribute in another function? Note that the variable you want to decorate has to be wrapped directly in the decoration function z
; otherwise, an error is raised (by design and for robustness).
example_fun <- function(x){
attr(x, "comment")
}
z <- function(x) {
nm <- substitute(x)
nm <- as.character(
if (is.symbol(nm) && !identical(nm, quote(.))) {
nm
} else if (length(nm) > 1L && (identical(nm[[1L]], quote(`[[`)) || identical(nm[[1L]], quote(`$`)))) {
tail(nm, 1L)
} else {
stop("not a valid symbol or extract operator.", call. = match.call())
}
)
`comment<-`(x, nm)
}
Output
> example_fun(z(df$noi))
[1] "noi"
> z(df$noi) %>% (function(x) x + 1) %>% example_fun()
[1] "noi"
> df %>% mutate(example_fun(z(noi)))
noi example_fun(z(noi))
1 1 noi
2 2 noi
3 3 noi
> z(df[["noi"]]) %>% example_fun()
[1] "noi"
> with(df, z(noi)) %>% example_fun()
[1] "noi"
> z(with(df, noi)) %>% example_fun()
Error in z(with(df, noi)) : not a valid symbol or extract operator.
> df$noi %>% z()
Error in z(.) : not a valid symbol or extract operator.
... but this may not be a robust method. It is extremely difficult to achieve what you want in a robust way, especially when a pipeline is involved. I think you should read Hadley's Advanced R and learn more about how bindings and environments work.
How can i get the name of a variable name of a parameter in Java
I believe what you are asking for is more than the information placed on the stack by Java. The JVM has no reason to record the name of a variable when it takes the handle held by that variable and puts it into the stack to call a method. In fact, there's usually no real reason to preserve that name past compilation. If you can give more information about why you'd want to do such a thing you'll probably get more reasonable responses.
If what you wanted were possible, it would be via a StackTraceElement, but looking at the API, there's nothing like what you're asking for.
How to get the original variable name of variable passed to a function
You can't. It's evaluated before being passed to the function. All you can do is pass it as a string.
Related Topics
How to Convert HTML to Plain Text
What Is a Nullreferenceexception, and How to Fix It
How to Update the Gui from Another Thread
How to Convert a Byte Array to a Hexadecimal String, and Vice Versa
Serialize and Deserialize Json and Json Array in Unity
Deserialize Json into C# Dynamic Object
Difference Between a Field and a Property
How to Force My .Net Application to Run as Administrator
Await' Works, But Calling Task.Result Hangs/Deadlocks
The Located Assembly'S Manifest Definition Does Not Match the Assembly Reference
Protect .Net Code from Reverse Engineering