如何将不存在的类成员函数动态转换为现有的成员函数[已解决]

时间:2019-07-11 09:37:18

标签: python

我有一堂课

class DataReader:
    def get_data(self, name):
        # get data of given name

可以按以下方式使用它:

reader = DataReader()
a = reader.get_data('a')
b = reader.get_data('b')
c = reader.get_data('c')
...

我是否可能编写如下代码:

a = reader.get_a()
b = reader.get_b()
c = reader.get_c()

对于当前代码,由于类DataReader没有像get_a()这样的方法,它将失败。我想要做的是,做一些事情让DataReader支持get_a之类的方法,然后自动将其转换为self.get_data('a'),而无需真正地一个个定义get_xxx方法。

在这里,a,b,c可以是任何字符串,并且在定义DataReader类时我无法全部了解它们。因此,让我以另一种方式问我的问题:是否有一些捷径可以让DataReader支持所有(无限)get_xxx方法(此处xxx可以是任何字符串),就像我定义了无限方法一样:

class DataReader:
    def get_a(self): return self.get('a')
    def get_b(self): return self.get('b')
    ...
    def get_z(self): return self.get('z')
    def get_aa(self): return self.get('aa')
    ...
    def get_asdf(self): return self.get('asdf')
    ...
    def get_okjgoke(self): return self.get('okjgoke')
    ...

2 个答案:

答案 0 :(得分:2)

一种方法是使用DataReader来定义__getattr__特殊方法(当在对象内部未找到属性时调用该方法):

class DataReader:
    def __init__(self, data):
        self.items = data.copy()

    def __getattr__(self, attr):
        if attr.startswith('get_'):
            return lambda: self.items[attr.split('get_')[-1]]
        raise AttributeError('Attribute "{}" not found.'.format(attr))

d = DataReader({'a':1, 'b':2})
print(d.get_a())
print(d.get_b())

打印:

1
2

答案 1 :(得分:1)

您将名称传递给get_data的方法对我来说似乎很合理。但是,如果您坚持使用基于属性的查找,则可以覆盖__getattr__并在其中使用get_data进行查找,例如:

class DataReader:
    def __getattr__(self, attr):
        parts = attr.partition('_')
        if parts[0] == 'get' and parts[-1] != 'data':
            return self.get_data(parts[-1])
        return super().__getattr__(attr)

    def get_data(self, name):
        return name

现在您可以使用Foo().get_a来获取Foo().get_data('a')

如果您想从Foo().get_a()之类的可调用对象而不是Foo().get_a中获取值,则可以在lambda中使用tuck:

class DataReader:
    def __getattr__(self, attr):
        parts = attr.partition('_')
        if parts[0] == 'get' and parts[-1] != 'data':
            return lambda: self.get_data(parts[-1])
        return super().__getattr__(attr)

    def get_data(self, name):
        return name

现在您可以Foo().get_a()了。