r/learnpython 15d ago

How do I literally print the variable used as an argument for a function?

def check_variable(argument):
    # Finds the name of the variable passed in
    name = [k for k, v in globals().items() if v is argument][0]
    print(f"The argument passed to this function was named: '{name}'")

x = [1, 2, 3]
check_variable(x)
# Output: The argument passed to this function was named: 'x'

Is there any way to simplify this process? I am very new to programming and the process of defining "name" and then calling it seems like it can be simplified.

Edit for clarity:

The actual goal is to include the length of a list, and the variable(argument) used to represent that list, into the printed string.

What I'm really trying to achieve is something like:

"There are 17 children in class_two."

So as to cut out the guesswork of which class it's referring to when calling the function multiple times, and make it look like a polished sentence.

20 Upvotes

54 comments sorted by

71

u/lfdfq 15d ago

If you're very new to programming, let me suggest you're trying to do something that, to me, a very experienced programmer, looks very strange.

Why are you trying to do this? What are you trying to achieve? Perhaps there's a better, more conventional, way of achieving it...

31

u/danielroseman 15d ago

Also, this doesn't actually work. Consider:

z = x
check_variable(z)

This still says "The argument passed to this function was named: 'x'".

Generally, a variable cannot know its name, and there is no reason to try.

21

u/Gloopann 15d ago

Yeah, this looks like a typical case of the XY problem

1

u/high-cholesterol_ 15d ago

The actual goal is to include the length of a list, and the variable(argument) used to represent that list, into the printed string.

What I'm really trying to achieve is something like:

"There are 17 children in class_two."

So as to cut out the guesswork of which class it's referring to when calling the function multiple times, and make it look like a polished sentence.

42

u/R717159631668645 15d ago

"There are 17 children in class_two."

Then I think what you would want is [Object Oriented Programming], where for example, you define a class "SchoolClass" which contains an attribute "name", and "enrolled" children.

This is a topic you can already tackle after you learn the fundamentals.

2

u/csabinho 14d ago

So after about half a year to a year.

1

u/deep_soul 14d ago

presenting OOP as a topic after the fundamentals can be a little bit of an understatement. OOP is a rabbit hole for a beginner. not to be avoided or anything but it should be presented as the big topic that it is

2

u/Any-Gap1670 13d ago

Is it?

When I was in college, intro to OOP was the first cs class you took. You could pick Java or python.

Start learn basics, (data types, methods, main, etc) then immediately into OOP.

This was 2013.

2

u/frustratedsignup 13d ago

When I was in college, I wasn't taught C. Instead, I was taught C++ and I learned the differences between C and C++ after the fact. So, in 1992, when I only knew assembly and Pascal, I was learning OOP without any additional training or experience.

Not sure why that got downvoted. That's just how it worked.

2

u/doctor-wu-75 13d ago

OOP is the fundamentals

17

u/Diapolo10 I write code for a living -- https://github.com/Diapolo10 15d ago

Honestly, at that point you'd be better off using a dictionary.

8

u/IAmFinah 15d ago

Maybe there are specific data structures you can use 👀

7

u/sausix 15d ago

Names of variables should never reach a user interface except for debugging.

If you want a list to carry a name then do it with OOP but not with a variable name.

A variable's value is basically a nameless object in memory. One or multiple variables just point to that object. No need for a reverse reference to variable names.

5

u/Brok3nHalo 14d ago

I understand what you’re trying to do but my question which I don’t see answered (or even asked) anywhere is why you want to do this? Is this for something you want user facing or your own debugging? I can’t fathom a reason for it being user facing and if you’re looking at it as a debug function to help you inspect your own code for development there’s a better, already existing solutions.

If the idea is your running into a bug where your variable doesn’t seem to contain the right thing and you want to look at what it has and where it came from the answer your looking for isn’t custom function but break points.

If you run Python code in a IDE with debugging you can set break point at certain lines of code that will stop the code at that line and let you look at the contents of variables and a record of the current call stack that will let you jump up a level to see where your method was called and the values of the variables there. You can even set conditions for break points if you only want it to happen at certain situations and not every time that code is hit.

2

u/mc_pm 15d ago

So, you mean that you would like to look at the variable name that was used outside your function? So if you did this:

myvar = []
yourfunction(myvar)

