簡體   English   中英

Python OOP用一種方法處理兩個對象

[英]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()的方法,該方法將執行以下操作:

  • u1.budget-s1.price
  • u1.stocks + = 1
  • s1.availability-= 1
  • 將顯示用戶購買的股票的價格和名稱,因此我將看到一條消息“ {Karin}以{200}美元購買了{Netflix}股票。”
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種類型的對象: PortfolioStock
一個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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM