Finding the name of a function while defining it

A

Abhas Bhattacharya

While I am defining a function, how can I access the name (separately as string as well as object) of the function without explicitly naming it(hard-coding the name)?
For eg. I am writing like:
def abc():
#how do i access the function abc here without hard-coding the name?
 
R

Roy Smith

Abhas Bhattacharya said:
While I am defining a function, how can I access the name (separately as
string as well as object) of the function without explicitly naming
it(hard-coding the name)?
For eg. I am writing like:
def abc():
#how do i access the function abc here without hard-coding the name?

Do you need it at compile-time, or is it good enough to have the name a
run-time? Assuming the latter, then I'm thinking the traceback module
is your friend. Call traceback.extract_stack() and pull off the last
frame in the stack. The function name will be in there.

There may be a cleaner way, but that's what I've done in the past.

I've only ever wanted the name. If you need the actual function object,
I suppose you might eval() the name, or something like that.
 
C

Chris Angelico

The
compiled code in a function, for example, exists as an object without a
name. That unnamed object can be bound to one or more function names, but
the code doesn't know that. Example:

def one():
print( "Here's one" )

two = one

That creates one function object, bound to two names. What name would you
expect to grab inside the function?

Presumably 'one'.
Even more obscure:

two = lamba : "one"
one = two

Which one of these is the "name" of the function?

