Decimals in python 3 - python

So i've been trying to code a section in my cash-register class. Im trying to make it so that it keeps track of the total price as an integer. so for example 18.66 would be 1866. But i still want it to be considered as 18.66 if that makes sense. this is so that it avoids the accumulation of roundoff errors. But i dont want to change the public interface of the class.
#!/usr/local/bin/python3
class CashRegister :
def __init__(self):
self._itemCount = 0
self._totalPrice = 0.0
def addItem(self, price):
self._itemCount = self._itemCount + 1
self._totalPrice = self._totalPrice + price
def getTotal(self):
return self._totalPrice
def getCount(self) :
return self._itemCount
def clear(self) :
self._itemCount = 0
self._totalPrice = 0.0
wouldn't i simply change the 0.0's to 0's? or would i go along the way of doing a split method and concatenate them back together?

You should keep the data as is.
You can achieve what you want by mean of formatting. If i were you i will add a new function like this:
def getTotalAsString(self):
return "%d" % (self._totalPrice * 100)
This approach will give you more flexibility in the future

Related

Implementing rules in a class python

I am stuck on applying rules in a class like forcing some values to change if some rule is present and so on. However I am unable to pass rules to the class. Here is my code, and what i require:
class Item:
valid_item_dict = {"a":20, "b":30, "c":40, "d":50}
def __init__(self, item_id):
self.item_id = item_id
self.item_cost = Item.valid_item_dict.get(self.item_id)
class checks:
def __init__(self):
self.content = list()
def cheque(self, item):
self.content.append(item)
def totals(self):
self.total = sum([self.item_counter().get(itm)*Item.valid_item_dict.get(itm) for\
itm in list(self.item_counter().keys())])
return self.total
def item_counter(self):
self.item_count_list = [itms.item_id for itms in self.content]
self.item_count_dict = dict((item, self.item_count_list.count(item)) for item in
self.item_count_list)
return self.item_count_dict
# Adding items to the list
item1 = Item("a")
item2 = Item("a")
item3 = Item("a")
item4 = Item("b")
# instatiance of class
cx = checks()
cx.cheque(item1)
cx.cheque(item2)
cx.cheque(item3)
cx.cheque(item4)
cx.totals()
>>> 90 (20*3 (from a) + 1*30 (from b))
In normal cases this works fine but I have a ton of rules which I need to add and I was earlier thinking of adding if-else rules in totals method of "checks" class. But is their a more generalized way to add these rules. Rule is something like if we have 3 types of product a, then the value of 'a' reduces from 20 to 10.
I did go over this question and am trying to use this, but any help would be wonderful. (Python how to to make set of rules for each class in a game)
You may want to use a more direct loop to implement these rules and make your code clearer. I find it easier to maintain complex logic than trying to code golf a 1-line result:
from collections import Counter, namedtuple
Rule = namedtuple("Rule", ["threshold", "newvalue"])
"""rule: if count is greater than or equal to threshold, replace with newvalue"""
class Item:
rules = {'a': Rule(3, 10)}
...
class checks:
...
def totals(self):
counts = Counter(self.content)
self.total = 0
for count in counts:
value = Item.valid_item_dict[count]
rule = Item.rules.get(count, Rule(0, value))
if counts[count] >= rule.threshold:
value = rule.newvalue
self.total += value*counts[count]
return self.total
I'm assuming you want the result of your sample to be 60 and not 90.

dynamic instances of a class object overwriting each other

I have a simple class that stores simple data. The class is as follows.
class DataFormater:
def __init__(self, N, P, K, price):
self.N = N
self.P = P
self.K = K
self.price = price
The code that calls this class is
from DataFormater import DataFormater
#global variables
ObjectList = [0,1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50]
ObjectListCounter = 0
# main
print "enter you N-P-K values, followed by a coma, then the price"
print "example ----> 5 5 5 %50 "
print "return as many values as you want to sort, then enter, 'done!' when done."
while True:
RawData = raw_input()
if RawData == 'done!':
break
else:
ObjectList[ObjectListCounter] = DataFormater
ObjectList[ObjectListCounter].N = int(RawData[0])
# very simple test way of putting first indice in ObjectList[ObjectListCounter].N
ObjectListCounter += 1
print ObjectList[0].N
print ObjectList[1].N
My idea is that ObjectList[0] would create that object '1' that I could call with 1.N
But, when I call these, it seems that I have overwritten the previous instances.
this is what prints...
return as many values as you want to sort, then enter, 'done!' when done.
12
1
done!
1
1
Thanks so much! And I know that my post is messy, I don't exactly know how to make it more "pretty"
So, it looks like you are assigning the actual class (instead of an instance of the class) in your loop. Where you do this:
ObjectList[ObjectListCounter] = DataFormater
I think what you actually want is this
ObjectList[ObjectListCounter] = DataFormater(...insert args here....)
EDIT to address the comments:
Your class init method looks like this:
def __init__(self, N, P, K, price):
That means that to create an instance of your class, it would look like this:
my_formater = DataFormater(1, 2, 3, 4)
You would then be able to access my_formater.N which would have a value of 1.
What you are trying to do instead is access a CLASS level attribute, DataFormater.N. This is generally used in situations where you have a constant variable that does not change between instances of the class. For example:
class DataFormater():
CONSTANT_THING = 'my thing that is always the same for every instance'
You would then be able to access that variable directly from the class, like this:
DataFormater.CONSTANT_THING
I hope that clears things up.

