Simple Class --> Class property updation - python

I have a simple class. This is the output I got:
>>> print(Customer.total_amount)
1300
but I expected the output to be:
>>> print(Customer.total_amount)
1000
What am I doing wrong?
class Customer:
total_amount = 0
def __init__(self, name, mob, email, amount=None):
self.name = name
self.mob = mob
self.eamil = email
self.amount = 0
def add_amount(self, amount):
self.amount += amount
Customer.total_amount += self.amount
cust1 = Customer("cust1", "8892398598", "ritheshb1#gmail.com")
cust2 = Customer("cust2", "8892498598", "ritheshb2#gmail.com")
cust1.add_amount(100)
cust2.add_amount(200)
cust1.add_amount(300)
cust2.add_amount(400)
print(cust1.amount)
print(cust2.amount)
print(Customer.total_amount)

Change :
Customer.total_amount += self.amount
to
Customer.total_amount += amount

Related

Why am I getting the error 'class FidelityPromo(Promotion):IndentationError: expected an indented block'?

from abc import ABC, abstractmethod
from collections import namedtuple
Customer = namedtuple('Customer', 'name fidelity')
class LineItem:
def __init__(self, product, quantity, price):
self.product = product
self.quantity = quantity
self.price = price
def total(self):
return self.quantity * self.price
class Order:
def __init__(self, customer, cart, promotion=None):
self.customer = customer
self.cart = list(cart)
self.promotion = promotion
def total(self):
if not hasattr(self, '__total'):
self.__total = sum(item.total() for item in self.cart)
return self.__total
def due(self):
if self.promotion is None:
discount = 0
else:
discount = self.promotion.discount(self)
return self.total() - discount
def __repr__(self):
return '<Order total: {:0.2f} due: {:0.2f}>'.format(self.total(), self.due())
class Promotion(ABC):
#abstractmethod
def discount(self, order):
class FidelityPromo(Promotion):
def discount(self, order):
return order.total() * .05 if order.customer.fidelity >= 1000 else 0
class BulkItemPromo(Promotion):
def discount(self, order):
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total() * .1
return discount
class LargeOrderPromo(Promotion):
def discount(self, order):
distinct_items = {item.product for item in order.cart}
if len(distinct_items) >= 10:
return order.total() * .07
return 0
joe = Customer('John Doe', 0)
ann = Customer('Ann Smith', 1100)
cart = [LineItem('banana', 4, .5), LineItem('apple', 10, 1.5), LineItem('watermellon', 5, 5.0)]
Order(joe, cart, FidelityPromo())
I expect this result:
<Order total: 42.00 due: 42.00>

Python, adding a "cashback" for every third iteration

Our professor gave us a problem of adding a "cashback" mechanism for an online store setting. We are tasked to use a parent class and a child class to use inheritance.
Goal: to add 50 after every third purchase
What I have so far:
Parent:
class Shop:
def __init__(self):
self.__balance = 0
def getBalance(self):
return self.__balance
def loadWallet(self, amount):
self.__balance += amount
def purchase(self, amount_val):
if amount_val <= self.__balance:
self.__balance -= amount_val
else:
print("Insufficient Funds")
Child:
class ShopCashBack(Shop):
def __init__(self, base_val=0):
self.__numpurchase = base_val
Shop.__init__(self)
def getPurch(self):
return self.__numpurchase
def purchase(self, amount_val):
self.__numpurchase += 1
Shop.purchase(self, amount_val)
if self.__numpurchase % 3 == 0:
result = self.getBalance() + 50
print(result)
Input:
user = ShopCashBack()
user.loadWallet(5000)
user.purchase(299)
print(user.getBalance())
user.loadWallet(3000)
print(user.getBalance())
user.purchase(4990)
print(user.getBalance())
user.purchase(1607)
print(user.getBalance())
Result:
4701
7701
2711
1154
1104
Desired Result:
where 1154 is 1104 + 50 (the balance after the third purchase)
4701
7701
2711
1154
you need to change child perchase method
from this:
if self.__numpurchase % 3 == 0:
result = self.getBalance() + 50
print(result)
to this:
if self.__numpurchase % 3 == 0:
self.loadWallet(50)
because you don't do anything to balance with result = self.getBalance() + 50 balance stays the same after this line

Calculations in class Student

