views:

200

answers:

7

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

+4  A: 

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"
Roger Pate
Why the downvote?
Roger Pate
Could be a competitive downvote. It has happened to me.
Skurmedel
@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.
Roger Pate
Yeah I understand, I'm fine with downvotes as long as somebody state their concern as well.
Skurmedel
+3  A: 

__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.

Ants Aasma
A: 

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__
0xfe
The desired behavior, as shown in the example, is printing 'foo' (the method name) not 'MyClass'.
Roger Pate
Doh, right, didn't read the question carefully enough.
0xfe
+8  A: 

This does what you're after:


from inspect import currentframe, getframeinfo

class MyClass:
    def foo(self):
        print "My name is %s" % getframeinfo(currentframe())[2]
MattH
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.
Roger Pate
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
@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).
Roger Pate
Yeah that would do it.... maybe print fn.__name__ before or afterwards. I don't know what he wants really :)
Skurmedel
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).
mizipzor
@mizipzor: Print the name... but I'm not interested in what he wants, I was pondering the alternatives.
Skurmedel
@mizipzor: Yes, you understood what I was having trouble with. Since a function has a __name__ property, I thought that this would be in scope of the function and easy to access. For trace purposes I was hoping to refer to __name__ from within the function and therefore not worry if the function name ever changed. Some nice answers here recommending inspect, but I was hoping that it would be a lot more straightforward to do.
ephesian
@ephesian: See my answer, its very straight forward to access the name of a function. But thats outside the scope of the function and that way you actually type the name of the function anyway (something you wanted to avoid?). Its a bit of a loophole, accessing the function without typing its name. Using **inspect** is, as far as I know, the most straight forward I know to do what you want.
mizipzor
@mizipzor: Typing the name of the function in the source code isn't more straight-forward? (The OP is asking how to print the name of the function; trying to use some special magic to get it dynamically is just his failed attempt.)
Roger Pate
+1  A: 

Use introspection with the inspect module.

import inspect

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

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! :)

mizipzor
+1  A: 

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
Dave Webb