[英]Python OOP manipulating two objects in one method
我是Python的新手,試圖了解OOP。 在我的程序中,我希望用戶能夠買賣股票,但是我正在努力實現此功能。 很抱歉,如果問題不大。
用戶類及其一個對象
class User:
def __init__(self, name, budget=None, stocks=None):
self.name = name
self.budget = budget or 1000
self.stocks = stocks or 0
def sell_stock(self):
if self.stocks != 0:
self.stocks -= 1
def buy_stock(self):
self.stocks += 1
u1 = User("Karin", stocks=9)
股票類別及其一個對象
class Stock:
def __init__(self, price, name, availability=None):
self.price = price
self.name = name
self.availability = availability or 1
s1 = Stock("200", "Netflix")
我想編寫一個名為buy_stock()的方法,該方法將執行以下操作:
class Stock:
def __init__(self, price, name, availability=1):
self.price = price
self.name = name
self.availability = availability
class User:
def __init__(self, name, budget=1000,):
self.name = name
self.budget = budget
self.stocks = []
def sell_stock(self, stock):
try:
self.stocks.remove(stock)
stock.availability += 1
self.budget += stock.price
print('{} has sold {} stock for {} dollars'.format(self.name, stock.name, stock.price))
except:
pass
def buy_stock(self, stock):
if self.budget - stock.price >= 0 and stock.availability >= 1:
self.stocks.append(stock)
stock.availability -= 1
self.budget -= stock.price
print('{} has bought {} stock for {} dollars'.format(self.name, stock.name, stock.price))
s1 = Stock(200, "Netflix")
s2 = Stock(300, "SomeStock", availability=2)
u1 = User("Karin", budget=10000)
u1.buy_stock(s2)
u1.sell_stock(s2)
u2 = User("Sam")
u2.buy_stock(s2)
u2.buy_stock(s1)
輸出:
Karin has bought SomeStock stock for 300 dollars
Karin has sold SomeStock stock for 300 dollars
Sam has bought SomeStock stock for 300 dollars
Sam has bought Netflix stock for 200 dollars
當您購買物品時,必須確保它可用並且有預算。 我從構造函數中刪除了股票參數以避免重復,並且只為邏輯buy_stock
一個來源。 最后一點:您不需要or
鍵,因為可以在構造函數中設置默認值。
為了在更現實的情況下考慮它,您將擁有一個Marketplace
對象,其中包含其他用戶可以從中購買股票的所有股票。
這樣,它將在未來的開發中相當容易閱讀和可擴展 。
Marketplace
可以是一個單獨的類,一個包含其他股票對象的字典(如下面的示例),或者是一個與數據庫連接的類(如mongodb)。
選擇哪一個取決於項目。
對於此示例,字典是一種不錯的解決方案,助您一臂之力:
class User:
def __init__(self, name, budget=None, stocks=None):
self.name = name
self.budget = budget or 1000
self.stocks = stocks or 0
def __repr__(self):
# returns a represantion of the object
# so it's more informative of the state
# of this object
return "{} balance: {}".format(
self.name,
self.budget
)
def sells(self, stock_name, amount):
# Increase my budget by the amount of stocks I'm selling
# multiplied by its price.
self.budget += marketplace[stock_name].price * amount
# Send the stocks back into the market and remove them
# from my ownership
marketplace[stock_name].availability += amount
self.stocks -= amount
def buys(self, stock, amount):
# Lower my budget by the stock price
# multiplied by the amount of stock I'm buying
marketplace[stock].availability -= amount
self.budget -= marketplace[stock].price * amount
# Print out the transaction
print("{} has bought {} stock for {} dollars".format(
self.name,
stock,
marketplace[stock].price * amount
))
class Stock:
def __init__(self, price, name, availability=None):
self.price = price
self.name = name
self.availability = availability or 1
# In production like environmnet, you would not do this but would keep in
# mongodb or some other sql/nosql database
# For this example, a kind of javascript dict logic would be alright to use
marketplace = {
"Netflix": Stock(200, "Netflix", 100)
}
u1 = User("Karin", budget=1000, stocks=0)
u1.buys("Netflix", 10)
u1.sells("Netflix", 5)
歡迎來到OOP的世界:)
您想要做的事情很簡單。 由於您要嘗試同時使用兩個類,因此這表明這些類之一應作為函數中的參數使用。 即
class Stock:
# .... basic init function
# we need a function to return the value
# of this stock, and maybe take an argument
# for how many shares we want to value
# so let’s write a function to do that for us
def get_value(self, number_of_shares=1):
return (self.value * number_of_shares)
class User:
#.... basic init function
def buy_stock(self, stock, amount=1):
total_value = stock.get_value(amount)
self.budget = self.budget - total_value
self.stocks = self.stocks + amount
#display what happened
print(“{} bought {} shares of {} for {}”.format(self.name, amount, stock.name, total_value))
然后在實踐中你可以寫
輸入:
# assuming Andrew is a user
# and my_stock is a stock worth $20 a share
Andrew.buy_stock(my_stock, 10)
輸出:
Andrew bought 10 shares of my_stock for $200
但基本上,問題的答案是傳遞一個您希望成為您要使用的類的參數。 因此,您既可以操縱調用方法的User對象,也可以操縱傳遞到方法中的庫存對象。
我認為應該這樣做。 另外,將股票價格的數據類型從字符串更改為整數(或之后進行類型轉換)
class User:
def __init__(self, name, budget=None, stocks=None):
self.name = name
self.budget = budget or 1000
self.stocks = stocks or 0
def sell_stock(self):
if self.stocks != 0:
self.stocks -= 1
def buy_stock(self, stock):
self.budget - stock.price
stock.availability -= 1
self.stocks += 1
print("{} has bought {} stock for {} dollars".format(self.name,stock.name,stock.price))
class Stock:
def __init__(self, price, name, availability=None):
self.price = price
self.name = name
self.availability = availability or 1
s1 = Stock(200, "Netflix")
u1 = User("Karin", stocks=9)
u1.buy_stock(s1)
您需要2種類型的對象: Portfolio
和Stock
。
一個User
可以有多個Portfolio
,並且在示例中僅以其名稱表示。
對於更復雜的模型,您也將Transactions
建模為對象。 您還需要處理庫存價格,佣金和其他成本的變化。
這是一個簡化的示例,演示了對象之間的交互方式:
class Stock:
def __init__(self, ticker, price):
assert price > 0
self.ticker = ticker
self.price = price
def __hash__(self):
return hash(self.ticker)
def __str__(self):
return self.ticker + ', $' + str(self.price) + ':'
class Portfolio:
def __init__(self, owner):
self.owner = owner
self.cash = 0
self.stocks = {} # a mapping of Stock --> quantity
def buy(self, stock, quantity):
if self.cash < stock.price * quantity:
print('Not enough cash to purchase ', quantity, stock)
else:
self.cash -= stock.price * quantity
try:
self.stocks[stock] += quantity
except KeyError:
self.stocks[stock] = quantity
def sell(self, stock, quantity):
assert quantity > 0
try:
if self.stocks[stock] < quantity:
print('Not enough', stock.ticker, 'inventory to sell', str(quantity), stock)
return
self.stocks[stock] -= quantity * stock.price
self.cash += quantity * stock.price
except KeyError:
print('No', stock.ticker, 'inventory to sell')
def __str__(self):
res = [self.owner, "'s Portfolio:\n"]
for stock, quantity in self.stocks.items():
res += [str(stock), ' ', str(quantity), ' -> ', '$', str(quantity*stock.price), '\n']
res += ['cash: ', '$', str(self.cash), '\n']
return ''.join(res)
goog = Stock('GOOG', 325)
alibaba = Stock('ALI', 12)
apple = Stock('AAPL', 42)
pfl = Portfolio('Karin')
pfl.cash = 10000
pfl.buy(goog, 10)
pfl.buy(alibaba, 100)
pfl.sell(apple, 100)
pfl.buy(apple, 10000)
pfl.sell(goog, 10000)
print()
print(pfl)
No AAPL inventory to sell
Not enough cash to purchase 10000 AAPL, $42:
Not enough GOOG inventory to sell 10000 GOOG, $325:
Karin's Portfolio:
GOOG, $325: 10 -> $3250
ALI, $12: 100 -> $1200
cash: $5550
可能是這樣的事情(我並沒有真正弄混“ User”類中的“ stocks”實例變量。我可能會拋棄它,而是維護一個Stock對象列表(您的庫存數量只是該對象的長度)列表)):
class User:
def __init__(self, name, budget=1000, stocks=0):
self.name = name
self.budget = budget
self.stocks = stocks
def sell_stock(self):
if self.stocks:
self.stocks -= 1
def buy_stock(self, stock, quantity=1):
try:
price = stock.request(quantity)
except RuntimeError as error:
raise error
else:
self.budget -= price
self.stocks += quantity
print(f"{self.name} bought ${price} worth of {stock.name} stocks")
class Stock:
def __init__(self, name, price, quantity_available=1):
self.name = name
self.price = price
self.quantity_available = quantity_available
def isAvailable(self):
return self.quantity_available > 0
def request(self, quantity_requested):
if not self.isAvailable():
raise RuntimeError(f"No more {self.name} stocks available")
elif self.quantity_available < quantity_requested:
raise RuntimeError(f"Requested too many {self.name} stocks")
else:
self.quantity_available -= quantity_requested
return self.price * quantity_requested
def main():
user = User("Karin")
stock = Stock("Netflix", 200, quantity_available=6)
user.buy_stock(stock, quantity=3)
user.buy_stock(stock, quantity=2)
user.buy_stock(stock, quantity=1)
user.buy_stock(stock, quantity=1)
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
輸出:
Karin bought $600 worth of Netflix stocks
Karin bought $400 worth of Netflix stocks
Karin bought $200 worth of Netflix stocks
RuntimeError: No more Netflix stocks available
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.