python,包装类返回包装成员的平均值

时间:2010-03-21 23:02:26

标签: python

标题不是很清楚,但我会尝试解释。

有这个课程:

class Wrapped(object):
    def method_a(self):
        # do some operations
        return n

    def method_b(self):
        # also do some operations
        return n

我希望有一个类与此相同的类:

class Wrapper(object):
    def __init__(self):
        self.ws = [Wrapped(1),Wrapped(2),Wrapped(3)]

    def method_a(self):
        results=[Wrapped.method_a(w) for w in self.ws]
        sum_ = sum(results,0.0)
        average = sum_/len(self.ws)
        return average

    def method_b(self):
        results=[Wrapped.method_b(w) for w in self.ws]
        sum_ = sum(results,0.0)
        average = sum_/len(self.ws)
        return average

显然这不是手边的实际问题(它不仅仅是两种方法),而且这段代码也是不完整的(只包含解释问题的最小值)。

所以,我正在寻找的是一种获得这种行为的方法。意思是,在包装器类中调用哪个方法,为所有Wrapped类对象调用该方法并返回其结果的平均值。

可以吗?怎么样?

提前致谢。

修改
谢谢你的答案...看到他们的解决方案后,这一切似乎都很明显:)我选择了Alex Martelli的答案,因为它很好地解释了解决方案。另一个答案也很有用,这也是我投票的原因。

4 个答案:

答案 0 :(得分:3)

虽然非常可行,但它有点棘手,因为获取方法(或其他属性)及其调用是单独的操作。这是一个解决方案:

class Wrapper(object):
    def __init__(self):
        self.ws = [Wrapped(1),Wrapped(2),Wrapped(3)]

    def __getattr__(self, n):
        meth = getattr(Wrapped, n)
        def caller():
            results = [meth(w) for w in self.ws]
            sum_ = sum(results,0.0)
            average = sum_/len(self.ws)
            return average
        return caller

它有点过分简单(假设在获取和调用之间self.ws没有变化 - 当然可以在获取时获得“快照”self.ws,如果这是所需的语义;不使用@functools.wraps所以如果那些需要保留,则不保留docstring& c,但应该主要用于您的目的。

答案 1 :(得分:1)

您可以使用getattr来对此进行调用(在对象上调用'任意'方法):

以此为例:

# this fetches you references to the 'method_a' methods for objects in self.ws
funcs = [getattr(wrapped_obj, "method_a") for wrapped_obj in self.ws]
# now execute them to get the results
results = [func() for func in funcs]

您的其余代码将保持不变。

答案 2 :(得分:1)

您可以通过在Wrapper中实现__getattr__方法来执行此操作,该方法返回一个函数,该函数将调用转发给所有包装的对象。这是一个简单返回结果的基本实现示例:

import functools

class Wrapper(object):
    def __init__(self, *args):
        self._targets = args

    def _broadcast(self, name, *args, **kwargs):
        return [getattr(t, name)(*args, **kwargs) for t in self._targets]

    def __getattr__(self, name):
        return functools.partial(self._broadcast, name)

请注意,只有在找不到属性时才会调用__getattr__,因此您在Wrapper中定义的所有方法名称都不会被转发(例如上面示例中的_broadcast )。

答案 3 :(得分:0)

您可以使用特殊的getattr方法执行此操作。