带有可选参数的继承链

2024-03-29 02:18:36 发布

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

我希望继承链有一个可选参数。链上的大多数类有时需要使参数成为成员,但我也希望在其他时间使用链而不使参数成为成员。你知道吗

我曾想过将参数设为可选类并使用import,但我希望避免对成员optional使用类语法。而且还因为链上的所有类都在字典中用作键。你知道吗

替代方案?我做错什么了吗?有没有一种更像Python的方法?你知道吗

class Top:

    def __init__(self, optional=None):

        if optional is not None:
            self.optional = optional
        return


class Middle(Top):

    def __init__(self, one, optional=None):

        if optional is not None:
            super().__init__(optional)

            self.one = one


class Bottom(Middle):

    def __init__(self, one, two, optional=None):

        if optional is not None:
            super().__init__(one, optional)
        else:
            super().__init__(one)

            self.two = two


a = Middle('one')
b = Middle('one', 'two')
c = Bottom('one', 'two')
d = Bottom('one', 'two', 'three')

Tags: selfnonemiddle参数ifinitisdef
2条回答

您只需要在Top(parent/base)类中有if语句:

class Top:
    def __init__(self, optional=None):
        if optional is not None:
            self.optional = optional

# (you don’t need an explicit return in __init__)

class Middle(Top): 
    def __init__(self, one, optional=None):
        super().__init__(optional)
        self.one = one

# this applies to Bottom class as well

现在不管你是否提供这个选项。假设您在调用Middle时没有选择,则one属性按预期设置,而Top.__init__是用None调用的,因为Middle中的默认参数将其设置为该属性(如果未提供)。由于在所有类中,您的参数缺省值都是None,因此基本上,optional的存在(或不存在)都会被执行。你知道吗

就我个人而言,我甚至不想包括if语句。我会将该属性设置为None,以便在稍后的代码中,如果您尝试访问obj.optional,则不会引发AttributeError。我认为,如果继承了子类,就应该通过子类保持属性的一致性,这样任何试图使用子类的人都会期望在__init__中使用的所有参数都通过调用继承链的大量super()被使用或设置为属性,并且不会丢失。你知道吗

Top已经知道如何处理optional=None;只需按原样传递参数即可。但是,请记住,每个类都必须准备好接收和传递未知参数,以防您没有定义的类继承了这些参数中的任何一个,并将其自己的参数添加到__init__。(考虑一个从Top和其他一些类Foo继承的类X,并且Foo期望一个关键字参数barX(1, 2, 3, bar=5)最终将调用Top.__init__,而bar尚未被删除。将__init__super一起使用时,关键字参数是一个非常好的主意。)

class Top:

    def __init__(self, optional=None, **kwargs):
        super().__init__(**kwargs)
        if optional is not None:
            self.optional = optional


class Middle(Top):

    def __init__(self, one, optional=None, **kwargs):
        super().__init__(optional, **kwargs)
        self.one = one


class Bottom(Middle):

    def __init__(self, one, two, optional=None, **kwargs):
        super().__init__(one, optional, **kwargs)    
        self.two = two

相关问题 更多 >