在类中调用方法来修改列表

时间:2016-03-29 19:56:28

标签: python python-2.7

我有一个课程,我借助各种方法收集数据(比如说23)。每个方法都使用list并可以修改它。我的问题是如何以更普遍接受的方式调用(在课堂上)所有类的方法?

class Example(object):
    def __init__(self):
        self.lst = []

    def multiply(self):
        for i in xrange(10):
            self.lst.append(i**2)

    def get_list(self):
        return self.lst
# Calling:
ex = Example()
ex.multiply
print ex.get_list
# What I want is call multiply method inside class and just do this
print ex.get_list

示例类说明了我的想法。我知道可以通过使用Example .__ dict__values()迭代来解决我的问题,在一个类的方法或者使用inspect模块调用所有方法,但我不确定没有更多纯粹的Pythonic方法。

更新

我想要的只是收集yapf格式化程序的配置数据。

主要问题是如何调用类中的所有方法 - 我不想在一个方法中实现输入文件的所有配置分析。 OOP和模式是我的指南。

更新2: 回答Jared Goguen。我想创建类来收集数据到字典并将其发送到CreateStyleFromConfig方法。 当它完成后,我只想从类中获取get_style方法而不调用其中的所有方法:

config = ConfData() # Class which collects all configurations from file
config.get_style()

ConfData类包含特定于数据名称的方法。例如:

def align_closing_bracket_with_visual_indent(self):
    # Do some work..
    pass

1 个答案:

答案 0 :(得分:0)

所以,我想有两个可能的解决方案,但我不喜欢其中任何一个。我想你可能会以错误的方式解决这个问题。

您可以使用外部装饰器track和类变量tracker来跟踪您要调用的方法。

def track(tracker):
    def wrapper(func):
        tracker.append(func)
        return func
    return wrapper

class Example:
    tracker = []

    @track(tracker)
    def method_a(self):
        return [('key_a1', 'val_a1'), ('key_a2', 'val_a2')]

    @track(tracker)
    def method_b(self):
        return [('key_b1', 'val_b1'), ('key_b2', 'val_b2')]

    def collect_data(self):
        return dict(tup for method in self.tracker for tup in method(self))

print Example().collect_data()
# {'key_b1': 'val_b1', 'key_b2': 'val_b2', 'key_a1': 'val_a1', 'key_a2': 'val_a2'}

通过这种方法,您可以在课堂上使用您不想打电话的实用方法。

另一种方法是检查类的目录,并在逻辑上确定要调用的方法。

from inspect import ismethod

class Example:
    def method_a(self):
        return [('key_a1', 'val_a1'), ('key_a2', 'val_a2')]

    def method_b(self):
        return [('key_b1', 'val_b1'), ('key_b2', 'val_b2')]

    def collect_data(self):
        data = {}
        for attr in dir(self):
            if not attr.startswith('_') and attr != 'collect_data':
                possible_method = getattr(self, attr)
                if ismethod(possible_method):
                    data.update(possible_method())
        return data

此方法类似于帖子中提到的方法(即迭代__dict__)并且很弱,因为您想要调用的任何实例方法都需要从' _'开始。您可以调整此方法以使用其他任何命名约定,但其他人可能无法读取。

这些方法中的任何一个都可以将collect_data部分实现为超类,允许您创建最小的子类。对第一种方法来说,这并没有多大帮助。

class MethodTracker(object):
    def collect_data(self):
        return dict(tup for method in self.tracker for tup in method(self))

class Example(MethodTracker):
    tracker = []

    @track(tracker)
    def method_a(self):
        return [('key_a1', 'val_a1'), ('key_a2', 'val_a2')]

    @track(tracker)
    def method_b(self):
        return [('key_b1', 'val_b1'), ('key_b2', 'val_b2')]

使用第二种方法,得到的子类是最小的。此外,你可以做一些反思,让超级班级有实用的方法,不要以' _'

开头。

from inspect import ismethod

class MethodTracker(object):
    def collect_data(self):
        data = {}
        for attr in dir(self):
            if not attr.startswith('_') and not hasattr(MethodTracker, attr):
                possible_method = getattr(self, attr)
                if ismethod(possible_method):
                    data.update(possible_method())
        return data

    def decoy_method(self):
        return 'This is not added to data.'

class Example(MethodTracker):
    def method_a(self):
        return [('key_a1', 'val_a1'), ('key_a2', 'val_a2')]

    def method_b(self):
        return [('key_b1', 'val_b1'), ('key_b2', 'val_b2')]