Search code examples
pythondictionarymetaclassprepare

NoneType when changing a value in Python class dictionary


I'm trying to change the dictionary of a python class so that everytime a function object is added to the dictionary I add an instance of my class where I redefine __call__ instead. I use a custom dictionary for the metaclass and in __setitem__ of the dictionary class I'm instantiating the class that I use to change the behaviour of the added functions and I add a not NoneType object to the dictionary. However, when I instantiate the class with the functions I'm wrapping and try to call the respective function I get a "NoneType not callable" error and the function object that I've wrapped in the class dictionary is = None. Any ideas why this might happen? Thanks!


Solution

  • Before I start - is the posted code your actual code? It doesn't actually work for me under Python 3.2 - I've fixed it up a bit. Here's what I've changed, to start:

    class_dict = list()
    

    is now

    class_dict = {}
    

    and in OverloadedFunction.__call__:

    for fkey, function in class_dict.items():
        inspect_t = inspect.getfullargspec(function)
        print(inspect_t)
    

    in member_dict.__setitem__:

    if value.__class__.__name__ == "function":
        class_dict[key] = value
        dict.__setitem__(self,key,OverloadedFunction(key,value))
    

    I believe this is what you intended. I never got the NoneType not callable error - with these modifications (plus import inspect at the top), your code works and prints the argument specification:

    $ python3 temp.py
    FullArgSpec(args=['self', 'a', 'b'], varargs=None, varkw=None, defaults=None, kwonlyargs=[],    kwonlydefaults=None, annotations={'a': <class '__main__.Asteroid'>, 'b': <class '__main__.Asteroid'>})
    

    Now, you want to implement the multimethod - the modifications I made preclude that, since your multimethods are overwritten on each call to __setitem__, so you can work from there (perhaps use collections.defaultdict(list) and append to class_dict[key] instead).

    May I suggest something? I don't think you need a metaclass - http://www.artima.com/weblogs/viewpost.jsp?thread=101605 provides a multimethod implementation for Python 2.x that's very simple.