如何正确继承基于条件返回其他类的类?

2024-04-18 15:47:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我将首先编写代码,然后详细解释我要实现的目标,因为这样做比较容易:

global child_selector

class Base(object): 
  def __init__(self):
    self.extended_name = self.name + '_Base'


class Child1(Base): 
  def __init__(self):
    super(Child1, self).__init__()

  def print_my_name(self):
    print 'I am ChildOne'

class Child2(Base):

  def __init__(self):
    super(Child2, self).__init__()

  def print_my_name(self):
    print 'I am ChildTwo'

class ChildAsBaseSelector(object):
  def __new__(cls):
    if child_selector == 1:
      return Child1()
    elif child_selector == 2:
      return Child2()
    else:
      print 'No child selected'

现在如果我创建一个从Child1或Child2继承的类姓名作为实例变量,一切都按预期工作:

class Testing1(Child1):

  def __init__(self):
    self.name = 'Testing1'
    super(Testing1, self).__init__()

a = Testing1()
a.print_my_name() # 'I am ChlidOne'
print a.extended_name # 'Testing1_Base'

但是如果我创建另一个类,它将直接从ChildAsBaseSelector()继承,那么事情就变得可疑了:

class Testing2(ChildAsBaseSelector):

  def __init__(self):
    self.name = 'Testing2'
    super(Testing2, self).__init__()

child_selector = 1
a = Testing2() 
# Will raise AttributeError: 'Child1' object has no attribute 'name'

在阅读了关于“\uuuu new\uuuuuuuuuuuuo()”的python文档之后,我认为问题是因为:“如果\uuuu new\uuuuuuuuo()没有返回cls的实例,那么新实例的\uuuu init\uuuuuuuuo()方法将不会被调用。”这并没有真正的帮助,因为我不知道如何“修复它”。你知道吗

我也知道我可以这样做:

if child_selector == 1:
  ChildAsBaseSelector = Child1
if child_selector == 2:
  ChildAsBaseSelector = Child2

而不是直接从ChildAsBaseSelector继承。但我发现这并不优雅,而且将python的灵活性推向了极限。 我真正想做的是有一个类,它只会根据一个条件返回另一个类,然后我就可以用它来继承。有什么提示吗?我想元类(一个我正在努力理解的概念)现在会派上用场。你知道吗

谢谢你给我小费。谢谢您!你知道吗


Tags: nameselfchildbaseinitdefselectorclass
1条回答
网友
1楼 · 发布于 2024-04-18 15:47:04

为什么不让ChildAsBaseSelectorBase继承呢?在您的示例中,super(Testing2, self).__init__()将解析为object.__init__()(因此它不会做您期望的事情),但是-正如您提到的-它无论如何都不会被调用,因为它既不在Child1__mro__中,也不在Child2__mro__中。你知道吗

无论如何:让您的Base.__init__()依赖于子类在调用super().__init__()之前设置一个属性是不好的设计-如果Base需要它,那么它应该作为参数传递,或者在Base本身有一个可用的默认值。你知道吗

另外,如果ChildAsBaseSelector的唯一存在理由是基于全局/设置/任何东西创建Child1Child1的实例,那么只需使用工厂函数。。。没有“new”关键字真是一件幸事。你知道吗

相关问题 更多 >