在 Python 中将派生类转换为基类

Convert derived class to base class in Python

提问人:yEmreAk.com 提问时间:4/16/2022 更新时间:11/10/2023 访问量:1013

问:

class Option:
    order_type: str
    pair: str

    def __init__(self, pair, order_type) -> None:
        self.order_type = order_type
        self.pair = pair

class Order(Option):

    price: float
    quantity: float
    
    def __init__(self, pair, order_type, price, quantity) -> None:
        Option.__init__(self, pair, order_type)
        self.price = price
        self.quantity = quantity


order = Order("btcusdt", "sell", "1", "1")

我想从对象中得到喜欢。optionorder

option = order as Option
order.option
python-3.x 转换 多态性 downcast

评论

0赞 Code-Apprentice 4/16/2022
“我想从物体中得到喜欢。”为什么?拿到它后你会怎么处理?optionorderoption
1赞 Code-Apprentice 4/16/2022
另外,为什么派生?请记住,继承描述了一种“is-a”关系。说“订单是一种选择”有意义吗?还是说“订单选择”更有意义?如果是后者,则应在类中包含一个字段,而不是使用继承。OrderOptionoptionOrder
0赞 yEmreAk.com 4/17/2022
你是对的。也许是我误解了继承关系。我会在订单类中包含选项字段,非常感谢:)

答:

0赞 Floh 4/16/2022 #1

这与 Python 中的继承工作方式不同。

一种选择是让类方法重新创建 Option 对象。

class Option:
    order_type: str
    pair: str

    def __init__(self, pair, order_type) -> None:
        self.order_type = order_type
        self.pair = pair

    @classmethod
    def from_order(cls, the_order):
        the_obj = cls(the_order.pair, the_order.order_type)
        return the_obj


class Order(Option):

    price: float
    quantity: float

    def __init__(self, pair, order_type, price, quantity) -> None:
        Option.__init__(self, pair, order_type)
        self.price = price
        self.quantity = quantity

我必须承认,我没有看到具体的例子应该有用。

评论

0赞 yEmreAk.com 4/17/2022
也许是我误解了继承关系。我会在订单类中包含选项字段,非常感谢:)
1赞 Shadi 11/8/2023 #2

对于那些因同一问题而登陆此处但不特定于此示例的用户,请使用 .它通常在类成员函数中使用(检查使用 super 的正确方法(参数传递)),但这里有一些从类外部使用它的示例:super(...)

# create some classes with inheritance to test
class A:
    x="a"
class B(A):
    x="b"
class C(B):
    x="c"
class D(C):
    x="d"
    
# Casting types to parents via explicit class name
assert A().x=='a'
assert B().x=='b'
assert super(B, B()).x=='a' # << cast B to A
assert super(C, C()).x=='b' # << cast C to B
assert super(B, C()).x=='a' # << cast C to A
assert super(D, D()).x=='c' # << cast D to C
assert super(C, D()).x=='b' # << cast D to B
assert super(B, D()).x=='a' # << cast D to A

# create an unrelated class
class X:
    x="x"

# cast C to X fails because C is unrelated to X
try:
    super(X, B())
except TypeError as e:
    assert str(e)=="super(type, obj): obj must be an instance or subtype of type"

# Casting types to parent via "__bases__"
# Ref:
#   List all base classes in a hierarchy of given class?
#   https://stackoverflow.com/questions/1401661/list-all-base-classes-in-a-hierarchy-of-given-class
assert A.__bases__==(object,)
assert B.__bases__==(A,)
assert C.__bases__==(B,)
assert D.__bases__==(C,)
assert super(C.__bases__[0], C()).x=='a' # << cast C to A
assert super(D.__bases__[0], D()).x=='b' # << cast D to B
assert super(D.__bases__[0].__bases__[0], D()).x=='a' # << cast D to A

# Note that "type(super(...))" returns "super" instead of the class name
# Not sure how to fix that (maybe in combination with __bases__?)
assert type(super(B, B()))==super

# Casting ***instances*** to parents (super(...) returns types, not instances)
b1=B()
assert b1.x=="b"
b1.__class__=A # cast instance of B to A with __class__, ref: https://stackoverflow.com/a/50465583/4126114
assert b1.x=="a"

# create multi-class inheritance (inherit from two classes)
class E(C, X):
    x="e"
    
# Casting types
assert E().x=='e'
assert super(E, E()).x=='c' # cast E to C

# cast type E to X via super doesnt work
try:
    super(X, E()).x
except AttributeError as e:
    assert str(e)=="'super' object has no attribute 'x'"

assert super(C, E()).x=='b' # cast E to B
assert super(B, E()).x=='a' # cast E to A

# cast type E to parent of D (which is also the parent of E) doesn't work, even though they're both C
try:
    super(D, E()).x
except TypeError as e:
    assert str(e) == "super(type, obj): obj must be an instance or subtype of type"

# Casting ***instances***
e1=E()
e1.__class__=C # cast E to C
assert e1.x=="c"
e1.__class__=X # cast E to X (it works with instances, but didn't work with types)
assert e1.x=="x"