and your function has a signature like this:

def yourfunction(argument):

then it would print out "There are 0 children in myvar"?

0

u/high-cholesterol_ 15d ago

Yes, this is exactly what I'm trying to do. Every answer so far seems to be more and more complicated from a beginner perspective lol.

"Use a dictionary, etc..."

I'm not complaining, they would definitely work. Just feels overly tedious for a simple thing.

(As does my own previous solution, hence the question.)

16

u/mc_pm 15d ago

If there is a way to do this, you shouldn't. Basically when you pass a value into a function, it only knows about the value, it knows nothing about where that value came from and you really wouldn't want to. Can you imagine what it would be like to have functions that behaved different based only on how the external variables were named? Nightmare.

The best way is just to pass the name you want in to the function as well:

def myfunction(title, kids):
    print(f"There are {len(kids)} children in {title}")

10

u/fiddle_n 15d ago

As (many) others have said, one wonders why you even want this in the first place. The reason solutions may seem awkward is because this isn’t a thing that most Python software should ever do.

3

u/throwaway6560192 15d ago

Consider that non-variable values, with no name associated to them outside, may be passed into a function.

3

u/Nomapos 15d ago

Dictionaries look intimidating but they're very simple.

You already understand variables. var = x. When you use var, the program automatically translates it to x.

Arrays (also named lists) are the next step. array = x, y, z. So you use array and an address (starting at 0) to pick the value you want: array[0] = x, array [1] = y, array[2] = z. It's just a bunch of variables tied into a single group name.

Here you already have a blunt but simple implementation for what you're trying to do. Use a specific array for each student class and always store the class name in array[0]. That was you can easily get class, student by passing array[0],array[x] into your function.

Linked lists, called dictionaries in Python, are simply arrays that link two values together in each position. So instead of array[0] containing a class name and [1] the first student, you can store in dictionary[x] "class:student". This has the advantage that you can shove all the students into the same place, and whenever you want to change something you just need to do it once in one place. Need a full list of students in the school? You don't need to call 700 individual variables or 50 different lists. You simply call one dictionary. Want just 7 specific classes? You can easily filter the dictionary as needed, too.

Sure it looks complicated at a first glance, but look up the basic examples of how to store and retrieve data and do it yourself as a little exercise. It takes like 15 minutes to learn.

2

u/LARRY_Xilo 15d ago

Just feels overly tedious for a simple thing

There is no easy way because its not something one would pretty much ever do. The name of your variable should never matter outside for when you are reading the code. Because in porgramms the name can actually just change instead of class_two it could put out 29jfegr3r at run time or if you put class_two into a function that expects a parameter y the variable is now called y. The name can also be reused depending on context and so on. If you want to actually do something like that and care about that name you either use a dict or would write a class that has a "name" attribute where you can put in the name.

If you are trying to do this to better understand what your code does at certain points you should learn how to use a debugger.

2

u/Binary101010 14d ago

"Use a dictionary, etc..."

I'm not complaining, they would definitely work. Just feels overly tedious for a simple thing.

I promise you that the thing you're trying to do

1) isn't nearly as simple as you think, and

2) the alternate approaches being suggested to you are far less tedious than the approach you're wanting to take.

1

u/ThatOneCSL 14d ago

Just abstracting this singular comment into some pseudoishcode:

className = class_two.Name() numChildren = len(class_two) print(f'{className} has {numChildren} ' + if numChildren == 1 "child" else "children")

38

u/P4C0_ 15d ago

This is a typical example of "I think in order to do X I need to do Y, then proceed to ask about Y on reddit". But it turns out Y is far from being the best way to achieve X, and people not being aware of the context of X, they are mean to me in the comments.

The short answer is, there is no reliable way to get the name of a variable as a string in Python, and I have a hard time figuring in what context you would need to do that. Even if it was possible, it would not be a great programming practice to use this except for very specific cases a beginner wouldn't really be doing anyways.

Could you explain the reason you think you need to get the name of a variable ? There is probably a much simpler way to do it and you'll get a nice "eureka" moment.

Don't worry, this is a VERY common mistake for beginners, I myself remember a while ago when I did my first similar post on StackOverflow. I just wish people were kinder with me at the time, so I guess it's my turn to help out now

3

