0

I'd like to know what the variable name was that was passed into a function. Is this possible in Python?

Consider this case:

john = 199

def foo(userId:int)->float:
   age = get_age_by_id(userId)
   return age

I'd like to log something like:

foo(john)

>>> Called with userId = 199 # john 

So, I am looking for a way to "peek" at the variable name that was passed as an argument to the function.

Any ideas?

Daniel Walker
  • 6,380
  • 5
  • 22
  • 45
MYK
  • 1,988
  • 7
  • 30

2 Answers2

4

Variable names are not passed into a function. Variable values are. Those values may or may not be conveyed via variables at the point of a given call, but if they are, the variable names are not part of the semantics of the call. That is, the names are not available to the code in the function.

It's unclear why you ask. If it's for debugging-related purposes then you are probably looking for a Python debugger. There are several, including pdb, which comes with Python. If it's because the function inherently requires a name to go along with the value, then you need to redesign the function to accept more or different parameters.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Thank you. I didn't really expect it to be possible, thank you for clarifying. I'm running ML experiments and I wanted to log the variable names in the MLFlow experiment tracker. In MLFlow you can't really log datasets, but you can log "ran with X_filtered_bound_on_90th_percentile" - It was a slight pain to pass the variable and the variable name separately. – MYK Jun 27 '22 at 14:24
  • My code looks like: ``` log_run(X_bool_filtered, y_relative_filtered < 0.2, scoring_function=totalScore(ind), run_name='''X_bool_filtered, y_relative_filtered < 0.2, scoring_function=totalScore(ind)''') ``` – MYK Jun 27 '22 at 14:25
  • 2
    @MYK, you could just set up another parameter to the function and pass there the "Metadata" you'd want logged, for example that exact text "X_filtered_bound_..." – artur99 Jun 27 '22 at 14:34
  • ... or, instead of passing a plain integer and a separate string, pass an instance of a class that encapsulates the integer together with the accompanying name. – John Bollinger Jun 27 '22 at 14:40
3

The closest thing to a solution is to inspect the stack and look for a variable with a matching value. Note that you can't actually know for certain which of those variables (if any) was the source of the value that your function received.

import inspect

def foo(age: int) -> None:
    caller_vars = [
        var
        for var, val in inspect.stack()[0].frame.f_back.f_locals.items()
        if val == age
    ]
    print(f"Called with {age} = {', '.join(caller_vars) or '???'}")

foo(199)   # Called with 199 = ???
john = 199
foo(john)  # Called with 199 = john
eric = 199
foo(john)  # Called with 199 = john, eric
Samwise
  • 68,105
  • 3
  • 30
  • 44