3

I'm trying to learn how to code in python, but am having trouble on finding ways to create custom classes online. I wrote a program in java and I am trying to convert it in python. I think I have the custom class down (I'm not sure), and I'm definitely having trouble with the driver.

my custom class (python):

class CostCalculator:
    __item = ""
    __costOfItem = 0.0
    __tax = 0.0
    __tip = 0.0

    def set_item(self, item):
        self.__item = item
    def get_name(self):
        return self.__item

    def set_costOfItem(self, costOfItem):
        self.__costOfItem = costOfItem
    def get_costOfItem(self):
        return self.__costOfItem

    def get_tax(self):
        __tax = self.__costOfItem * .0875
        return self.__tax

    def get_tip(self):
        __tip = self.__costOfItem * .15
        return self.__tip

My python driver attempt

import sys
from CostCalculator import CostCalculator

item = ""
cost = 0.0
totalTip = 0.0
totalTax = 0.0
overallTotal = 0.0
subtotal = 0.0

print("Enter the name of 3 items and their respective costs to get the total value of your meal")
print ("\n Enter the name of your first item: ")
item = sys.stdin.readline()
print("How much is " + item + "?")
cost = sys.stdin.readLine()

My java custom class and driver:

public class TotalCost
{
   String item = " ";
   double costOfItem = 0;
   double tax = 0;
   double tip = 0;

   public void setItem ( String i )
   {
       item = i;
    }

   public String getItem()
   {
       return item;
    }

   public void setCostOfItem ( double c )
   {
       costOfItem = c;
    }

   public double getCostOfItem ()
   {
       return costOfItem;
    }

   public double getTax ()
   {
       double tax = costOfItem * .0875;
       return tax;
    }

   public double getTip()
   {
      double tip = costOfItem * .15;
      return tip;
    }

   public String toString()
   {
      String str;
        str = "\nMeal: " + getItem() +
        "\nCost of " + getItem() + ": " + getCostOfItem() +
        "\nTax of " + getItem() + ": " + getTax() +
        "\nTip of " + getItem() + ": " + getTip();
      return str;

    }

}

import java.util.Scanner;
public class Driver
{
    public static void main (String args[])
    {
        Scanner input = new Scanner (System.in);

        String item ;
        double cost ;
        double totalTip = 0;
        double totalTax = 0;
        double OverallTotal = 0;
        double subtotal;
        TotalCost a = new TotalCost ();
        TotalCost b = new TotalCost ();
        TotalCost c = new TotalCost ();

        System.out.println("Enter the name of 3 items and their respective costs to get the total value of your meal");
        System.out.println("Enter the name of your first item: ");
        item = input.nextLine();
        a.setItem ( item );
        System.out.println("How much is " + a.getItem() + "?" );
        cost = input.nextDouble();
        a.setCostOfItem (cost);

        input.nextLine();

        System.out.println("Enter the name of your second item: ");
        item = input.nextLine();
        b.setItem (item);
        System.out.println("How much is a " + b.getItem() + "?");
        cost = input.nextDouble();
        b.setCostOfItem (cost);

        input.nextLine();

        System.out.println("Enter the name of your third item: ");
        item = input.nextLine();
        c.setItem (item);
        System.out.println("How much is a " +c.getItem() + "?" );
        cost = input.nextDouble();
        c.setCostOfItem(cost);

        System.out.println(a + "\n" + b + "\n" + c);
        subtotal = a.getCostOfItem() + b.getCostOfItem() + c.getCostOfItem();
        totalTip = a.getTip() + b.getTip() + c.getTip();
        totalTax = a.getTax() + b.getTax() + c.getTax();
        OverallTotal = subtotal + totalTip + totalTax;

        System.out.println("\n\tSubtotal: $" + subtotal);
        System.out.println("\tTax: $" + totalTax);
        System.out.println("\tTip: $" + totalTip);
        System.out.println("\tMeal Total: $" + OverallTotal);
    }   
}
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
Jamie Vu
  • 31
  • 1
  • 4
  • For future reference [How do I format my code blocks?](https://meta.stackexchange.com/questions/22186/how-do-i-format-my-code-blocks) – Cory Kramer Jun 03 '15 at 11:36

3 Answers3

3

In Python, there is no notion of public vs private, everything is public so you do not need setters or getters.

What you do need is the __init__ function, which is similar to a constructor. You can initialize the member variables here so they are not static and shared among all instances of your class. You can also add default arguments so you many pass in any, all, or none of the arguments to the class upon instantiation.

class CostCalculator:
    def __init__(self, item = "", cost = 0.0):
        self.item = item
        self.cost = cost

    def __str__(self):
        return 'Meal: {item}\nCost of {item}: {cost}\nTax of {item}: {tax}\nTip of {item}: {tip}'.format(item = self.item, cost = self.cost, tax = self.calc_tax(), tip = self.calc_tip())

    def calc_tax(self):
        return self.cost * 0.0875

    def calc_tip(self):
        return self.cost * 0.15

    def calc_total(self):
        return self.cost + self.calc_tax() + self.calc_tip()

Then you can create an instance of this class. Again note that you can directly access the members without setters or getters, for better or worse ;)