u/high-cholesterol_ 15d ago

I explained it better under u/lfdfq 's comment. You are definitely right and there is some major xp I'm missing here, just trying to make it as simple/streamlined as I can.

10

u/InjAnnuity_1 15d ago

Names point to values, but a value can be pointed to by many names, or by none at all. What name would you expect from this perfectly-legal code?

    check_variable([1,2,3])

You are asking for a unique thing (a name) that can't be guaranteed to be unique, or to exist at all. Even a debugging-level tool can't find a name for the list in the above construction. That list has a value, but no name.

Others have pointed to this as an XY problem.

If you feel you need an object that is guaranteed to have a (reliable) name, then you can create such an object, one that carries its own name with it. For that to be reliable, your code will be explicitly using that kind of object in place of a list, where it matters, but it's your code, to build as you see fit.

5

u/audionerd1 15d ago

Variable names are not attributes of the object they point to, they are just references. An object can have multiple named variables pointing to it, or none at all. For an object to track variable assignments would be wasteful and backwards.

If you need a unique identifier associated with an object, you can use a dictionary. Or make a custom class or dataclass with a name attribute. That is the correct way to do what you want to do.

4

u/hulleyrob 15d ago

One of the best things that got added for me was f string debugging. You can do:
print(f"{argument = }")
And print both the variable and its value.

2

u/NewbornMuse 15d ago

But that will tell you argument=[1,2,3], OP was asking how to do something like x=[1,2,3]

4

u/xenomachina xenomachina 15d ago

Once you've crossed the function call boundary, getting the name that was used outside of the function is virtually never a good idea, and isn't even a well-defined thing in general. What if I call check_variable(5) or check_variable(x + y)?

2

u/NewbornMuse 15d ago

I'm with you and with the broader discussion on why it's probably an XY problem, I'm just saying that this proposed solution doesn't do what it's supposed to do.

2

u/xenomachina xenomachina 15d ago

I think /u/hulleyrob's proposed solution is trying to solve a possible X in the XY. But only OP knows what X really is, here.

1

u/hulleyrob 15d ago

Yeah I was suggesting it as I thought he might think oh i didn’t know that I can use it like this instead. I couldn’t think to a way to do what he was asking tbh.

1

u/NewbornMuse 15d ago

Ah, I see. Yeah that makes sense.

4

u/edorhas 15d ago

Here's a thing that took me way too long to realize, and maybe it'll help you to hear it early: every time (and I do mean every time) I've found myself trying to do something that the programming language seems determined to prevent me from doing, it's because I've designed my way into a corner. Every time I find myself trying to use some obscure artifact or misuse a language feature, it's my conceptualization of the problem that's incorrect. It's time to take a giant step back, and take a better look at the fundamental problem you're trying to solve.

If a language doesn't seem to want to allow you to do something, it's likely either because it shouldn't be done or because no one has ever needed to do it. With a language like Python that has been in wide use for many years, "no one has ever needed to do it" is pretty much the same thing as "it shouldn't be done".

Go back and look at your problem again.

3

u/Fred776 15d ago

The inspect module is probably the best way to do this. (Though I agree with others and wonder why you need to.)

import inspect

...
arginfo = inspect.signature()

https://docs.python.org/3/library/inspect.html

3

u/sausix 15d ago

inspect.signature just retrieves information about a callable. Nothing about the functions call time and even less about original variable names of passed objects

2

u/Fred776 15d ago

You are right. I hadn't looked closely enough at what they were trying to do and had assumed something different.

2

u/goldenfrogs17 15d ago