I have created two classes: Person and Student in different modules. Here is my class Person:
import datetime
class Person:
def __init__(self, name, surname, patronymic, birthdate):
self.name = name
self.surname = surname
self.patronymic = patronymic
self.birthdate = birthdate
def age(self):#this function calculates age of person
today = datetime.date.today()
age = today.year - self.birthdate.year
if today < datetime.date(today.year, self.birthdate.month, self.birthdate.day):
age -= 1
return age
Here is my class Student:
from ClassPerson import Person
class Student(Person):
number_of_group = eval(input("\nInput number of group: "))
summa = 0
amount_of_students = 0
overall_age = 0
def __init__(self, name, surname, patronymic, birthdate, faculty, group, scholarship):
Person.__init__(self, name, surname, patronymic, birthdate)
self.faculty = faculty
self.group = group
self.scholarship = scholarship
if Student.number_of_group == self.group:
Student.summa += self.scholarship
Student.overall_age += Student.age(self)
Student.amount_of_students += 1
#property
def scholarship(self):
return self.__scholarship
#scholarship.setter
def scholarship(self, new_s):
if new_s < 1300:
self.__scholarship = 1300
elif new_s > 4000:
self.__scholarship = 4000
else:
self.__scholarship = new_s
I have one simple problem: I need to calculate for specific group overall sum of scholarships and middle age of students of this group. I do calculations in def __init__. But i also had property and setter to change the amount of scholarship due to conditions. So for example we have 3 students:
student1 = Student(
"Joe",
"Hapfy",
"Canes",
datetime.date(1992, 3, 12),
"Philosophy faculty",
441,
4300
)
student2 = Student(
"Jane",
"Mers",
"Rodrigo",
datetime.date(1998, 4, 29),
"Historical faculty",
441,
2700
)
student3 = Student(
"Pavlo",
"Hornov",
"Andriyovich",
datetime.date(1997, 7, 22),
"Mathematics faculty",
171,
1300
)
I want to change student1 scholarship. For example:
student1.scholarship = 1500
print(student1.scholarship)
But the changes are not saved, cause i do calculations in dev __init__. For example, I input number of group as 441.
result = Student.overall_age/Student.amount_of_students
print("Total sum of scholarships: %d" % Student.summa)
The sum of scholarships will be 4300+2700, but due to setter 4300 will be changed to 4000 and sum will be 6700. But now my student1 scholarship is 1500 and i want to receive result 1500+2700=4200. How can i do such calculations after changes of scholarship? Should I use method or something like that instead of calculations in dev __init__?
The property setter needs to update Student.summa when necessary.
Since the setter needs to read the old value, we can't use it before we initialize the internal __scholarship attribute. So the __init__() method needs to assign directly to the internal attribute, rather than using the setter with self.scholarship.
from ClassPerson import Person
class Student(Person):
number_of_group = eval(input("\nInput number of group: "))
summa = 0
amount_of_students = 0
overall_age = 0
def __init__(self, name, surname, patronymic, birthdate, faculty, group, scholarship):
Person.__init__(self, name, surname, patronymic, birthdate)
self.faculty = faculty
self.group = group
self.__scholarship = scholarship
if Student.number_of_group == self.group:
Student.summa += self.scholarship
Student.overall_age += Student.age(self)
Student.amount_of_students += 1
#property
def scholarship(self):
return self.__scholarship
#scholarship.setter
def scholarship(self, new_s):
old_s = self.__scholarship
if new_s < 1300:
self.__scholarship = 1300
elif new_s > 4000:
self.__scholarship = 4000
else:
self.__scholarship = new_s
# Adjust Student.summa by the change in scholarship
if self.group == Student.number_of_group:
Student.summa += self.__scholarship - old_s

Printing sum of list items

