【问题标题】:Error with multiple class inheritance Python多类继承Python的错误
【发布时间】:2021-02-14 06:48:18
【问题描述】:
import matplotlib.pyplot as plt
import numpy as np
import plotly.graph_objects as go # run "pip install plotly==4.9.0" in your terminal to install plotly
import yfinance as yf
import numpy as np
import ast

eurusd = yf.Ticker("EURUSD=X")
usd_to_eur = 1 / (eurusd.info["ask"])
eur_to_usd = 1 * eurusd.info["ask"]

class Asset:
    def __init__(self,name, ticker, amount):
        self.amount = amount
        self.name = name
        self.ticker = ticker
        self.price = yf.Ticker(self.ticker).info["regularMarketPrice"]

class Usd_asset(Asset):
    def __init__(self, name, ticker, amount, buy_price):
        super().__init__(name, ticker, amount)
        self.buy_price = buy_price
        self.buy_price_eur = [x * usd_to_eur for x in self.buy_price]
        self.price_usd = yf.Ticker(self.ticker).info["regularMarketPrice"]
        self.price_eur = self.price_usd * usd_to_eur

class Crypto(Asset):
    def __init__(self, name, ticker, amount):
        super().__init__(name, ticker, amount)
        print("crypto")


class Crypto_Usd(Crypto, Usd_asset):
    def __init__(self, name, ticker, amount, buy_price):
        Usd_asset.__init__(self, name = name, ticker = ticker, amount = amount, buy_price = buy_price)
        Crypto.__init__(self, name = name, ticker = ticker, amount = amount)
        print("crypto usd")

每当我运行它时,我都会得到以下信息:

Attribute Error: Type object 'Usd_asset' has no attribute '_Crypto_Usd__init'

我在这里做错了什么?

我的目标是拥有一个继承自 Crypto 和 Usd_asset 的类。 它们又都继承自 Asset。

【问题讨论】:

  • 请以文字形式分享代码。

标签: python class multiple-inheritance


【解决方案1】:

因为您的实例是 Crypto_Usd,当您使用 super() 时,您没有按预期获得类 Asset => 替换调用 super().__init(...)by @987654323 @