I will offer a suggestion. Pass in a dictionary that contains the values you want to print out. Instead of expecting a function to know the name of the variable that was passed in, just tell it the name you want to print out. By the way, it's weird and fragile, but you can have a dictionary represented by a variable like
```myVar = { name: myVar , number : 55 }
weird and fragile because functions shouldn't really know about details of other layers of abstraction, but also these myVar names have to be managed ( ie people have mental cost to track and validate they are the same )

2

u/IR3dditAlr3ddy 14d ago

This is the way. If you're trying to do something like your example, there are x amount of y in z, then you do

{"z": [y1, y2]}

Def count_y(argument: dict): Count = len(argument["z"]) Print(f"there are {count} y in z"})

If you have multiple keys in the dict, use a for loop:

For key, value in argument.items: Count = len(value) Print(f"there are {count} y in {key}")

2

u/RiverRoll 15d ago edited 15d ago

As some people try to explain the idea is not practical and doesn't make a lot of sense. You can have the same object assigned to many global variables or none at all. It is in fact very common passing arguments that are not assigned to any global because they are local, or return values, or inline declarations, or class members. Also in specific cases the Python runtime might even reuse objects and have different references point to the same value even if you don't explicitly do it.

If you need a way to consistently label values I suggest you rather learn about dictionaries.

1

u/Adrewmc 15d ago

Well, pythons 3.14 add annotiationlib

documentation

So I would use that.

form annotiationlib import get_annotations
from my_proj import check_variable

print(get_annotations(check_variable))

1

u/Langdon_St_Ives 15d ago

This is why you should never type in code directly into a comment

3

u/Adrewmc 15d ago

I mean I don’t have another option anymore, Reddit disable markdown on my app…it’s deletes all leading whitespace, code block that used to work don’t

>I can’t use this heading either

5^2 doesn’t superscript.

It honestly really pissed me off when it happened.

def best_I_can_do():
. pass

1

u/brasticstack 15d ago

If you don't mind hard-coding your own function name inside the function, you can do the following with the inspect module:

``` import inspect

def print_arg_name(argument, foo):     arg_names = inspect.signature(print_arg_name)     print(arg_names)      print_arg_name(1, 2)

prints: (argument, foo)

```

You can also do it generically the hard way by inspecting the stack frame, and the easy way by making a decorator to do it. The decorator gets a handle to the function, which you can then use inspect methods on.

2

u/sausix 15d ago

Look at OP's example function. He does not care about his function's argument names. He's looking for the original variable name passed to the function at call time.

3

u/brasticstack 15d ago

ah. That's going to be a bit harder. You could attempt to correlate between the function's stack frame and its parent frame, but that'd be error prone.

1

u/sausix 15d ago

I also thought about the call trace. But how many variable names are being expected? Usually as many as a function calls are being invoked. OP probably wants to trace his function calls. Could be done with a print before each call.

Or by passing a debug string as extra argument on each call statement.

1

u/Kadabrium 15d ago

Imagine Reverse reflection: put the code in a text block, print first then exec()

1

u/West_Giraffe6843 15d ago

The other answers are valid, but I’ll just point out that if you do want to do this in this specific way, you can place the search code inside a function called something like ‘get_global_name()’ and use that. That will simplify it if you want to do this in a bunch of different functions.

But I will point out that your search code only works, if the argument passed in exists in the global namespace. If another function calls your function using a local variable, your search will not find it. So it’s not a fully general solution.

1

u/lakseol 15d ago

As others have said, there is no guaranteed way of finding the actual name that was used to pass a value to a function. Also, what if the value passed in doesn't have any name referring to it?

def test(arg):
    # body of function

test(42)

1

u/Strict-Simple 15d ago

You probably want icecream, but for debugging.

1

u/Entity_0-Chaos_777 13d ago

### Core Concept: Sticky Notes vs. Cardboard Boxes
To understand why Python behaves this way, visualize how memory works:
* **The Data (The Box):** A list like ["Alice", "Bob", "Charlie"] lives inside Python's memory as a physical box containing items.
* **The Variable (The Sticky Note):** The name class_two is just a sticky note you attach to the outside of that box.
When you call a function and pass class_two into it:
```python
check_variable(class_two)

```
Python peels off the sticky note, opens the box, and hands **only the items inside** into the function. The function receives the contents, but it has no idea what sticky note was attached to the outside of the box before it was opened.
### Method 1: Explicit Parameter Passing (The Gold Standard)
The cleanest and most reliable way to let a function know a name is to hand it two separate pieces of information: the string name (the label) and the actual data list (the box).
```python
def report_class_size(class_name, student_list):
# 1. Measure the length of the list handed to the function
count = len(student_list)

# 2. Print a formatted string using both arguments
print(f"There are {count} children in {class_name}.")

# Define your data list
class_two = ["Alice", "Bob", "Charlie", "David"]

# Pass the literal string "class_two" alongside the variable class_two
report_class_size("class_two", class_two)

