Reed Richards
Reed Richards

Reputation: 4378

Order of method definitions and dictionary of class method references in Python

I have a class and some methods in that class which I want to reference using a dictionary inside the class. If I define the dictionary before the class method I get a "not defined error". However, if I put the dictionary after the method definition python does not complain. Why is that? And what can I do to fix it?

Code example:

This does not work

class foo:
    fooFunDic = {
        'fooFun1': fooFun1,
        'fooFun2': fooFun2
    }
    def fooFun1(self):
        return 0
    def fooFun2(self):
        return 0

Ugly but works

class foo:
    def fooFun1(self):
        return 0
    def fooFun2(self):
        return 0
    fooFunDic = {
        'fooFun1': fooFun1,
        'fooFun2': fooFun2
    }

Upvotes: 1

Views: 209

Answers (5)

Vishnu Upadhyay
Vishnu Upadhyay

Reputation: 5061

When you assign a variable python serach that variable in 1:-Local namespace then serach in gloabal namespace. Python at compile time compiled the code line by line hence first line compile first, if any undefined variable came NameError: name 'fooFun1' is not defined.

in your case what python does, it looks for dictionary values but they are not defined untill parsing the dict.

The main thing in python is it parse the code line by line hence begore using any variable you have to assign it.

Upvotes: -1

disp_name
disp_name

Reputation: 1488

Define init and pass fooFun1() and fooFun2() in it.

class foo:
    def __init__ (self, fooFun1, fooFun2):
        fooFunDic = {
            'fooFun1': fooFun1,
            'fooFun2': fooFun2
        }
    def fooFun1():
        return 0
    def fooFun2():
       return 0

This way you can run these functions without defining them before. This is the good way to do. By doing this Python will not be dependent on these fooFun1() and fooFun2() and run successfully (though you might need them to add some functionality). This will be useful if you later want to change the name of the input functions or you want to add some functionality.

Upvotes: 0

RemcoGerlich
RemcoGerlich

Reputation: 31270

The reason is that Python is an interpreted language, and all the code class statement is executed when the class statement is.

You can add some print statements in the class definition to see it in action.

So if fooFunDic is early in the class definition, it's executed at a time when the methods simple don't exist yet.

Upvotes: -1

Martijn Pieters
Martijn Pieters

Reputation: 1123420

The names are yet do be defined when you define the dictionary.

The class body is executed like a function and the local namespace forms the attributes. The same order of name definition applies therefor.

Note that even in your second example, what you store in the dictionary are functions, not methods. Calling those functions would require you to explicitly pass in self parameters if you want them to work like methods. You could define the dictionary in the __init__ method instead to get bound methods in a dictionary stored on the instance:

class foo:
    def __init__(self):
        self.fooFunDic = {
            'fooFun1': self.fooFun1,
            'fooFun2': self.fooFun2
        }

    def fooFun1(self):
        return 0
    def fooFun2(self):
        return 0

If you don't care about bound methods vs. bare function objects, you can define the dictionary first, then 'register' each function with that dictionary:

class foo:
    fooFunDic = {}

    def fooFun1(self):
        return 0
    fooFunDic['fooFun1'] = fooFun1

    def fooFun2(self):
        return 0
    fooFunDic['fooFun2'] = fooFun2

Upvotes: 3

XNor
XNor

Reputation: 658

Do you need that dict to be a static variable?

You could do:

class foo:
 def __init__(self):
     self.fooFunDic = {
      'fooFun1': self.fooFun1,
      'fooFun2': self.fooFun2
      }
 def fooFun1:
   return 0
 def fooFun2:
   return 0

Upvotes: 0

Related Questions