0

I would like to use functions based on strings passed in argument as below. The code gives the following error: AttributeError: 'Obj' object has no attribute 'funA'

The functions funA and funB are defined within fun because they are only used within fun and nowhere else

class Obj(object):
    def __init__(self):
        self.A = 2
        self.B = 3

    def fun(self, ar):
        def funA(self):
            print self.A

        def funB(self):
            x = self.B + 4
            print self.B

        for letter in ar:
            name = 'fun' + letter
            getattr(self, name)()

obj_instance = Obj()
obj_instance.fun(['A', 'B'])
2
  • 2
    The problem is not with the getattr call, but with the functions themselves. Those are not attributes of self (the Obj instance), but local variables inside fun. Commented Dec 6, 2017 at 10:17
  • 1
    I don't see why you would declare a function inside a function if you don't need to call it several times and/or for code readability. Commented Dec 6, 2017 at 10:22

2 Answers 2

1

As an alternative you can try the following code. It gives you the opportunity to check whether a function exists or not.

class Obj(object):
    def __init__(self):
        self.A = 2
        self.B = 3

    def fun(self, ar):
        def funA():
            print self.A

        def funB():
            x = self.B + 4
            print self.B
            print x

        for letter in ar:
            name = 'fun' + letter
            if name in locals():
                locals()[name]()

obj_instance = Obj()
obj_instance.fun(['A', 'B'])
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Tobias. Your code works perfectly well for my purposes. Is there a reason why you use "if name in locals()", why not just leave is out?
As I wrote, it's just a sample how to check whether a function exists in your local scope or not. You can leave it out, but it's not safe. E.g. if you try to call obj_instance.fun(['A', 'B', 'C']) than you get an exception for 'C' because there is no funC in your local scope. This happens not if you use the check condition.
0

I wouldn't recommend it, but if you really need it, then you can do it this way:

class Obj(object):
    def __init__(self):
        self.A = 2
        self.B = 3

    def fun(self, ar):
        def funA(self):
            print self.A

        def funB(self):
            x = self.B + 4
            print self.B

        for letter in ar:
            name = 'fun' + letter + '()'
            exec(name)

obj_instance=Obj()
obj_instance.fun(['A', 'B'])

exec() executes any string that you put in parentheses as if it was python code.

1 Comment

This code generates the following error message: TypeError: funA() takes exactly 1 argument (0 given)

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.