python - Python:具有与基类相同的 __init__ 参数集的子类,加上额外的参数,而不使用 super()
问题描述
我不知道如何解释我的问题,所以我会尽力而为。
我有基类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方法,只需要在工厂方法中更改即可。这行得通,我会得到正确的对象,但是......
缺点:
1. 我的 IDE 不知道我得到的是什么类型的对象。
我可以:
def get_price_object(obj, *args, **kwargs) -> Price:
但后来它认为我只得到一个 Price 对象。我尝试过使用 python 类型库中的 TypeVar,但我似乎无法让它工作。设置一些东西# type: BestAvailablePrice
是一种解决方法,但并不理想。
2. 我的 IDE 没有在代码完成中显示预期的参数BestAvailablePrice
当我键入时,bap = get_price_object(BestAvailablePrice, )
我希望看到 BestAvailablePrice 对象所需的其他参数。有没有办法让它显示出来?我有几十种价格类型,很难记住哪个类需要哪个参数。
解决方案
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__
应该使用, 来处理多重继承,其中不一定是MRO 中的最后一个类。如果你做的事情正确,调用时会为空。super
Price
object
**kwargs
object.__init__
关于您的工厂方法,您可以添加适当的类型提示:
from typing import TypeVar, Type
P = TypeVar('P', bound=Price)
def get_price_object(obj: Type[P] , *args, **kwargs) -> P:
尽管这可能无助于您的 IDE 建议预期的参数名称。
推荐阅读
- c# - 使用 BinaryFormatter 进行序列化时在解析完成之前遇到 C# 流结束或错误值
- c++ - OpenCV Mat 对象复制加速
- java - 无法更新表
- firebase-realtime-database - 在 Firebase 实时数据库中更新一个孩子不会做任何事情
- python - python中的套接字服务器拒绝连接
- neo4j - 在 Neo4j 中加载加权图
- cloud-foundry - 跨 api 端点的路由名称
- java - 如何创建自定义“ExpectedException”junit 规则?
- javascript - JavaScript中一长串整数的转换问题
- python - 可以在管道处理期间从 spaCy 文档中删除令牌吗?