Changing value of class variable python3

Hello im on my journey to understand classes in python, so to make it more fun im trying to make basic text rpg game. Right now im trying to make function which take instance of class as argument and is changing specific attribute of it for example:
class short_sword:
def __init__(self):
self.modf = 1
self.name = "Short Sword"
self.min_dmg = 1 * self.modf
self.max_dmg = 3 * self.modf
self.group = 0
Now im trying to change self.modf value by using function on instance of that class:
def jewel(short_sword):
short_sword.modf = short_sword.modf + 1
After that im creating object and printing values min_dmg and max_dmg before and after usage of that function to check if its works:
item = short_sword(1)
print(str(item.min_dmg))
print(str(item.max_dmg))
jewel(item)
print(str(item.min_dmg))
print(str(item.max_dmg))
but its stays the same 1 for min_dmg and 3 for max_dmg nothing is getting changed, how can i access that variable by function to change it?
English is not my native language so i hope that somebody will understand me Sorry for trouble and thanks for help :P
When you update your modf you don't update min_dmg and max_dmg. You could use an accessor:
class short_sword:
def __init__(self):
self.modf = 1
self.name = "Short Sword"
self.min_dmg = 1 * self.modf
self.max_dmg = 3 * self.modf
self.group = 0
def change_modf(self, newValue):
self.modf = newValue
self.processDmg()
def processDmg(self):
self.min_dmg = 1 * self.modf
self.max_dmg = 3 * self.modf
And then
def jewel(short_sword):
short_sword.change_modf(short_sword.modf + 1)
Because otherwise your properties still have their initial value.
Side note: you use
item = short_sword(1)
But your short_sword class doesn't take any argument in its constructor... What is the 1 supposed to be useful for?

Errors in minor details in a class output

I have two files :
class Account:
def __init__(self,id=0,balance=100.0,AIR=0.0):
self.__id = id
self.__balance = balance
self.__AIR = AIR
def getd(self):
return self.__id
def getbalance(self):
return self.__balance
def getAnnualInterest(self):
return self.__AIR
def setid(self,newid):
self.__id = newid
def setbalance(self,newbalance):
self.__balance = newbalance
def setAnnualInterestRate(self,newrate):
self.__AIR = newrate
def getMonthlyInterestRate(self):
return self.__AIR/12
def getMonthlyInterest(self):
return self.__balance*self.getMonthlyInterestRate()
def withdraw(self,amount):
if amount<=self.__balance:
self.__balance -= amount
def deposit(self,amount):
self.__balance += amount
def __str__(self):
return "Account ID : {0.setid} Account Balance : {0.setbalance} Annual Interest Rate : {0.setAnnualInterestRate}".format(self)
and Test:
from Account import Account
def main():
accountA = Account(0,100,0)
accountA.setid = 1234
accountA.setbalance = 20500
accountA.setAnnualInterestRate = 0.375
print(accountA)
accountA.withdraw(500)
accountA.deposit(1500)
print(accountA)
print(accountA.getMonthlyInterest())
main()
My output is mostly correct but there are two minor deatils which I have gotten wrong and I am not sure where in the code the problem is from.
Account ID : 1234 Account Balance : 20500 Annual Interest Rate : 0.375
Account ID : 1234 Account Balance : 20500(This is supposed to be 21500) Annual Interest Rate : 0.375
0.0(And this is supposed to be 671.875 but somehow I got it wrong)
accountA.setbalance = 20500 doesn't call the setbalance method. It changes the value of the setbalance attribute to 20500 (that is, after this line, accountA.setbalance is no longer a method but an int). Instead, you want accountA.setbalance(20500).
However, what you're doing is profoundly un-pythonic in the first place (you're a Java/C#/C++ programmer, aren't you?). Getters and setters are an anti-pattern in Python: just access and change the id, balance et al. attributes, and make them properties if (and only if) you need to perform computations/checks when setting/accessing them.
In addition, __attribute is not a private attribute in Python. The pythonic way to mark an attribute as "private" is a single leading underscore. However, it's just a convention, and the attribute itself will still be public (everything always is in Python -- it has no concept of visibility modifiers).
This:
accountA.setid = 1234
accountA.setbalance = 20500
accountA.setAnnualInterestRate = 0.375
doesn't call the functions. You actually change functions into variables this way. To call the functions use this notation:
accountA.setid(1234)
accountA.setbalance(20500)
accountA.setAnnualInterestRate(0.375)