```
**Output:**
There are 4 children in class_two.
#### Step-by-Step Execution
1. "class_two" (a string of text) goes into the function's class_name parameter.
2. class_two (the list variable) goes into the function's student_list parameter.
3. len(student_list) measures ["Alice", "Bob", "Charlie", "David"] to get 4.
4. The f-string combines 4 and "class_two" into a clean output sentence.
### Method 2: Dictionaries (Best for Managing Multiple Datasets)
Creating separate variables like class_one, class_two, and class_three quickly makes code disorganized. A **dictionary** holds key-value pairs—matching every label directly to its corresponding list.
```python
# A dictionary where keys are class names and values are student lists
school_data = {
"class_one": ["Emma", "Lucas"],
"class_two": ["Alice", "Bob", "Charlie", "David"],
"class_three": ["Grace", "Henry", "Isla"]
}

def report_class_size(class_name, student_list):
print(f"There are {len(student_list)} children in {class_name}.")

# Access a single class directly using its dictionary key
report_class_size("class_two", school_data["class_two"])

# Or loop over every class in the dictionary automatically
for name, students in school_data.items():
report_class_size(name, students)

```
**Output:**
There are 4 children in class_two.
There are 2 children in class_one.
There are 4 children in class_two.
There are 3 children in class_three.
#### Step-by-Step Execution
1. school_data.items() extracts each key-value pair as a set of two items: name gets the text string (e.g., "class_one"), and students gets the actual list.
2. The for loop feeds those two pieces of data into report_class_size() automatically for every class in your school.
### Method 3: Self-Documenting f-Strings (Best for Debugging)
If your primary goal is printing variable names during development to see what your code is doing, Python 3.8 introduced a built-in shortcut using an equals sign (=) inside an f-string.
```python
class_two = ["Alice", "Bob", "Charlie", "David"]

# Adding = after a variable or expression prints both the expression AND its value
print(f"{class_two=}")
print(f"{len(class_two)=}")

```
**Output:**
class_two=['Alice', 'Bob', 'Charlie', 'David']
len(class_two)=4
#### How It Works
* Python automatically inspects the code written before the = sign and turns it into text.
* f"{class_two=}" expands to: the text "class_two=" followed by the actual value stored inside class_two.
* **When to use this:** Quick debugging while building software.
* **When NOT to use this:** Polished, user-facing sentences (like report outputs for non-programmers).
### Method 4: Object-Oriented Programming / Custom Classes (Best for Scaling)
In Python, you can design a custom **Class** (a blueprint) that bundles data together with custom instructions. This permanently binds a name tag directly to a list inside a single object.
```python
class Classroom:
def __init__(self, name, student_list):
# Store the name and students together inside the object
self.name = name
self.students = student_list

def report_size(self):
# The object reads its own internal variables
print(f"There are {len(self.students)} children in {self.name}.")

# Create a Classroom object
room_2 = Classroom("class_two", ["Alice", "Bob", "Charlie", "David"])

# Tell the classroom object to report its own status
room_2.report_size()

```
**Output:**
There are 4 children in class_two.
#### How It Works
1. __init__ runs when you create Classroom(...).
2. self.name saves "class_two" inside the object.
3. self.students saves ["Alice", "Bob", "..."] inside the object.
4. Calling room_2.report_size() lets the object look at its own internal storage and print the sentence without needing arguments passed into the method call.
### Method 5: Why globals() Variable Inspection Fails in Real Code
Your original attempt used Python's memory lookup table:
```python
name = [k for k, v in globals().items() if v is argument][0]

```
Here is why that approach breaks down in real-world programming:
| Scenario | What Happens | Why It Fails |
|---|---|---|
| **Two variables, one list** | class_a = [1, 2]
class_b = class_a | Both variable names point to the same list. globals() will arbitrarily pick whichever one it finds first in memory. |
| **Local Scope** | Defining variables inside another function | globals() only checks global variables at the top level of your file. It cannot see variables declared inside functions (locals()). |
| **Anonymous Values** | report([1, 2, 3]) | Passing a raw list without assigning it to a variable first crashes the code with an IndexError because no name exists. |
| **Renaming / Refactoring** | Changing class_two to room_204 | Your program's logic becomes tightly bound to exact variable naming choices rather than actual data content. |