8

Say I have the following class defined with the method foo:

class MyClass:
    def foo(self):
        print "My name is %s" % __name__

Now when I call foo() I expect/want to see this printed out

My name is foo  

However I get

My name is __main__  

And if I was to put the class definition into a module called FooBar I would get

My name is FooBar  

However if I do

m = MyClass()
print m.foo.__name__

I get exactly what I want which is

My name is foo

Can someone please help explain why __name__ refers to the module and not the method name ? Is there an easy way to get the method name?

Many thanks

1
  • why do you need to do this? what problem are you solving? Commented Feb 8, 2010 at 14:23

7 Answers 7

11

This does what you're after:


from inspect import currentframe, getframeinfo

class MyClass:
    def foo(self):
        print "My name is %s" % getframeinfo(currentframe())[2]
Sign up to request clarification or add additional context in comments.

9 Comments

While this is correct, there's no reason to prefer it over just typing 'foo' in the function body without a lot more information from the OP.
Cool, wonder if one could make a decorator that does this somehow... At least after the decorated method has been run. Maybe you could inspect the method decorated.
@Skurmedel: def with_name(fn): return lambda *args, **kwds: fn(fn.__name__, *args, **kwds) (eat that, SO comment formatting) You'd have to change the function to know it's being wrapped (the name is the first arg and self/cls comes second).
Yeah that would do it.... maybe print fn.__name__ before or afterwards. I don't know what he wants really :)
What do you propose the decorator would do? A function already has a __name__ property, the problem is that its hard to access from within the function itself (if I understood the question correctly).
|
4

Names always refer to local variables or (if one doesn't exist) then global variables. There is a a global __name__ that has the module's name.

class MyClass:
  def foo(self):
    print "My name is %s" % MyClass.foo.__name__

Of course, that's redundant and almost entirely pointless. Just type out the method name:

class MyClass:
  def foo(self):
    print "My name is %s" % "foo"
    print "My name is foo"

3 Comments

@Skurmedel: That's always possible, and hurts them more than it does me (through upvotes in response it's net win for me, even gameable), but if I have missed something, I really want to know about it.
Yeah I understand, I'm fine with downvotes as long as somebody state their concern as well.
@Roger Pate: If I change the method name, I would not want to spend time in tracking down and change every occurrence of the method name inside the method. For example, consider a logging or debug statement, which would you prefer : "entering method : foo" v/s "entering method : %s" % inspect.stack()[0][3]
3

__name__ refers to the module because that's what it's supposed to do. The only way to get at the currently running function would be to introspect the stack.

Comments

2

The other answers explain it quite well so I contribute with a more concrete example.

name.py

def foo():
    print "name in foo",__name__

foo()
print "foo's name",foo.__name__
print "name at top",__name__

Output

name in foo __main__
foo's name foo
name at top __main__

name2.py

import name

Output

name in foo name
foo's name foo
name at top name

Notice how the __name__ refers to built-in property of the module? Which is __main__ if the module is run directly, or the name of the module if its imported.

You should have run across the if __name__=="__main__": snippet.

You can find the relevant docs here, go check them out. Good luck! :)

Comments

1

Use introspection with the inspect module.

import inspect

class MyClass:
    def foo(self):
        print "My name is %s" % inspect.stack()[0][3]

Comments

1

Have a look at the the inspect module.

Try:

>>> import inspect
>>> def foo():
...     print inspect.getframeinfo(inspect.currentframe())[2]
...
>>> foo()
foo

or:

>>> def foo2():
...     print inspect.stack()[0][3]
...
>>> foo2()
foo2

Comments

-2

This will do it:

(You need to refer to self.__class__._name__.)

class MyClass:
    def foo(self):
        print "My name is %s" % self.__class__.__name__

1 Comment

The desired behavior, as shown in the example, is printing 'foo' (the method name) not 'MyClass'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.