>>> c = CostCalculator('cheese', 1.0)
>>> c.item
'cheese'
>>> c.calc_tip()
0.15

Now you can invoke print on your object

>>> c = CostCalculator('cheese', 1.0)
>>> print(c)
Meal: cheese
Cost of cheese: 1.0
Tax of cheese: 0.085
Tip of cheese: 0.15

Lastly, the way you accept input from a user is generally via input (although messing around with stdin isn't necessarily wrong)

>>> tax = input('how much does this thing cost? ')
how much does this thing cost? 15.0
>>> tax
'15.0'
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • 1
    Note that on Python versions before 3.x you should prefer `raw_input()` over `input()` -- `input()` evals the text being entered and presents a security risk -- see e.g. http://stackoverflow.com/questions/7709022/is-it-ever-useful-to-use-pythons-input-over-raw-input – bgporter Jun 03 '15 at 12:05
  • What if I wanted to set tax as a rate x costOfItem instead of just a static value? Would I keep it in its initializing method? – Jamie Vu Jun 03 '15 at 17:52
  • @JamieVu In that case, I wouldn't even keep `tax` and `tip` around as member variables, since they are dependent on `cost`. I would make helper functions `get_tax` and `get_tip` that can compute this. See my edit for an example – Cory Kramer Jun 03 '15 at 18:29
1

Another nice feature of Python is the built-in @property decorator, which helps to replace setters and getters from Java. The @property decorator allows you to create early versions of a class using property attributes (i.e., self.tax). If it later becomes necessary to perform calculations on the attribute or move it to a calculated attribute, the @property attribute allows this to be done transparently to any code that depends on the existing implementation. See example, below.

TAX_RATE = 0.0875
TIP_RATE = 0.15

class CostCalculator(object):
    def __init__(self, item='', cost=0):
        self.item = item
        self.cost = cost


    @property
    def tax(self):
        """Tax amount for item."""

        return self.cost * TAX_RATE


    @property
    def tip(self):
        """Tip amount for item."""

        return self.cost * TIP_RATE



if __name__ == '__main__':
    item = CostCalculator('Steak Dinner', 21.50)
    assert item.tax == 1.8812499999999999
    assert item.tip == 3.225
Deacon
  • 3,615
  • 2
  • 31
  • 52
-1

It is like CoryKramer said, python doesn't encourage use of private staff and you don't need setters and getters. But if you still want in, this might help:

class CostCalculator:
    __item = ""
    __cost_of_item = 0.0
    __tax = 0.0
    __tip = 0.0

    def set_item(self, item):
        self.__item = item

    def get_name(self):
        return self.__item

    def set_cost_of_item(self, cost_of_item):
        self.__cost_of_item = float(cost_of_item)

    def get_cost_of_item(self):
        return self.__cost_of_item

    def get_tax(self):
        self.__tax = self.__cost_of_item * 0.0875
        return self.__tax

    def get_tip(self):
        self.__tip = self.__cost_of_item * 0.15
        return self.__tip


item = ""
cost = 0.0
totalTip = 0.0
totalTax = 0.0
overallTotal = 0.0
subtotal = 0.0

print("Enter the name of 3 items and their respective costs to get the total vaalue of your meal")

ls = [CostCalculator(), CostCalculator(), CostCalculator()]

for entry in ls:
    print "Enter the name of your item:"
    item = raw_input()
    entry.set_item(item)
    print("How much is " + entry.get_name() + "?")
    cost = raw_input()
    entry.set_cost_of_item(cost)

subtotal = sum([x.get_cost_of_item() for x in ls])
totalTip = sum([x.get_tip() for x in ls])
totalTax = sum([x.get_tax() for x in ls])
corrado
  • 23
  • 1
  • 8
  • This is going to be a problem. `__item`, etc should not be set in the class definition itself or they will be shared among all instances of `CostCalculator`. If you make two instances of that class, changing `__item` in one will affect the other. – Cory Kramer Jun 03 '15 at 12:12
  • Also the member variable names should not start with double-underscore `__` according to PEP8, that is reserved for certain functions and they will become mangled https://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python – Cory Kramer Jun 03 '15 at 12:13
  • I know about double-underscore, just rewrote original class, if @Jamie Vu wants to have it like it is. But I disagree about affecting `__item` – corrado Jun 03 '15 at 12:24
  • Regarding affecting `__item`, that was a bad example as their members are `str` and `int` which are immutable, but if they had members which were mutable, such as a `list`, this would indeed produce undesired behavior. https://stackoverflow.com/questions/1680528/how-do-i-avoid-having-python-class-data-shared-among-instances – Cory Kramer Jun 03 '15 at 12:28
  • Totally agree. But it doesn't affect it here, so i left it. – corrado Jun 03 '15 at 12:34