在python中委托@classmethods

在python中委托@classmethods,python,delegation,Python,Delegation,我需要一个委托类来委托@classmethod。以下是我尝试过的: class Foo(object): def __init__(self, a): self.a = a @classmethod def from_a(cls, a): return cls(a) class Bar(object): def __init__(self, foo): elf._foo = foo def __ge

我需要一个委托类来委托
@classmethod
。以下是我尝试过的:

class Foo(object):

    def __init__(self, a):
        self.a = a

    @classmethod
    def from_a(cls, a):
        return cls(a)

class Bar(object):

    def __init__(self, foo):
        elf._foo = foo

    def __getattribute__(self, name):
        return getattr(self._foo, name)

但是,这当然没有定义如何查找
Foo
(不是
Foo
)的属性,因此
Bar.from_a(5)
将引发
AttributeError
。当然,通过在
Bar
上定义一个
from\u a
方法,或者通过调用
Bar(Foo.from\u a(5))
在实例化时,可以显式地做到这一点,但我宁愿隐式地做到这一点。想法?

我开始研究一种简单的方法,即使用元类,但实际上相当复杂。您可能应该在这里做的是从
Foo
继承
Bar
,但我还是会向您展示我的想法:

import types
import functools

def make_delegating_type(delegatee):
    class DelegatingType(type):
        def __getattr__(self, name):
            obj = getattr(delegatee, name)
            if isinstance(obj, (types.FunctionType, types.MethodType)):
                @functools.wraps(obj)
                def wrapper(*args, **kwargs):
                    result = obj(*args, **kwargs)
                    if isinstance(result, delegatee):
                        return self(result)
                    return result
                return wrapper
            return obj
    return DelegatingType

class Foo(object):
    def __init__(self, a): self.a = a

    @classmethod
    def from_a(cls, a): return cls(a)

class Bar(object):
    __metaclass__ = make_delegating_type(Foo)
    def __init__(self, foo): self._foo = foo

    def __getattr__(self, name): return getattr(self._foo, name)
请注意,在3.x中,您将使用
类栏(object,metaclass=make\u delegating\u type(Foo)
,而不是
栏顶部的
元类=make\u delegating\u type(Foo)

这是如何工作的。您当前的版本当前将
Bar
实例上的属性查找委托给
Foo
实例,这使用了一个元类,以便类
Bar
上的属性查找也委托给类
Foo
。不幸的是,这并不像只使用
\tattr\uuuu
返回的定义
getattr(delegatee,name)
,因为如果a查找的属性是一个工厂函数,如示例中所示,则需要该工厂函数的一个版本,该函数将返回委托类型的实例。因此,例如
Bar.from\u a(5)
应与
Bar(Foo.from\u a(5))相同
,使用这种简单的方法,您只需从_a(5)
中获得
Foo.这就是为什么所有逻辑都会检测属性是否是函数或方法,并创建一个包装器来检查该函数/方法的返回类型


再次重申,我不建议您使用此代码!它比仅从
Bar
上定义
,或从
Bar
继承
Foo
要复杂得多。但希望这对您来说是一次学习经历,就像对我一样。

Foo的
Foo
实例满足了该类要求hod.你想实现什么?为什么?显然
from_a
不存在于
Bar
上,因为你没有定义它或子类
Foo
。你为什么期望它呢?@MartijnPieters:但提问者正在寻找使
Bar.from_a(5)
work,所以看不到
Foo
的实例。@SteveJessop:啊,我明白你的意思。然后你需要一个元类。@Martijn:我也在想元类,但我也在想,总的来说,提问者可能不需要元类,而需要做一些更有意义的事情。我仍在想为什么
Bar
不仅仅继承自
Foo
Bar
在这种情况下不能继承自
Foo
。它需要是委托类或代理类。请检查注释。