如何在缺货时不添加商品价格?
How to not add an item's price when it is out of stock?
Product
class已定义。
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 var
(if 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
)。
另见
- Martin Fowler,重构:Replace Nested Conditional with Guard Clauses
- Python 文档:Format String Syntax,带有示例
Product
class已定义。
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 var
(if 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
)。
另见
- Martin Fowler,重构:Replace Nested Conditional with Guard Clauses
- Python 文档:Format String Syntax,带有示例