3

I'm trying to do something like this, but I can't figure out how to call the function bar.

def foo():
    def bar(baz):
        print('used getattr to call', baz)
    getattr(bar, __call__())('bar')

foo()

Notice, that this is somewhat unusual. Normally you'd have an object and get an attribute on that, which could be a function. then it's easy to run. but what if you just have a function within the current scope - how to do getattr on the current scope to run the function?

MetaStack
  • 3,266
  • 4
  • 30
  • 67

2 Answers2

3

You are close. To use getattr, pass the string value of the name of the attribute:

getattr(bar, "__call__")('bar')

i.e

def foo():
  def bar(baz):
    print('used getattr to call', baz)
  getattr(bar, "__call__")('bar')

foo()

Output:

used getattr to call bar
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
  • what if I wanted to do `getattr('bar', "__call__")('bar')` ? when I try to make the function referenced via a string I get `AttributeError: 'str' object has no attribute '__call__'` Is there any way to reference the name of that dynamically? – MetaStack Oct 11 '18 at 15:10
  • I just used a map, this works for my purposes `methods = {'bar': bar} ; getattr(methods['bar']...` – MetaStack Oct 11 '18 at 15:15
  • just call the `locals()` function, it returns a dictionary of objects from the local scope – Sam Mason Oct 11 '18 at 15:35
2

alternatively, you can also use the locals() function which returns a dict of local symbols:

def foo():
  def bar(baz):
    print('used getattr to call', baz)
  locals()['bar']('pouet')

foo()

It also allows you to get the function by its name instead of its reference without need for a custom mapping.

Tryph
  • 5,946
  • 28
  • 49