What I need is to print the total a person has spent on products, I know the code is horrible but that's how I received the assignment. Never worked with Python so it's all a little mystery for me.
My result so far
The outcome should be 950 for Jeroen, 1175 for Martijn and 800 for Bart without printing them individually.
#start opdracht3 class
class opdracht3:
#start product class
class Product:
#constructor
def __init__(self, productname, price):
self.productname = productname
self.price = price
#end product class
#person class
class Person:
#constructor
def __init__(self, name, email, productlist):
self.name = name
self.email = email
self.productlist = productlist
#adding products to person's collection
def buyItem(self, item):
self.productlist.append(item)
#end person class
#collection of persons
persons = []
#defining person1 with the items he has bought
productlist1 = []
person1 = Person("Jeroen","jbm.mutsters#avans.nl", productlist1)
product1 = Product("Moto G7",150)
person1.buyItem(product1)
product3 = Product("iPhone",800)
person1.buyItem(product3)
#defining person2 with the items he has bought
productlist2 = []
person2 = Person("Martijn","m.dereus1#avans.nl", productlist2)
product2 = Product("iPhone",800)
person2.buyItem(product2)
product5 = Product("iPad",375)
person2.buyItem(product5)
#defining person2 with the items he has bought
productlist3 = []
person3 = Person("Bart","b.linsen#avans.nl", productlist3)
product4 = Product("iPhone",800)
person3.buyItem(product2)
#add person1 and person2 to the persons collection
persons.append(person1)
persons.append(person2)
persons.append(person3)
#generating output
for p in persons:
print(p.name)
for i in p.productlist:
print(i.productname)
print(i.price)
print("-----------------")
print("einde output")
print("***************")
#end generating output
#end opdracht3 class
Thanks in advance.
You can use the built-in sum to find the sum, and a list comprehension to get the prices from the items:
sum([x.price for x in p.productlist])
Same but in as a instance method:
class Person:
def __init__(self, name, email, productlist):
self.name = name
self.email = email
self.productlist = productlist
def buyItem(self, item):
self.productlist.append(item)
def get_sum_spend(self):
return sum([product.price for product in self.productlist])
Also, camel case methods naming typically is not used in Python. You can read more in pep8.
I added the method sum_product_prices to the person class which adds up the prices of the products in the persons productlist. Add the persons to the list persons and print out the return value of sum_product_prices. I removed the opdracht 3 class because it is not used.
#start product class
class Product:
#constructor
def __init__(self, productname, price):
self.productname = productname
self.price = price
#end product class
#person class
class Person:
#constructor
def __init__(self, name, email, productlist):
self.name = name
self.email = email
self.productlist = productlist
#adding products to person's collection
def buy_item(self, item):
self.productlist.append(item)
def sum_product_prices(self):
sum = 0
for product in self.productlist:
sum += product.price
return sum
#end person class
#collection of persons
persons = []
#defining person1 with the items he has bought
productlist1 = []
person1 = Person("Jeroen","jbm.mutsters#avans.nl", productlist1)
product1 = Product("Moto G7",150)
person1.buy_item(product1)
product3 = Product("iPhone",800)
person1.buy_item(product3)
persons.append(person1)
productlist2 = []
person2 = (Person("Martijn","x#y.com",productlist2))
person2.buy_item(product3)
product4 = Product("iPad",375)
person2.buy_item(product4)
persons.append(person2)
productlist3 = []
person3 = Person("Bart","a#b.com",productlist3)
person3.buy_item(product4)
persons.append(person3)
for person in persons:
print(person.name + " " + str(person.sum_product_prices()))

Set object attribute based on zipped attribute, value pairs

How would you simplify calculate_commission() if the commission percentages for each attribute was defined by the zipped list and the length of the zipped list could potentially increase (ex. ...('price_201', 2.3),) ?
zipped_price_and_commission = [
('price_4', .04),
('price_3', .034),
('price_2', .029),
('price_1', .021),
]
class Price:
def __init__(self, **kwargs):
self.price = kwargs.get('price')
self.price_1 = 2
self.price_2 = 2.5
self.price_3 = 3
self.price_4 = 5
def calculate_commission(self):
if self.price >= self.price_4:
commission = .04
elif self.price >= self.price_3:
commission = .034
elif self.price >= self.price_2:
commission = .029
elif self.price >= self.price_1:
commission = .021
else:
commission = 0
setattr(self, 'commission', commission)
IN: price = Price(price=3.3)
IN: price.calculate_commission()
IN: print(price.commission)
OUT: 0.034
In the first place, you should define all attributes in the init function. For example, you would get an error if someone tried to access the commission attribute without checking it first. So, just to be sure, you should initialize it with something.
Assuming that there is no need to have the commission as a zipped list, you can just do it like this:
comission = [ 0.04, 0.034, 0.029, 0.021]
class Price:
def __init__(self, cost):
self.price = cost
self.prices = [5,3,2.5,2]
self.commission = 0
def calculate_commission(self):
for index, prc in enumerate(self.prices):
if self.price >= prc:
self.commission = comission[index]
break
price = Price()
price.calculate_commission()
print(price.commission)
However, if you do need a zipped list, you can change the self.comission line to
self.commission = zipped_price_and_commission[index][1]
Edit: after seeing your update: If the number of commissions increases, you just have to update the self.prices variable to reflect them. You should also pass the prices as an argument to the class, instead of setting it inside the class
You can use a dictionary:
commissions = {
'price_4': .04,
'price_3': .034,
'price_2': .029,
'price_1': .021}
Then, in calculate_commission():
def calculate_commission(self):
if self.price >= self.price_4:
commission = commissions['price_4']
elif self.price >= self.price_3:
commission = commissions['price_3']
elif self.price >= self.price_2:
commission = commissions['price_2']
elif self.price >= self.price_1:
commission = commissions['price_1']
else:
commission = 0
setattr(self, 'commission', commission)
zipped_price_and_commission = [
('price_4', .04),
('price_3', .034),
('price_2', .029),
('price_1', .021),
]
class Price:
def __init__(self, **kwargs):
self.price = kwargs.get('price')
self.price_1 = 2
self.price_2 = 2.5
self.price_3 = 3
self.price_4 = 5
self.priceData = { 'price_4': 5,'price_3': 3,'price_2': 2.5,'price_1': 2}
def calculate_commission(self):
commission = 0
for price , commision in zipped_price_and_commission:
if self.price >= self.priceData[price]:
commission = commision
break
setattr(self, 'commission', commission)
price = Price(price=3.3)
price.calculate_commission()
print(price.commission)

Categories