Python:在抽象类中动态调用函数

时间:2016-04-21 18:58:54

标签: python python-2.7 abstract-class

我有一个需要调用analyze方法的类实例。构造函数使用此类消息接收请求对象

  

{     “信息”:{         “属性”:{             “MESSAGE_ID”: “2aj78h98-2112-4637-76h1-09ec727933bb”             “主题”:“MyTopic”             “版本”:1         },         “data”:“{”id“:123541234}”       }   }

my_model = MyModel(request)
my_model.analyse(data)

MyModel类的结构是:

import importlib


class MyModel(object):

    def __init__(self, req):

        """
        From the request, extract the topic and dynamically create is    instance
        """
        try:
            self.req = req
            classname = self.req.topic # in this example: MyTopic
            classpath = 'foo.bar'
            module = importlib.import_module(classpath)
            self.some_object = getattr(module, classname)
        except Exception as e:
            raise Exception(e.message)

    def analyse(self):
        data = self.req.data
        # self.some_object is an instance of foo.bar.MyTopic
        self.some_object.analyse(data)

以下是MyTopic类的结构:

class MyTopic(TopicBase):

    def __init__(self):
        super(MyTopic, self).__init__()
        self.retreive_mode = 'api'

    def _retreive_from_db(self):
        print 'in db'

    def _retreive_from_datawarehouse(self):
        print 'in datawarehouse'

    def _retreive_from_api(self):
       print 'in api

及其父类:

from abc import ABCMeta, abstractmethod

class TopicBase(object):
__metaclass__ = ABCMeta

    def __init__(self, *args, **kwargs):
        pass

    def analyse(self, data):
        """
        Base on the class configuration, call the proper retreive method
        """

        def func_not_found():  # just in case we dont have the method
            raise NotImplementedError

        func_name = '_retreive_from_' + self.retreive_mode
        func = getattr(self, func_name, func_not_found)
        func(data)

    @abstractmethod
    def _retreive_from_db(self):
        pass

    @abstractmethod
    def _retreive_from_datawarehouse(self):
        pass

    @abstractmethod
    def _retreive_from_api(self):
        pass

当调用my_model.analyse(data)时,我收到错误:

TypeError: unbound method analyse() must be called with MyTopic instance as first argument (got dict instance instead)

my_model已经是MyTopic的一个实例。所以,如果我尝试my_model.analyse(my_model,data),我收到错误:

TypeError: unbound method analyse() must be called with MyTopic instance as first argument (got ABCMeta instance instead)

任何想法??

1 个答案:

答案 0 :(得分:2)

self.some_object = getattr(module, classname)

self.some_object设置为一个类(不是该类的实例),这意味着当MyModel.analyse()调用时

self.some_object.analyse(data)

它正在呼叫SomeClass.analyse(data)而不是SomeClass().analyse(data)