带有可选参数的继承链
Inheritance chain with optional parameter
我想要一个继承链有一个可选参数。链上的大多数 classes 有时需要 参数成为成员 ,但我也想在其他时候使用链 而无需参数成为成员成员。
我考虑过将参数设为可选的 class 并使用导入,但我想避免对成员 optional
使用 class 语法。也因为链上的所有 classes 在字典中用作键。
这个的替代品?难道我做错了什么?有没有更 Pythonic 的方式?
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')
Top
已经知道如何处理optional=None
;只需按原样传递参数。但是,请记住,每个 class 都必须准备好接收和传递未知参数,以防您未定义的 class 继承其中任何一个并添加其 拥有 __init__
个参数 个。 (考虑从 Top
和其他一些 class Foo
继承的 class X
,并且 Foo
需要关键字参数 bar
: X(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
您只需要在 Top
(parent/base) class:
中包含 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
中的默认参数将其设置为这个如果没有提供。由于您的参数默认值在所有 class 中都是 None
,因此本质上可以执行可选的存在(或不存在)。
就我个人而言,我什至不会包含 if 语句。我会将该属性设置为 None
,以便稍后在您的代码中尝试访问 obj.optional
时,不会引发 AttributeError
。我相信如果属性是继承的,应该通过 subclasses 保持属性一致,这样任何试图使用 subclasses 的人都期望 __init__
中使用的所有参数都被使用或设置为属性无数的 super()
调用了继承链并且没有丢失。
我想要一个继承链有一个可选参数。链上的大多数 classes 有时需要 参数成为成员 ,但我也想在其他时候使用链 而无需参数成为成员成员。
我考虑过将参数设为可选的 class 并使用导入,但我想避免对成员 optional
使用 class 语法。也因为链上的所有 classes 在字典中用作键。
这个的替代品?难道我做错了什么?有没有更 Pythonic 的方式?
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')
Top
已经知道如何处理optional=None
;只需按原样传递参数。但是,请记住,每个 class 都必须准备好接收和传递未知参数,以防您未定义的 class 继承其中任何一个并添加其 拥有 __init__
个参数 个。 (考虑从 Top
和其他一些 class Foo
继承的 class X
,并且 Foo
需要关键字参数 bar
: X(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
您只需要在 Top
(parent/base) class:
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
中的默认参数将其设置为这个如果没有提供。由于您的参数默认值在所有 class 中都是 None
,因此本质上可以执行可选的存在(或不存在)。
就我个人而言,我什至不会包含 if 语句。我会将该属性设置为 None
,以便稍后在您的代码中尝试访问 obj.optional
时,不会引发 AttributeError
。我相信如果属性是继承的,应该通过 subclasses 保持属性一致,这样任何试图使用 subclasses 的人都期望 __init__
中使用的所有参数都被使用或设置为属性无数的 super()
调用了继承链并且没有丢失。