我有一堂课
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')
...
答案 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()
了。