I would say '<lambda>'. Whatever method is used to get the function's
name, I would expect it to match the __name__ attribute of the
function (which is a peer to __code__, but I don't think the
function's code *is* the function).

ChrisA
 
A

Abhas Bhattacharya

Do you need it at compile-time, or is it good enough to have the name a

run-time? Assuming the latter, then I'm thinking the traceback module

is your friend. Call traceback.extract_stack() and pull off the last

frame in the stack. The function name will be in there.



There may be a cleaner way, but that's what I've done in the past.



I've only ever wanted the name. If you need the actual function object,

I suppose you might eval() the name, or something like that.

I need it compile-time.
During run-time, I can always use: function_name.__name__ (although that's kind of lame because it returns "function_name"). But if the function itself contains print(__name__) and I call the function, it returns __main__ (yes, __main__ itself, not the string "__main__") (which is the calling function).
 
A

Abhas Bhattacharya

Why? Of what value would that be?



Note that I'm not merely being obstructionist here. What you're asking

here is not something that a Python programmer would normally ask. The

compiled code in a function, for example, exists as an object without a

name. That unnamed object can be bound to one or more function names, but

the code doesn't know that. Example:



def one():

print( "Here's one" )



two = one



That creates one function object, bound to two names. What name would you

expect to grab inside the function?



Even more obscure:



two = lamba : "one"

one = two



Which one of these is the "name" of the function?

--

Tim Roberts, (e-mail address removed)

Providenza & Boekelheide, Inc.

It is of quite value to me.
Because I have this situation:
I have used a dictionary with "function_name":value pair in the top of the code. Now when some function is called, I need to print the value assigned to its name in the dictionary (the functions are defined after the dictionary). Now there is only one bad way-around for me: I need to hard-code the name in the function like this:
def function_name():
print(dict_name.get("function_name"))
but ofcourse it is a bad thing to do because I have a lot of this type of functions. It would be better if I can can use the same code for all of them, because they are all essentially doing the same thing.

Now, for your questions:
If i call one() and two() respectively, i would like to see "one" and "two"..
I dont have much knowledge of lambda functions, neither am i going to use them, so that's something I cant answer.
 
A

Abhas Bhattacharya

Presumably 'one'.







I would say '<lambda>'. Whatever method is used to get the function's

name, I would expect it to match the __name__ attribute of the

function (which is a peer to __code__, but I don't think the

function's code *is* the function).



ChrisA

If i call one() and two() respectively, i would like to see "one" and "two".
 
A

Abhas Bhattacharya

Presumably 'one'.







I would say '<lambda>'. Whatever method is used to get the function's

name, I would expect it to match the __name__ attribute of the

function (which is a peer to __code__, but I don't think the

function's code *is* the function).



ChrisA

If i call one() and two() respectively, i would like to see "one" and "two".
 
C

Chris Angelico

During run-time, I can always use: function_name.__name__ (although that's kind of lame because it returns "function_name"). But if the function itself contains print(__name__) and I call the function, it returns __main__ (yes, __main__ itself, not the string "__main__") (which is the calling function).

That's because __name__ looks for that attribute on the module (aka
"global variable"), not the function. When you run your Python script
as an application, the module is called __main__.

ChrisA
 
A

Abhas Bhattacharya

That's because __name__ looks for that attribute on the module (aka

"global variable"), not the function. When you run your Python script

as an application, the module is called __main__.



ChrisA

Ok, that sheds some light on why it acts like that, but how can i use it the way I want (which i already told)?
 
A

Abhas Bhattacharya

That's because __name__ looks for that attribute on the module (aka

"global variable"), not the function. When you run your Python script

as an application, the module is called __main__.



ChrisA

Ok, that sheds some light on why it acts like that, but how can i use it the way I want (which i already told)?
 
C

Chris Angelico

[ a whole lot of double-spaced quoted text - please trim it ]
If i call one() and two() respectively, i would like to see "one" and "two".

That completely goes against your idea of knowing at compile-time,
because the name "two" isn't anywhere around at that time.

There's no way to know what name was used to look something up. It
might not even have a name - the called function could well have been
returned from another function:

# foo.py
def indirection():
return lambda: print

# bar.py
import foo
foo.indirection()()("Hello, world!")

What are the names of all the functions called here?

ChrisA
 
A

Abhas Bhattacharya

[ a whole lot of double-spaced quoted text - please trim it ]
If i call one() and two() respectively, i would like to see "one" and "two".



That completely goes against your idea of knowing at compile-time,

because the name "two" isn't anywhere around at that time.



There's no way to know what name was used to look something up. It

might not even have a name - the called function could well have been

returned from another function:



# foo.py

def indirection():

return lambda: print



# bar.py

import foo

foo.indirection()()("Hello, world!")



What are the names of all the functions called here?



ChrisA

Yes, I get it that it may not be possible in complex cases (mostly using lambda functions). But in the simple case I mentioned, is it possible?
 
A

Abhas Bhattacharya

[ a whole lot of double-spaced quoted text - please trim it ]
If i call one() and two() respectively, i would like to see "one" and "two".



That completely goes against your idea of knowing at compile-time,

because the name "two" isn't anywhere around at that time.



There's no way to know what name was used to look something up. It

might not even have a name - the called function could well have been

returned from another function:



# foo.py

def indirection():

return lambda: print



# bar.py

import foo

foo.indirection()()("Hello, world!")



What are the names of all the functions called here?



ChrisA

Yes, I get it that it may not be possible in complex cases (mostly using lambda functions). But in the simple case I mentioned, is it possible?
 
M

Mitya Sirenef

It is of quite value to me.
Because I have this situation:
I have used a dictionary with "function_name":value pair in the top of the code. Now when some function is called, I need to print the value assigned to its name in the dictionary (the functions are defined after the dictionary). Now there is only one bad way-around for me: I need to hard-code the name in the function like this:
def function_name():
print(dict_name.get("function_name"))
but ofcourse it is a bad thing to do because I have a lot of this type of functions. It would be better if I can can use the same code for all of them, because they are all essentially doing the same thing.

Now, for your questions:
If i call one() and two() respectively, i would like to see "one" and "two".
I dont have much knowledge of lambda functions, neither am i going to use them, so that's something I cant answer.

How about defining a function that prints value and then calls a function?

def call(func_name):
print(mydict[func_name])
globals()[func_name]()


You could also define a custom class that does the same thing on attribute
lookup and do something like Call.func_name() .

-m
 
A

Abhas Bhattacharya

How about defining a function that prints value and then calls a function?



def call(func_name):

print(mydict[func_name])

globals()[func_name]()





You could also define a custom class that does the same thing on attribute

lookup and do something like Call.func_name() .



-m

Can you explain me what this means?
globals()[func_name]()
 
A

Abhas Bhattacharya

How about defining a function that prints value and then calls a function?



def call(func_name):

print(mydict[func_name])

globals()[func_name]()





You could also define a custom class that does the same thing on attribute

lookup and do something like Call.func_name() .



-m

Can you explain me what this means?
globals()[func_name]()
 
A

Abhas Bhattacharya

Not possible per se without resorting to sys._getframe() or similar hackery.

A simple+elegant way to do this would require PEP 3130 (http://www.python..org/dev/peps/pep-3130/ ) or similar, but that particular proposal got rejected.

Thanks for telling that. I thought that there is a direct way, and now you have confirmed that there isn't. So, as I can see, Mitya's code can be a perfect way-around, although it will require another function.
 
A

Abhas Bhattacharya

Not possible per se without resorting to sys._getframe() or similar hackery.

A simple+elegant way to do this would require PEP 3130 (http://www.python..org/dev/peps/pep-3130/ ) or similar, but that particular proposal got rejected.

Thanks for telling that. I thought that there is a direct way, and now you have confirmed that there isn't. So, as I can see, Mitya's code can be a perfect way-around, although it will require another function.
 
C

Chris Rebert

[Oh god please stop/avoid using Google Groups with its godawful
reply-quoting style that adds excessive blank lines]
Because I have this situation:
I have used a dictionary with "function_name":value pair in the top of
the code. Now when some function is called, I need to print the value
assigned to its name in the dictionary (the functions are defined after the
dictionary). Now there is only one bad way-around for me: I need to
hard-code the name in the function like this:
def function_name():
print(dict_name.get("function_name"))
but ofcourse it is a bad thing to do because I have a lot of this type of
functions. It would be better if I can can use the same code for all of
them, because they are all essentially doing the same thing.

I agree with the general outline of Mitya's suggestion, i.e. refactor the
"print the associated value" step into a separate function, thus obviating
the self-reference issue; it'd be bad to repeat that code in each function
anyway.

Anyhow, here's a simple variation that exploits decorators (because they're
generally awesome & one of my favorite features):

def printing_name_beforehand(func):
def wrapper(*args, **kwargs):
print(the_dict.get(func.__name__))
return func(*args, **kwargs)
return wrapper

Usage:

@printing_name_beforehand
def some_func(...):
# whatever

(Forgive me if there are typos; composing this reply on a tablet is
cumbersome.)
 
M

Mitya Sirenef

How about defining a function that prints value and then calls a function?



def call(func_name):

print(mydict[func_name])

globals()[func_name]()





You could also define a custom class that does the same thing on attribute

lookup and do something like Call.func_name() .



-m
Can you explain me what this means?
globals()[func_name]()

globals() is a globals dictionary that maps function
names to function objects (along with other things),
so we get the function object by name and then
run it.

-m
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top