【问题标题】:Python subclass with new, init and method带有 new、init 和方法的 Python 子类
【发布时间】:2021-05-03 19:08:55
【问题描述】:

我正在尝试在特定情况下创建一个子类,但我无法为其附加属性或方法。我认为 new / init 的用法对我来说并不清楚,但我无法从互联网上找到方法。

这是一个最小的工作玩具示例,展示了我正在尝试做的事情。

---- create_special_human() 函数的编辑

# I have this
class Human():
    def __init__(self):
        self.introduction = "Hello I'm human"


def create_special_human():
    special_human = do_very_complicated_stuffs() #returns type Human
    special_human.introduction = "Hello I'm special"
    return special_human


# I want to create this class
class SuperHero(Human):

    def __new__(self):
        special_human = create_special_human()
        return special_human

    def __init__(self):
        self.superpower = 'fly'

    def show_off(self):
        print(self.introduction)
        print(f"I can {self.superpower}")



human = Human()
special_human = create_special_human()
super_hero = SuperHero()
super_hero.show_off() # fails with error "type object 'Human' has no attribute 'show_off'"
print(super_hero.superpower) # fails with error "type object 'Human' has no attribute 'superpower'"

我想创建子类Superhero,我需要用create_special_human()返回的内容来初始化它,因为这个函数在实际情况下非常复杂。此外,我无法修改Human 类和create_special_human()

我知道返回的类型是 Human,这是错误的,但我不知道为什么会这样。

【问题讨论】:

  • 我认为你不能为所欲为。请参阅此answer,它解释了如果__new__ 返回不同的类型,则不会调用__init__
  • 我可以通过在__new__ 方法中添加superpower 属性来摆脱__init__。但如果我这样做,我仍然会遇到无法识别 show_off 方法的问题。
  • 您可以将do_very_complicated_stuffs(self) 添加到SuperHero.__init__ 吗?为什么使用__new__
  • @OneCricketeer 好问题,实际上在我的真实情况下我不能,让我修改我的玩具示例。我将修改 create_special_human() 以更好地匹配我的情况。
  • do_very_complicated_stuffs() 恰好返回了一个Human 类型的对象,但它是由多层构建的。它背后的initialHuman() 初始化器被挖掘得很深。这就是为什么我不能把这段代码复制到我的__init__

标签: python python-3.x class inheritance design-patterns


【解决方案1】:

(已编辑) 我对您的代码做了一些更改,它正在成功执行。

  • 您必须在子类 __init__ 内调用超类 __init__
  • 正如我在评论中所说,只需从 create_special_human 返回 SuperHero。
  • 我已经从SuperHero 中删除了__new__ 方法,因为它没有任何意义。看看this article
class Human():
    def __init__(self):
        self.introduction = "Hello I'm human"


class SuperHero(Human):
    
    # Removed __new__

    def __init__(self):
        super().__init__()  # Init superclass
        self.superpower = 'fly'

    def show_off(self):
        print(self.introduction)
        print(f"I can {self.superpower}")


def create_special_human():
    # Simply initialize and return SuperHero instance
    special_human = SuperHero()
    do_very_complicated_stuffs(special_human)
    special_human.introduction = "Hello I'm special"
    return special_human


human = Human()
special_human = create_special_human()
super_hero = SuperHero()
super_hero.show_off() 
print(super_hero.superpower)

您可以在this question 中阅读有关super() 的更多信息。

【讨论】:

  • 但是我需要用函数 create_special_human() 的结果来初始化我的 SuperHero() 对象。
  • 然后简单地返回 SuperHuman 实例,就像在 __main__ 中所做的一样
  • 您能否用您的建议更新您的答案?我不确定我明白你的意思。
  • 刚刚更新,你的代码有一些变化
  • SuperHero 对象仍未被 create_special_human() 的输出初始化。我还更新了我的代码以更正 create_special_human 函数。
猜你喜欢
  • 1970-01-01
  • 2019-11-25
  • 1970-01-01
  • 2018-08-07
  • 2013-06-12
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多