首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用组合而不是继承传递方法的Pythonic方法

使用组合而不是继承传递方法的Pythonic方法
EN

Stack Overflow用户
提问于 2022-07-03 04:15:54
回答 2查看 39关注 0票数 0

假设我有一个库,如下所示,其中Person是一个面向用户的类。

代码语言:javascript
复制
class SwissArmyKnife:

    def open_bottle(self):
        """...etc...."""

    def open_package_with_scissors(self):
        """...etc...."""

    def uncork_wine(self):
        """...etc...."""

    def whittle_an_intricate_dolphin_figurine(self):
        """...etc...."""

class Person:
    
    def __init__(self):
        self.swiss_army_knife = SwissArmyKnife()
        
    def open_bottle(self):
        self.swiss_army_knife.open_bottle()

    def open_package_with_scissors(self):
        self.swiss_army_knife.open_package_with_scissors()

    def uncork_wine(self):
        self.swiss_army_knife.uncork_wine()

    def whittle_an_intricate_dolphin_figurine(self):
        self.swiss_army_knife.whittle_an_intricate_dolphin_figurine()

我想将SwissArmyKnife的所有方法传递给Person,因为Person将有一个SwissArmyKnife,但理想情况下,我希望避免Person类中的所有样板代码,因为每次我更新瑞士军刀所能做的事情时,我也必须记住更新person类。

这样做的一种方法是让Person继承SwissArmyKnife,但这感觉很尴尬,因为一个人不是瑞士军刀,他们只是有一把刀。

另一种可能只是期望用户编写person.swiss_army_knife.open_bottle(),但这有点冗长。另外,在导致我提出这个玩具问题的实际案例中,我已经发布了一个库的版本,您可以只编写person.open_bottle(),我不想破坏向后兼容性。

有什么好的方法不让我看到自动检查SwissArmyKnifePerson的方法吗?你要做什么呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-07-04 23:53:48

如果对使用继承的反对意见似乎在语义上令人困惑,那么您可以考虑使用混合模式。在Python中使用Mixins的方式仍然使用继承,但是这种模式传达的是“具有”的功能而不是“是一个”的关系。

这个StackOverflow问题对这个主题进行了很好的讨论。

票数 1
EN

Stack Overflow用户

发布于 2022-07-03 05:33:40

如果您真的、真的、真的想这样做,您可以重载特殊的__getattr__方法。根据文档的说法

当默认属性访问与__getattr__一起失败时调用AttributeError ( __getattribute__()引发AttributeError,因为名称不是类树中的实例属性或属性;或者名称属性的__get__()引发AttributeError).`

因此,您可以自动将任何未定义的方法调用转发给瑞士军刀,如下所示:

代码语言:javascript
复制
class SwissArmyKnife:
    def doit(self):
        print("I done it!")

class Person:
    def __init__(self):
        self.swiss_army_knife = SwissArmyKnife()

    def say_howdy(self):
        print("howdy")

    def __getattr__(self, name):
        return getattr(self.swiss_army_knife, name)

p = Person()
p.say_howdy()
p.doit()
代码语言:javascript
复制
<script src="https://cdn.jsdelivr.net/gh/pysnippet/pysnippet@latest/snippet.min.js"></script>

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72843876

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档