如何在缺货时不添加商品价格?

How to not add an item's price when it is out of stock?

Productclass已定义。

class Product:
    def __init__(self, code, description, price=1.0, quantity=1):
        self.code = int(code)
        self.description = str(description)
        self.price = float(price)
        self.quantity = int(quantity)
    
    def __str__(self):
        if self.quantity == 0:
            return ("Code = {}, {} - Out of Stock".format(self.code, self.description))
        else:
            return ("Code = {}, {}, ${:.2f}, quantity = {}".format(self.code, self.description, self.price, self.quantity))
        
        

我还定义了另一个 class - PurchaseProduct 这里我在 purchasing(self, search_code) 方法中遇到问题。此方法的作用是将代码值作为参数,如果搜索代码存在于购物项目列表中并且该项目可用(即数量 > 0),则将数量值减 1。它还打印该项目的描述和价格(小数点后两位)。该方法调用 search() 方法。

如果搜索代码项目存在但不可用,该方法应打印消息 'XXX Out of Stock!',其中 XXX 表示项目代码。如果搜索模式不存在,该方法应该打印消息“XXX Not Found!”其中 XXX 表示项目代码。最后,方法 returns 商品的价格(如果商品存在且可用)。

class PurchaseProduct:
    def __init__(self, filename = 'items.txt'):
        self.filename = filename
        PurchaseProduct.items_list = []
        
    def read_item_file(self):
        try:
            file = open(self.filename, 'r')
            res = file.read()
            content_list = res.split('\n')
            
        except FileNotFoundError:
            print ("ERROR: The file '{}' does not exist.".format(self.filename))
            return 0
            
        else:
            file.close()
            return res_list
    
    def load_items(self):
        try:
            list_items = self.read_item_file()
            for item in list_items:
                code, desc, price, quant = item.split(',')
                self.items_list.append(Product(code= int(code), description= str(desc), price=price, quantity= int(quant)))
        except:
            list_items = []
            
    def search(self, search_code): 
        self.search_code = search_code
        for index in range(len(PurchaseProduct.items_list)):
            if PurchaseProduct.items_list[index].code == self.search_code:
                return (PurchaseProduct.items_list[index])
   

     def purchasing(self, search_code): #ISSUE HERE
            self.search_code = search_code
            for index in range(len(PurchaseProduct.items_list)):
                if self.search(search_code) != None: 
                    if PurchaseProduct.items_list[index].quantity >= 1:
                        print ("{} ${:.2f}".format(PurchaseProduct.items_list[index].description,PurchaseProduct.items_list[index].price))
                        PurchaseProduct.items_list[index].quantity -= 1
                        return PurchaseProduct.items_list[index].price
                    else:
                        print ("{} Out of Stock!".format(PurchaseProduct.items_list[index].code))
                        return PurchaseProduct.items_list[index].price
            else:
                print ("{} Not Found!".format(self.search_code))
                return PurchaseProduct.items_list[index].price

测试:

shop_cart = PurchaseProduct('item.txt')
shop.load_items()
cost = shop_cart.purchasing(11)
cost += shop_cart.purchasing(11)
print(cost)
cost += shop_cart.purchasing(11)
print(cost)
cost += shop_cart.purchasing(999)
print(cost)

预期输出:

Coca Cola Soft Drink 500ml .00
Coca Cola Soft Drink 500ml .00
8.0
11 Out of Stock!
8.0
999 Not Found!
8.0

实际输出:

Coca Cola Soft Drink 500ml .00
Coca Cola Soft Drink 500ml .00
8.0
11 Out of Stock!
12.0
999 Not Found!
14.0

'item.txt' 的内容:

11,Coca Cola Soft Drink 500ml,4,2
12,L & P Soft Drink Lemon & Paeroa 500ml,4,9
13,V Blue Drink can 500mL,3.5,8
14,V Vitalise Energy Drink 500ml,3.5,5
15,Pump Water NZ Spring 750ml,2.5,9
16,Twix Chocolate Bar 50g,2.5,12
17,Nestle Kit Kat Chocolate Bar 4 Finger, 2.4,15
18,Snickers Chocolate Bar 50g,2,11
19,Cadbury Chocolate Bar Crunchie 50g, 2,13
20,Cadbury Picnic Chocolate Bar 46g,2,15

在您的具体情况下,您似乎可以在商品缺货时简单地 return 0,因为它不会改变总成本。

if PurchaseProduct.items_list[index].quantity >= 1:
    print("{} ${:.2f}".format(PurchaseProduct.items_list[index].description,PurchaseProduct.items_list[index].price))
    PurchaseProduct.items_list[index].quantity -= 1
    return PurchaseProduct.items_list[index].price
else:
    print ("{} Out of Stock!".format(PurchaseProduct.items_list[index].code))
    return 0

这应该很容易修复。只需将 purchasing 函数的最后一行替换为

return 0

因为您只想 return 价格(如果存在)。

有货时为价格,否则为 0

我会:

  • 提取找到的 item 供以后多次重复使用
  • guard clause(也称为 guard 语句)分隔不愉快的路径(反转 if)
  • 使用 f-strings 进行格式化(Python 3.6+ 要求)
item = PurchaseProduct.items_list[index]  # to reuse later
# guard statement, fail fast
if item.quantity < 1:
    print(f"{item.code} Out of Stock!")
    return 0

# the expected, happy case
print(f"{item.description}: {item.price:.2f}$")
item.quantity -= 1
return item.price

结构改进

也许可以为该功能定义一个函数(减少库存和 return 价格)。查看您的代码 index 是如何确定的,我们可以在 search 函数中看到它,其中找到的项目被 returned 为: PurchaseProduct.items_list[index]

我们在进一步设计时考虑到这一点item-operations,比如提现或评估价格的功能:

def priceAndWithdrawFromStock(item):
   if item.quantity < 1:
       print(f"{item.code} Out of Stock!")
       return 0

   print(f"{item.description}: {item.price:.2f}$")
   item.quantity -= 1
   return item.price

然后在循环中使用它或者重构purchasing函数体后剩下的:

def purchasing(self, search_code): #ISSUE HERE
    found_item = self.search(search_code)  # either item or None returned
    if not found_item:  # guard for not-found
        print (f"{search_code} Not Found!")  # safer to rely on param instead of self.search
        return 0

    return priceAndWithdrawFromStock(found_item)

注:guard-clause为not-found(倒置if),f-string,不需要for-loop,var == None等于not varif var 等于 if var != None

.. 并删除了属性的重复赋值,因为它之前已经由 search 函数设置: self.search_code = search_code

重复使用 Product 字符串

查看 pre-defined 产品 class,尤其是 dunder-method __str__,其中 return 是您的产品或项目的字符串表示形式。

您可以在某些情况下重复使用它,例如像 print(item)

一样打印
  • 改为print ("{} Out of Stock!".format(PurchaseProduct.items_list[index].code))
  • 改为print ("{} ${:.2f}".format(PurchaseProduct.items_list[index].description,PurchaseProduct.items_list[index].price))

只要item存在(item != None)Python的built-inprint函数就会调用__str__方法获取用于打印的项目的字符串表示(独立于 stock-status,请参阅 __str__ 中的 if)。

另见