Python:具有与基类相同的一组_init__参数的子类,以及附加参数,而不使用super()

2024-10-01 02:26:16 发布

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

我不知道如何解释我的问题,所以我会尽我所能

我有基类Price

class Price:
    def __init__(self, contractid, *args, **kwargs):
        self.contractid = contractid

我有一堆从Price派生的类。每个子类都需要参数Price以及一些附加参数。例如

class BestAvailablePrice(Price):
    def __init__(self, contractid, sell_type)
        super().__init__(contractid)
        self.sell_type = sell_type

class MaxInvestedPrice(Price):
    def __init__(self, contractid, n_shares, cumulative=True)
        super().__init__(contractid)
        self.n_shares = n_shares
        self.cumulative = cumulative

....

使用super().__init__(contractid)的问题是,如果Price.__init__()发生变化,我也需要更新我的所有子类。例如,如果我决定Price还需要一个marketid参数:

class Price:

    # new __init__ method includes marketid argument
    def __init__(self, contractid, marketid, *args, **kwargs):  
        self.contractid = contractid
        self.marketid = marketid

然后我不得不返回并更新所有的子类

我一直在做的事情是声明一个setup_init_args(*args, **kwargs)方法,并在其中定义其他参数:

class Price:
    def __init__(self, contractid, *args, **kwargs):
        self.contractid = contractid
        self.setup_init_args(*args, **kwargs)

    def setup_init_args(*args, **kwargs)
        pass # overridden in subclasses

class BestAvailablePrice:
    def setup_init_args(sell_type)
        self.sell_type = sell_type

这将正确设置我的基本对象的属性,我可以使用工厂方法实例化我的对象:

marketid = 1000
contractid = 2020

def get_price_object(obj, *args, **kwargs):
    return obj(marketid, contractid, *args, **kwargs)

bap = get_price_object(BestAvailablePrice, sell_type = 'sell')

如果我更改基类的init方法,我只需要在工厂方法中更改它。这是可行的,我会得到正确的对象,但是

缺点:

一,。我的IDE不知道我得到的是什么类型的对象。

我可以做到:

def get_price_object(obj, *args, **kwargs) -> Price:

但它认为我只得到了一个价格对象。我曾尝试使用python类型库中的TypeVar,但似乎无法实现。使用# type: BestAvailablePrice设置某些内容是一种解决方法,但并不理想

二,。My IDE在BestAvailablePrice

当我键入bap = get_price_object(BestAvailablePrice, )时,我希望看到BestAvailablePrice对象所需的附加参数。有没有办法让它出现?我有几十种价格类型,很难记住哪个类需要哪个参数


Tags: 对象方法self参数initdeftypeargs
1条回答
网友
1楼 · 发布于 2024-10-01 02:26:16

如果您同意在调用时始终使用关键字参数,则子类不必从Price复制命名参数。请记住,它不识别的任何关键字参数都会添加到kwargs中以进行传递。通过使__init__的所有参数仅为关键字,您可以坚持使用关键字参数

class Price:
    def __init__(self, *, contractid, **kwargs):
        super().__init__(**kwargs)
        self.contractid = contractid


class BestAvailablePrice(Price):
    def __init__(self, *, sell_type, **kwargs)
        super().__init__(**kwargs)
        self.sell_type = sell_type


class MaxInvestedPrice(Price):
    def __init__(self, *, n_shares, cumulative=True, **kwargs)
        super().__init__(**kwargs)
        self.n_shares = n_shares
        self.cumulative = cumulative

注意Price.__init__也应该使用super来处理多重继承,其中Price不一定是MRO中object之前的最后一个类。如果你做的很好,当调用object.__init__时,**kwargs将是空的


关于工厂方法,您可以添加适当的类型提示:

from typing import TypeVar, Type

P = TypeVar('P', bound=Price)

def get_price_object(obj: Type[P] , *args, **kwargs) -> P:

尽管这可能无助于IDE建议预期的参数名称

相关问题 更多 >