python - Using __init__ in OOP
问题描述
I am learning to develop code using OOP. However I am having issues understanding when to use the __init__
constructor. Is __init__
mandatory in OOP? If so how would I use __init__
?
What the following code does is takes the users requested pizza size and toppings and returns and final total.
When I run the following code:
class Pizza:
""" customer orders pizza size and pizza toppings"""
def size_menu(self): # Provides user a menu
self.menu_s = """
What size pizza would you like?
_____________________________________________________________
| 1: Small | 2: Large | 3: Extra Large | 4: Party Size |
| $6.23 | $10.23 | $12.23 | $24.23 |
|___________|____________|__________________|________________|
"""
print(self.menu_s)
return self.menu_s
def size_order(self): # Gets size wanted and returns pizza total.
size_mappings = {
1: "Small",
2: "Large",
3: "Extra Large",
4: "Party Size"
}
cost_mappings = {
"Small": 6.23,
"Large": 10.23,
"Extra Large": 12.23,
"Party Size": 24.23
}
response = input('-') # user inters 1-4 for pizza size wanted and returns a size total.
self.size_wanted = float(response) # Turns response as a float
self.size_wanted = size_mappings[self.size_wanted] # Size requested
self.size_cost = cost_mappings[self.size_wanted] # Cost of size
print(f"Getting your {self.size_wanted} pizza ready.")
print(f"Your current total is: ${self.size_cost}")
return self.size_cost
def topping_menu(self): # Provides user with toppings menu
self.menu_t = """
What toppings do you want on your pizza?
_____________________________________________________
| 1:Bacon | 4:Anchovies | 7:Black Olives |
| 2:Pepperoni | 5:Spinach | 8:Chicken |
| 3:Mushrooms | 6:Onions | 9:Ground Beef |
|________________|__________________|_________________|
What toppings do you want on your pizza?
"""
print(self.menu_t)
return self.menu_t
def topping_order(self): # Gets toppings the user wants and returns a total of all toppings.
topping_mappings = {
1: 'Bacon',
2: 'Pepperoni',
3: 'Mushrooms',
4: 'Anchovies',
5: 'Spinach',
6: 'Onions',
7: 'Black Olives',
8: 'Chicken',
9: 'Ground Beef'
}
self.requested_toppings = []
while True:
response = input('-')
if response == 'q':
break
toppings_wanted = response
toppings_wanted = topping_mappings[int(toppings_wanted)]
self.requested_toppings.append(toppings_wanted)
if toppings_wanted in topping_mappings.values():
print(f"Adding: {toppings_wanted}")
else:
print(f"We do not have {toppings_wanted}")
self.topping_total = len(self.requested_toppings) * float(1.23)
print("\nWe are adding the requested toppings to your pizza.")
print(f"your topping total will be: ${self.topping_total}")
return self.topping_total
def final_total(self):
total = self.size_cost + self.topping_total
total = float(total)
print(f"\nYour final order total will be ${total}")
if __name__ == '__main__':
customer_order = Pizza()
customer_order.size_menu()
customer_order.size_order()
customer_order.topping_menu()
customer_order.topping_order()
customer_order.final_total()
I am wondering why would I use the __init__
constructor if the program is returning the information I am seeking?
Thank you for the assistance.
解决方案
虽然此代码有效,但它的可扩展性和可重用性都不是很高。
如果明天您希望允许使用来自 json 文件的输入而不是用户输入来订购比萨饼怎么办?
如果您忘记调用其中一种order
方法怎么办?调用final_total
会使您的程序崩溃,因为某些属性会丢失。
此外,在方法之外创建属性被认为是一种反模式,__init__
因为它使代码不可读、难以理解和难以使用(目前,并非所有Pizza
实例都始终具有相同的属性)。
如何让它变得更好
将所有硬编码的永久值移动为类属性。这些将在 的所有实例之间共享
Pizza
。获取成为in
Pizza
所需的所有参数。这些对于每个.Pizza
__init__
Pizza
实现可能的排序方法
Pizza
。其中之一可能是from_user_input
。
请注意,此代码可能使用比您目前可能知道的更高级的 Python 概念。以此为契机学习。它远非完美(例如,它缺少一些非常基本的错误检查和处理),但它是一个很好的起点。
class Pizza:
size_mappings = {
1: "Small",
2: "Large",
3: "Extra Large",
4: "Party Size"
}
cost_mappings = {
"Small": 6.23,
"Large": 10.23,
"Extra Large": 12.23,
"Party Size": 24.23
}
cost_per_topping = 1.23
topping_mappings = {
1: 'Bacon',
2: 'Pepperoni',
3: 'Mushrooms',
4: 'Anchovies',
5: 'Spinach',
6: 'Onions',
7: 'Black Olives',
8: 'Chicken',
9: 'Ground Beef'
}
size_menu = """
What size pizza would you like?
1: Small ${Small}
2: Large ${Large}
3: Extra Large ${Extra Large}
4: Party Size ${Party Size}\n\n"""
def __init__(self, size_wanted, requested_toppings):
self.size_wanted = size_wanted
self.requested_toppings = requested_toppings
def finalize_order(self):
cost = self.cost_mappings[self.size_mappings[self.size_wanted]] + len(self.requested_toppings) * self.cost_per_topping
print("Thanks for ordering. The final cost is {}".format(cost))
@classmethod
def show_size_menu(cls):
return cls.size_menu.format(**cls.cost_mappings)
@classmethod
def show_toppings_menu(cls):
return "What toppings would you want on your Pizza?\n{}".format(
'\n'.join('{}: {}'.format(k, v) for k, v in cls.topping_mappings.items())
)
@classmethod
def from_user_input(cls):
size_wanted = int(input(cls.show_size_menu()))
requested_toppings = []
print(cls.show_toppings_menu())
print("Type requested toppings' numbers, and 'q' when done")
while True:
req_topping = input()
if req_topping == 'q':
break
try:
requested_toppings.append(int(req_topping))
except ValueError:
print('Only numbers or q')
return cls(size_wanted, requested_toppings)
p = Pizza.from_user_input()
p.finalize_order()
好处:
所有常量值都在一个位置,就在
class Pizza
. 如果我们需要改变某些东西,我们确切地知道它在哪里。该类
Pizza
与创建方法解耦,并不依赖于我们每次创建实例时都以正确的顺序调用 5 个方法。如果明天有人要求我们从 json 文件创建一个
Pizza
,那只是实现def from_json_file
.
上述代码的示例执行:
What size pizza would you like?
1: Small $6.23
2: Large $10.23
3: Extra Large $12.23
4: Party Size $24.23
2
What toppings would you want on your Pizza?
1: Bacon
2: Pepperoni
3: Mushrooms
4: Anchovies
5: Spinach
6: Onions
7: Black Olives
8: Chicken
9: Ground Beef
Type requested toppings' numbers, and 'q' when done
1
3
7
q
Thanks for ordering. The final cost is 13.92
推荐阅读
- html - 使用 bootstrap 4 以移动设备为中心但不在桌面模式下的图像的 Div
- webpack - 如何调试 chunk.isInitial() 不是函数
- javascript - PATCH 调用不适用于动态生成的用户列表编辑按钮
- php - 无法加载动态库“pdo_mysql”
- c# - 使用列表的 Linq 过滤器
- javascript - Typescript的Javascript导入-导出默认对象
- python - Pandas:PeriodIndex 与年份开始锚定偏移
- php - WKHTMLTOPDF(knplabs - snappy)不显示页眉或页脚页面
- java - 如何将回调值放入主方法?
- python - 在 pandas/numpy 中运行应用函数时访问元素的 2D 索引?