An exercise from fundamentals of python [duplicate]

This question already exists:
Closed 11 years ago.
Possible Duplicate:
Fundamentals of Python Chapter 8 project 3
Hi I am a newbie programmer who just started to learn about python.
I have recently posted this same question before and I have solved it but my answer is not exactly what the question is asking.
I need help on why I need to implement a new method even though I could do the other way.
thanks
Question:
The __str__ method of the Bank class returns a string containing the
accounts in random order. Design and implement a change that causes
the accounts to be placed in the string by order of name.
[this is the part where I don't understand]
(Hint: You will also have to define a new method in the SavingsAccount class.)
class Bank(object):
def __init__(self):
self._accounts = {}
def __str__(self):
"""Return the string rep of the entire bank."""
pTemp =[]
for i in xrange(len(SavingsAccount.temp)-1):
if self._accounts.get(SavingsAccount.temp[i]).getName() >= self._accounts.get(SavingsAccount.temp[i+1]).getName():
temp = SavingsAccount.temp[i]
SavingsAccount.temp[i] = SavingsAccount.temp[i+1]
SavingsAccount.temp[i+1] = temp
for i in SavingsAccount.temp:
pTemp.append(self._accounts[i])
return '\n'.join(map(str, pTemp))
def add(self, account):
"""Inserts an account using its PIN as a key."""
self._accounts[account.getPin()] = account
def remove(self, pin):
return self._accounts.pop(pin, None)
def get(self, pin):
return self._accounts.get(pin, None)
def computeInterest(self):
"""Computes interest for each account and
returns the total."""
total = 0.0
for account in self._accounts.values():
total += account.computeInterest()
return total
class SavingsAccount(object):
"""This class represents a Savings account
with the owner's name, PIN, and balance."""
RATE = 0.02
temp = []
def __init__(self, name, pin, balance = 0.0):
self._name = name
self._pin = pin
self._balance = balance
SavingsAccount.temp.append(self)
def __str__(self):
result = 'Name: ' + self._name + '\n'
result += 'PIN: ' + self._pin + '\n'
result += 'Balance: ' + str(self._balance)
return result
def getBalance(self):
return self._balance
def getName(self):
return self._name
def getPin(self):
return self._pin
def deposit(self, amount):
"""Deposits the given amount and returns the
new balance."""
self._balance += amount
return self._balance
def withdraw(self, amount):
"""Withdraws the given amount.
Returns None if successful, or an
error message if unsuccessful."""
if amount < 0:
return 'Amount must be >= 0'
elif self._balance < amount:
return 'Insufficient funds'
else:
self._balance -= amount
return None
def computeInterest(self):
"""Computes, deposits, and returns the interest."""
interest = self._balance * SavingsAccount.RATE
self.deposit(interest)
def main():
bank = Bank()
bank.add(SavingsAccount("Zelda","1003",5000.00))
bank.add(SavingsAccount("Wilma","1001",4000.00))
bank.add(SavingsAccount("Fred","1002",1000.00))
print bank
main()
I think the question expects you to define ordering in the SavingsAccount class, that is, be able to determine whether an instance of SavingAccounts comes after or before another instance of SavingAccount. I don't want to write any spoiler here, but tell me if my hint is not enough ;).
UPDATE
Also, a common source of errors in Python with string ordering : a comes before z which comes before A which comes before Z ...
UPDATE2
more hints ;)
What you really want here is to sort a list of instances of SavingAccount according to a given criteria. There are 2 way to do this kind of thing. You can either :
have the one doing the sorting take care of it
or you can have the instances stored in your list taking care of it.
The second option is usually better because "the class to be sorted" should know better than anybody else how to sort itself (it's about encapsulation : not letting people outside control how your class works). Even though the question is not really clear, and the example is not very good (in my opinion), this is the option they would like you to chose.
The idea is that the Bank should just do something like this :
class Bank(object):
def __str__(self):
"""Return the string rep of the entire bank."""
#get a sorted copy of the list
#using default SavingAccount comparison
pTemp =sorted(self._accounts)
return '\n'.join(map(str, pTemp))
And SavingAccount contains information about how to sort.
You may want to have a look at this article from the PythonInfo Wiki.
Also: http://docs.python.org/reference/datamodel.html#object.__lt__

Categories