捏造类和函数之间的界限

时间:2016-02-18 21:23:23

标签: python

我有一系列用于对数据进行分类的功能。每个函数都传递相同的输入。该系统的目标是能够随意放入新的分类功能,而无需进行任何调整。

为此,我使用了从here取消的classes_in_module函数。然后,将在每个输入上运行一个python文件中的每个分类器。

但是,我发现将分类器实现为类或函数是kludgy。类意味着实例化和执行,而函数缺乏干净的内省,允许我查询名称或使用继承来定义公共值。

这是一个例子。首先,类实现:

class AbstractClassifier(object):
    @property
    def name(self):
        return self.__class__.__name__

class ClassifierA(AbstractClassifier):
    def __init__(self, data):
        self.data = data
    def run(self):
        return 1

这可以以这种方式使用,假设classifier_list是包含classes_in_module的文件中ClassifierA的输出:

result = []
for classifier in classifier_list:
    c = classifier(data)
    result.append(c.run())

然而,这似乎有点傻。这个类显然是静态的,并不真正需要维护自己的状态,因为它被使用一次并被丢弃。分类器实际上是一个函数,但后来我失去了共享name属性的能力 - 我将不得不使用丑陋的内省技术sys._getframe().f_code.co_name并为每个分类器函数复制该代码。分类器之间的任何其他共享属性也将丢失。

你怎么看?我应该接受这种错误的课程吗?或者有更好的方法吗?

3 个答案:

答案 0 :(得分:2)

函数可以包含成员数据。您还可以使用func_name属性找到函数的名称。

def classifier(data):
    return 1
classifier.name = classifier.func_name

print(classifier.name) #classifier

如果您希望多个函数的行为方式相同,则可以使用装饰器。

function_tracker = []

def add_attributes(function):
    function.name = function.func_name
    function.id = len(function_tracker)
    function_tracker.append(function)
    return function

@add_attributes
def classifier(data):
    return 1

print(classifier.name, classifier.id) # 'classifier', 0

这会在特定情况下避免上课吗?

答案 1 :(得分:1)

如果您不需要该类的多个实例(而且似乎没有),请创建该类的一个实例并将run更改为__call__

class AbstractClassifier(object):
    @property
    def name(self):
        return self.__class__.__name__

class ClassifierA(AbstractClassifier):
    def __call__(self, data):
        return 1
ClassifierA = ClassifierA()       # see below for alternatives

然后在你的其他代码中:

result = []
for classifier in classifier_list:
    result.append(classifier(data))

不是让ClassifierA = ClassifierA()(不是很优雅),而是可以做到:

classifier_list = [c() for c in (ClassifierA, ClassifierB, ...)]

如果您需要创建更多的实例,此方法可以让您的类保持方便;如果你不需要有多个实例,你可以使用装饰器来IAYG(实例化你去;):

def instantiate(cls):
    return cls()

@instantiate
class ClassifierZ(object):
    def __call__(self, data):
        return some_classification

答案 2 :(得分:1)

将类实例用作函数:

class ClassifierA(AbstractClassifier):
    def __init__(self, data):
        self.data = data
    def __call__(self):
        return 1

result = []
for classifier in classifier_list:
    c = classifier(data)
    result.append(c())

或者只是使用功能:

classifier_list = []
def my_decorator(func):
    classifier_list.append(func)
    return func

@my_decorator
def classifier_a(data):
    return 1

result = []
for classifier in classifier_list:
    c = classifier(data)
    result.append(c)