【讨论】:

    【解决方案2】:

    在 Python 3.8.6 中,我无法重现该错误,但出现了其他奇怪的行为:

    class Asset:
      def __init__(self, name):
        print("init Asset")
        self.name = name
    class Usd_asset(Asset):
      def __init__(self, name):
        print("init Usd_asset")
        super().__init__(name)
        print("done Usd_asset")
    class Crypto(Asset):
      def __init__(self, name):
        print("init Crypto", Crypto.__mro__)
        super().__init__(name)
        print("done Crypto")
    class Crypto_Usd(Crypto, Usd_asset):
      def __init__(self, name):
        print("init Crypto_Usd")
        Usd_asset.__init__(self, name = name)
        Crypto.__init__(self, name = name)
        print("done Crypto_Usd")
    
    print("\nCrypto('bar')")
    x = Crypto('bar')
    print("\nCrypto_Usd('foo')")
    a = Crypto_Usd('foo')
    

    输出:

    Crypto('bar')
    init Crypto (<class '__main__.Crypto'>, <class '__main__.Asset'>, <class 'object'>)
    init Asset
    done Crypto
    
    Crypto_Usd('foo')
    init Crypto_Usd
    init Usd_asset
    init Asset
    done Usd_asset
    init Crypto (<class '__main__.Crypto'>, <class '__main__.Asset'>, <class 'object'>)
    init Usd_asset        ## <<<--- strange
    init Asset
    done Usd_asset
    done Crypto
    done Crypto_Usd
    

    问题是在Crypto.__init__() 方法中调用Usd_asset.__init__()__mro__ 表明 Asset 是唯一的超类。

    使用完整代码,我在Crypto.__init__() 中得到一个异常

    __init__() missing 1 required positional argument: 'buy_price'
    

    它尝试调用Usd_asset.__init__()

    解决方案

    不要在用于多重继承的类中使用super()。或者可能永远不要使用super(),因为您不知道该类是否会用于多重继承。

    总是写Class.method(self, arguments)

    class Usd_asset(Asset):
        def __init__(self, name, ticker, amount, buy_price):
            Asset.__init__(self, name, ticker, amount)
            self.buy_price = buy_price
            self.buy_price_eur = [x * usd_to_eur for x in self.buy_price]
            self.price_usd = yf.Ticker(self.ticker).info["regularMarketPrice"]
            self.price_eur = self.price_usd * usd_to_eur
    
    class Crypto(Asset):
        def __init__(self, name, ticker, amount):
            Asset.__init__(self, name, ticker, amount)
            print("crypto")
    

    编辑

    Crypto.__init__()中的super()之所以选择Usd_asset.__init__()是因为super()super(Crypto, self)使用self.__class__.__mro__找到Crypto类的第一个父类。

    如果selfCrypto 的实例

    self.__class__.__mro__ (<class '__main__.Crypto'>, <class '__main__.Asset'>, <class 'object'>)
    

    Asset 将被选中。

    如果selfCrypto_Usd 的实例

    self.__class__.__mro__ (<class '__main__.Crypto_Usd'>, <class '__main__.Crypto'>, <class '__main__.Usd_asset'>, <class '__main__.Asset'>, <class 'object'>)
    

    Usd_asset 将被选中。

    class Crypto(Asset):
      def __init__(self, name):
        print("init Crypto", Crypto.__mro__)
        print("self.__class__.__mro__", self.__class__.__mro__)
        super().__init__(name)
        print("done Crypto")
    

    __mro__ 元组不显示多重继承,因此会产生这种奇怪的行为。

    【讨论】:

    • 非常感谢,这很有意义,解决了我的问题!
    • @Krulke 我找到了super() 问题的原因,如果对您有解决方案,请将其标记为答案
    【解决方案3】:
    import matplotlib.pyplot as plt
    import numpy as np
    import plotly.graph_objects as go # run "pip install plotly==4.9.0" in your terminal to install plotly
    import yfinance as yf
    import numpy as np
    import ast
    
    eurusd = yf.Ticker("EURUSD=X")
    usd_to_eur = 1 / (eurusd.info["ask"])
    eur_to_usd = 1 * eurusd.info["ask"]
    
    class Asset:
        def __init__(self,name, ticker, amount):
            self.amount = amount
            self.name = name
            self.ticker = ticker
            self.price = yf.Ticker(self.ticker).info["regularMarketPrice"]
    
    class Usd_asset(Asset):
        def __init__(self, name, ticker, amount, buy_price):
            super().__init__(name, ticker, amount)
            self.buy_price = buy_price
            self.buy_price_eur = [x * usd_to_eur for x in self.buy_price]
            self.price_usd = yf.Ticker(self.ticker).info["regularMarketPrice"]
            self.price_eur = self.price_usd * usd_to_eur
    
    class Crypto(Asset):
        def __init__(self, name, ticker, amount):
            super().__init__(name, ticker, amount)
            print("crypto")
    
    
    class Crypto_Usd(Crypto, Usd_asset):
        def __init__(self, name, ticker, amount, buy_price):
            Usd_asset.__init__(self, name = name, ticker = ticker, amount = amount, buy_price = buy_price)
            Crypto.__init__(self, name = name, ticker = ticker, amount = amount)
            print("crypto usd")
    

    【讨论】:

    • 这是您问题的答案还是您问题中图片中给出的代码?在第二种情况下,请编辑您的问题以提供该代码并删除该答案(那不是答案)
    • 为什么要导入numpy 两次?为什么需要ast
    • numpy 两次是一个错误,我稍后需要。问题已解决。谢谢大家。
    • @Krulke 请删除而不是未回答,下次编辑您的问题而不是错误地使用答案
    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 2019-03-25
    • 2016-03-06
    相关资源
    最近更新 更多