仅继承 parent class in Python 的类型
Inherit only the type from parent class in Python
考虑一个 parent class Foo
和我的 class myFoo
。我希望 isinstance(myFoo, Foo)
returns 为真,但不继承 Foo
.
的所有方法和属性
例如
class Foo:
def __init__(self):
# do stuff
# tons of methods!
class myFoo:
def __init__(self):
# do stuff
# couple of methods not in common with Foo
这可能是一个小众用例,但对我来说非常方便。我怎么能 'fool' isinstance
相信 myFoo
是一个 Foo
实例而不做 class myFoo(Foo)
并因此继承了 Foo
的大量方法。
根据上下文编辑:
所以在我的例子中,Foo
继承自 Mixin classes,每个都定义了一堆相关的方法。这些 Mixin 中定义的一些方法以 self if isinstance(self, Foo) else self.foo
开头,因为要么提供了 Foo
,要么提供了 Foo
设置为 .foo
属性的 class。
现在,我想定义一个不同的 myFoo
class,它只继承其中的一些 Mixin。但是它们在检查 isinstance(self, Foo)
时不起作用。更改 Mixin 或 Foo
class 不是一个选项,所以我必须复制整个 Mixin 和它可能调用的所有函数并编辑它们;或者我找到了 'fool' Mixin 的方法,相信我提供给它的确实是一个 Foo
实例。
或者,我可以从 Foo
和 overwrite/raise AttributeError
继承对所有我不想要的方法的调用作为 myFoo
.[=35= 的一部分]
听起来像是严重违反了 https://en.wikipedia.org/wiki/Liskov_substitution_principle。也许您可以提取一个具有您想要的接口的超类,然后让两者 类 从它继承。
Python 实现了“Virtual Subclassing”的概念——它精确地允许将 class 声明为另一个的 subclass,而不必继承自那个。 (也就是说,正是你的问题)。
唯一的要求是允许虚拟子classing 的基础class 是使用abc.ABCMeta metaclass 创建的——即使你没有使用抽象方法。它可以在自定义元 class 中使用较低级别 __subclasscheck__
来完成,但是 abc.ABC 已经准备好工作,包括 .register
调用,这也是需要的。
In [295]: import abc
In [296]: class Foo(abc.ABC):
...: def __init__(self):
...: # do stuff
...: ...
...: # tons of methods!
...:
...: class myFoo:
...: def __init__(self):
...: # do stuff
...: ...
...:
In [297]: Foo.register(myFoo)
Out[297]: __main__.myFoo
In [298]: issubclass(myFoo,Foo)
Out[298]: True
In [299]: isinstance(myFoo(), Foo)
Out[299]: True
如上例所示,abc.ABC class 具有允许虚拟子classing 的机制,方法是添加 class-only“注册”方法. myFoo
在此示例中无论如何都不会继承 Foo
。
至于
Alternatively, I could inherit from Foo and overwrite/raise
AttributeError on calls to all the methods I do not want as part of
myFoo.
这是可能的,但不太实用 - 可以通过仔细覆盖 class 上的 __getattribute__
并处理应隐藏在继承 class.
考虑一个 parent class Foo
和我的 class myFoo
。我希望 isinstance(myFoo, Foo)
returns 为真,但不继承 Foo
.
例如
class Foo:
def __init__(self):
# do stuff
# tons of methods!
class myFoo:
def __init__(self):
# do stuff
# couple of methods not in common with Foo
这可能是一个小众用例,但对我来说非常方便。我怎么能 'fool' isinstance
相信 myFoo
是一个 Foo
实例而不做 class myFoo(Foo)
并因此继承了 Foo
的大量方法。
根据上下文编辑:
所以在我的例子中,Foo
继承自 Mixin classes,每个都定义了一堆相关的方法。这些 Mixin 中定义的一些方法以 self if isinstance(self, Foo) else self.foo
开头,因为要么提供了 Foo
,要么提供了 Foo
设置为 .foo
属性的 class。
现在,我想定义一个不同的 myFoo
class,它只继承其中的一些 Mixin。但是它们在检查 isinstance(self, Foo)
时不起作用。更改 Mixin 或 Foo
class 不是一个选项,所以我必须复制整个 Mixin 和它可能调用的所有函数并编辑它们;或者我找到了 'fool' Mixin 的方法,相信我提供给它的确实是一个 Foo
实例。
或者,我可以从 Foo
和 overwrite/raise AttributeError
继承对所有我不想要的方法的调用作为 myFoo
.[=35= 的一部分]
听起来像是严重违反了 https://en.wikipedia.org/wiki/Liskov_substitution_principle。也许您可以提取一个具有您想要的接口的超类,然后让两者 类 从它继承。
Python 实现了“Virtual Subclassing”的概念——它精确地允许将 class 声明为另一个的 subclass,而不必继承自那个。 (也就是说,正是你的问题)。
唯一的要求是允许虚拟子classing 的基础class 是使用abc.ABCMeta metaclass 创建的——即使你没有使用抽象方法。它可以在自定义元 class 中使用较低级别 __subclasscheck__
来完成,但是 abc.ABC 已经准备好工作,包括 .register
调用,这也是需要的。
In [295]: import abc
In [296]: class Foo(abc.ABC):
...: def __init__(self):
...: # do stuff
...: ...
...: # tons of methods!
...:
...: class myFoo:
...: def __init__(self):
...: # do stuff
...: ...
...:
In [297]: Foo.register(myFoo)
Out[297]: __main__.myFoo
In [298]: issubclass(myFoo,Foo)
Out[298]: True
In [299]: isinstance(myFoo(), Foo)
Out[299]: True
如上例所示,abc.ABC class 具有允许虚拟子classing 的机制,方法是添加 class-only“注册”方法. myFoo
在此示例中无论如何都不会继承 Foo
。
至于
Alternatively, I could inherit from Foo and overwrite/raise AttributeError on calls to all the methods I do not want as part of myFoo.
这是可能的,但不太实用 - 可以通过仔细覆盖 class 上的 __getattribute__
并处理应隐藏在继承 class.