问题描述
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,amount,buy_price):
super().__init__(name,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,amount):
super().__init__(name,amount)
print("crypto")
class Crypto_Usd(Crypto,Usd_asset):
def __init__(self,buy_price):
Usd_asset.__init__(self,name = name,ticker = ticker,amount = amount,buy_price = buy_price)
Crypto.__init__(self,amount = amount)
print("crypto usd")
每次运行它,我都会得到以下信息:
Attribute Error: Type object 'Usd_asset' has no attribute '_Crypto_Usd__init'
我在做什么错了?
我的目标是要拥有一个既继承自Crypto又继承自Usd_asset的类。 两者都继承自Asset。
解决方法
在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 'object'>)
init Usd_asset ## <<<--- strange
init Asset
done Usd_asset
done Crypto
done Crypto_Usd
问题是在Usd_asset.__init__()
方法内调用Crypto.__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,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,amount):
Asset.__init__(self,amount)
print("crypto")
修改
super()
中的Crypto.__init__()
选择Usd_asset.__init__()
的原因是因为super()
或super(Crypto,self)
使用self.__class__.__mro__
来找到{{ 1}}类。
如果Crypto
是self
的实例
Crypto
self.__class__.__mro__ (<class '__main__.Crypto'>,<class 'object'>)
将被选择。
如果Asset
是self
的实例
Crypto_Usd
self.__class__.__mro__ (<class '__main__.Crypto_Usd'>,<class '__main__.Crypto'>,<class '__main__.Usd_asset'>,<class 'object'>)
将被选择。
Usd_asset
class Crypto(Asset):
def __init__(self,Crypto.__mro__)
print("self.__class__.__mro__",self.__class__.__mro__)
super().__init__(name)
print("done Crypto")
元组不显示多重继承,因此会产生这种奇怪的行为。
因为当您使用super()
时您的实例是 Crypto_Usd ,您没有像预期的那样获得 Asset 类=>替换了调用{{1} }由super().__init(...)
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,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,buy_price):
super().__init__(name,amount):
super().__init__(name,amount)
print("crypto")
class Crypto_Usd(Crypto,Usd_asset):
def __init__(self,buy_price):
Usd_asset.__init__(self,name = name,ticker = ticker,amount = amount,buy_price = buy_price)
Crypto.__init__(self,amount = amount)
print("crypto usd")