在Python中重定向类成员调用
我试着去“扩展”一个封闭的类。
collections.defaultdict(lambda: 1)
我想给它添加两个方法,分别叫做“vocabulary”和“wordcount”。显然,给内置类型设置属性是行不通的,我也不能从defaultdict继承,所以我决定写一个类,并把对它的调用重定向到我想要扩展的类型上。
class BagOfWordDoc():
def __init__(self):
self.data = collections.defaultdict(lambda: 1)
for method in dir(self.data):
if hasattr(getattr(self.data, method),'__call__') and method not in ['__class__', '__self__']:
l = lambda *args: getattr(self.data, method)(*args)
setattr(self, method,l)
def vocabulary(self):
return self.data.keys()
def wordcount(self):
return reduce(operator.add, self.data.values(), 0)
但是在访问它的时候出现了问题。
doc = BagOfWordDoc()
doc[123] = 123 # yields TypeError: values() takes no arguments (1 given)
doc.keys() # yields TypeError: values() takes no arguments (1 given)
doc.xxx() # yields TypeError: values() takes no arguments (1 given)
所以就好像每个lambda函数都被映射到了“values”这个函数上,而“values”是属性列表中的最后一个元素。
你知道为什么会这样吗?至于最开始的问题,我现在在考虑重写我自己的defaultdict。
更新
根据建议,这里是可用的实现:
class BagOfWordDoc():
def __init__(self):
self.data = collections.defaultdict(lambda: 0)
def __getattr__(self, *args):
return self.data.__getattribute__(*args)
def vocabulary(self):
return self.data.keys()
def wordcount(self):
return reduce(operator.add, self.data.values(), 0)
2 个回答
1
你说的“不能从defaultdict继承”是什么意思呢?对我来说是可以的(虽然这个例子不是很好,但我不太确定你想要实现什么,所以…):
#!/usr/bin/env python
from collections import defaultdict
import operator
class DD(defaultdict):
def vocabulary(self):
return self.keys()
def wordcount(self):
return reduce(operator.add, self.data.itervalues(), 0)
if __name__ == '__main__':
dd = DD(int)
dd[2] += 1
print dd.vocabulary()
4
要么是从一个类复制到另一个类,而不是从一个实例复制到另一个实例,要么就让 .__getattr__()
去调用被封装的对象。