我需要委派的类来委派@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
。虽然当然可以通过在from_a
上定义Bar
方法或通过调用Bar(Foo.from_a(5))
来实例化来明确地执行此操作,但我宁愿隐式地执行此操作。想法?
答案 0 :(得分:2)
我开始研究我认为使用元类的简单方法,但它实际上相当复杂。你应该在这里做的是让Bar
继承Foo
,但我会告诉你我想出的是什么:
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中,您会使用class Bar(object, metaclass=make_delegating_type(Foo)
代替__metaclass__ = make_delegating_type(Foo)
类主体顶部的Bar
行。
这是如何工作的。您当前的版本当前将Bar
实例上的属性查找委托给Foo
的实例,这会使用元类,以便委派类 Bar
上的属性查找到 class Foo
也是如此。不幸的是,它并不像使用返回__getattr__
的{{1}}定义那么简单,因为如果你查找的属性是一个工厂函数,就像在你的例子中那样你需要一个版本的工厂函数返回委派类型的实例。因此,例如getattr(delegatee, name)
应该与Bar.from_a(5)
相同,并且使用天真的方法,您将获得Bar(Foo.from_a(5))
。这就是为什么有所有逻辑检测属性是函数还是方法,并创建一个检查该函数/方法的返回类型的包装器。
重申一下,我建议您不要使用此代码!这比在Foo.from_a(5)
上定义from_a
或Bar
继承更复杂来自Bar
。但希望这对你来说是一次学习经历,就像我一样。