Перенаправить вызовы члена класса в Python - PullRequest
0 голосов
/ 31 января 2010

Я пытался «расширить» закрытый класс

collections.defaultdict(lambda: 1)

с помощью addint it 2 метода, которые называются «словарь» и «wordcount» по-видимому, невозможно создать метод setattr для создания типов, и при этом я не могу наследовать от defaultdic, поэтому я решил написать класс и перенаправить вызовы к нему типа, который я хочу расширить.

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)

Так что, как будто каждая лямбда была отображена на функцию 'values' И 'values' - последний элемент списка свойств

Знаете ли вы, почему это происходит? Что касается первоначальной проблемы, я сейчас думаю о переписывании своего собственного по умолчанию.

обновление

Основываясь на предложении, рабочая реализация:

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 ]

3 голосов
/ 31 января 2010

Либо скопируйте из класса в класс, не из экземпляра в экземпляр, или просто делегируйте .__getattr__() инкапсулированному объекту.

1 голос
/ 31 января 2010

Что вы подразумеваете под "не может наследовать от 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()
...