繁体   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